122 lines
3.7 KiB
Dart
122 lines
3.7 KiB
Dart
import 'dart:ui';
|
||
|
||
import 'package:cached_network_image/cached_network_image.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:hgdj/assets_tool/images.dart';
|
||
import 'package:hgdj/hj_utils/screen.dart';
|
||
import 'package:hgdj/tools_base/cache/image_cache_manager.dart';
|
||
|
||
class NetworkImageLoader extends StatelessWidget {
|
||
final double borderRadius;
|
||
final BorderRadius? imgBorderRadius;
|
||
final String? imageUrl;
|
||
final double? width;
|
||
final double? height;
|
||
final BoxFit fit;
|
||
final double? placeHolderH;
|
||
final double? placeHolderW;
|
||
final bool blur; //高斯模糊
|
||
final Alignment alignment;
|
||
final bool encrypt; //是否需要加密
|
||
final Widget? placeHolderWidget;
|
||
final int? loadWidth; // 服务端根据宽度等比例压缩
|
||
final bool? isResizeImage; //是否需要根据组件大小压缩
|
||
|
||
const NetworkImageLoader({
|
||
super.key,
|
||
required this.imageUrl,
|
||
this.borderRadius = 8,
|
||
this.imgBorderRadius,
|
||
this.height,
|
||
this.fit = BoxFit.cover,
|
||
this.width,
|
||
this.blur = false,
|
||
this.placeHolderH,
|
||
this.placeHolderW,
|
||
this.alignment = Alignment.center,
|
||
this.encrypt = true,
|
||
this.placeHolderWidget,
|
||
this.loadWidth,
|
||
this.isResizeImage = true,
|
||
});
|
||
|
||
bool get isGif => imageUrl?.contains(".gif") ?? false;
|
||
String get realImgUrl {
|
||
if (imageUrl == null) return "";
|
||
return imageUrl!;
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return LayoutBuilder(builder: (context, cons) {
|
||
final imageWidget = CachedNetworkImage(
|
||
alignment: alignment,
|
||
imageUrl: realImgUrl,
|
||
width: width,
|
||
height: height,
|
||
fit: fit,
|
||
memCacheWidth: memCacheWidth(cons),
|
||
// 默认 FilterQuality.low 用廉价 bilinear,iOS retina(dpr=3) 上肉眼可见的模糊
|
||
// medium 是质量/性能平衡点,high 会卡列表滚动
|
||
filterQuality: FilterQuality.medium,
|
||
cacheManager: encrypt ? ImageCacheManager() : null,
|
||
placeholder: (context, url) => _buildPlaceHolder(),
|
||
errorWidget: (context, url, err) => _buildPlaceHolder(),
|
||
fadeInCurve: Curves.linear,
|
||
fadeOutCurve: Curves.linear,
|
||
);
|
||
final clip = borderRadius == 0
|
||
? imageWidget
|
||
: ClipRRect(
|
||
borderRadius:
|
||
imgBorderRadius ?? BorderRadius.circular(borderRadius),
|
||
child: imageWidget,
|
||
);
|
||
final backdrop = blur
|
||
? ClipRRect(
|
||
borderRadius:
|
||
imgBorderRadius ?? BorderRadius.circular(borderRadius),
|
||
child: ImageFiltered(
|
||
imageFilter: ImageFilter.blur(
|
||
sigmaX: 5,
|
||
sigmaY: 5,
|
||
),
|
||
child: clip,
|
||
),
|
||
)
|
||
: clip;
|
||
return backdrop;
|
||
});
|
||
}
|
||
|
||
//resize的宽度
|
||
int? memCacheWidth(BoxConstraints cons) {
|
||
final dpr = screen.devicePixelRatio;
|
||
if (isResizeImage == true) {
|
||
//约束无限时用屏幕宽兜底,避免退化成按原图解码(图片过载)
|
||
final w = (cons.maxWidth == double.infinity || cons.maxWidth.isNaN)
|
||
? screen.screenWidth
|
||
: cons.maxWidth;
|
||
return (w * dpr).toInt();
|
||
} else {
|
||
return loadWidth != null
|
||
? loadWidth!
|
||
: (screen.screenWidth * dpr).toInt();
|
||
}
|
||
}
|
||
|
||
_buildPlaceHolder() {
|
||
if (placeHolderWidget != null) return placeHolderWidget;
|
||
return Container(
|
||
padding: EdgeInsets.symmetric(horizontal: 4),
|
||
decoration: BoxDecoration(color: Color(0xff343434)),
|
||
alignment: Alignment.center,
|
||
child: Image.asset(
|
||
'place_holder_logo.webp'.commonImgPath,
|
||
width: placeHolderW ?? 136,
|
||
height: placeHolderW ?? 96,
|
||
),
|
||
);
|
||
}
|
||
}
|