♻️ Better image loading animation and more commonly used blurhash
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_blurhash/flutter_blurhash.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class UniversalImage extends StatelessWidget {
|
||||
class UniversalImage extends HookWidget {
|
||||
final String uri;
|
||||
final String? blurHash;
|
||||
final BoxFit fit;
|
||||
@@ -27,6 +28,7 @@ class UniversalImage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final loaded = useState(false);
|
||||
final isSvgImage = isSvg || uri.toLowerCase().endsWith('.svg');
|
||||
|
||||
if (isSvgImage) {
|
||||
@@ -35,9 +37,8 @@ class UniversalImage extends StatelessWidget {
|
||||
fit: fit,
|
||||
width: width,
|
||||
height: height,
|
||||
placeholderBuilder:
|
||||
(BuildContext context) =>
|
||||
Center(child: CircularProgressIndicator()),
|
||||
placeholderBuilder: (BuildContext context) =>
|
||||
Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -46,8 +47,9 @@ class UniversalImage extends StatelessWidget {
|
||||
if (width != null && height != null && !noCacheOptimization) {
|
||||
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
|
||||
cacheWidth = width != null ? (width! * devicePixelRatio).round() : null;
|
||||
cacheHeight =
|
||||
height != null ? (height! * devicePixelRatio).round() : null;
|
||||
cacheHeight = height != null
|
||||
? (height! * devicePixelRatio).round()
|
||||
: null;
|
||||
}
|
||||
|
||||
return SizedBox(
|
||||
@@ -66,21 +68,72 @@ class UniversalImage extends StatelessWidget {
|
||||
memCacheWidth: cacheWidth,
|
||||
progressIndicatorBuilder: (context, url, progress) {
|
||||
return Center(
|
||||
child: CircularProgressIndicator(value: progress.progress),
|
||||
child: AnimatedCircularProgressIndicator(
|
||||
value: progress.progress,
|
||||
color: Colors.white.withOpacity(0.5),
|
||||
),
|
||||
);
|
||||
},
|
||||
errorWidget:
|
||||
(context, url, error) =>
|
||||
useFallbackImage
|
||||
? Image.asset(
|
||||
'assets/images/media-offline.jpg',
|
||||
fit: BoxFit.cover,
|
||||
key: Key('image-broke-$uri'),
|
||||
)
|
||||
: SizedBox.shrink(),
|
||||
imageBuilder: (context, imageProvider) {
|
||||
Future(() => loaded.value = true);
|
||||
return AnimatedOpacity(
|
||||
opacity: loaded.value ? 1.0 : 0.0,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: Image(
|
||||
image: imageProvider,
|
||||
fit: fit,
|
||||
width: width,
|
||||
height: height,
|
||||
),
|
||||
);
|
||||
},
|
||||
errorWidget: (context, url, error) => useFallbackImage
|
||||
? Image.asset(
|
||||
'assets/images/media-offline.jpg',
|
||||
fit: BoxFit.cover,
|
||||
key: Key('image-broke-$uri'),
|
||||
)
|
||||
: SizedBox.shrink(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AnimatedCircularProgressIndicator extends HookWidget {
|
||||
final double? value;
|
||||
final Color? color;
|
||||
final double strokeWidth;
|
||||
final Duration duration;
|
||||
|
||||
const AnimatedCircularProgressIndicator({
|
||||
super.key,
|
||||
this.value,
|
||||
this.color,
|
||||
this.strokeWidth = 4.0,
|
||||
this.duration = const Duration(milliseconds: 200),
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final animationController = useAnimationController(duration: duration);
|
||||
final animation = useAnimation(
|
||||
Tween<double>(begin: 0.0, end: value ?? 0.0).animate(
|
||||
CurvedAnimation(parent: animationController, curve: Curves.linear),
|
||||
),
|
||||
);
|
||||
|
||||
useEffect(() {
|
||||
animationController.animateTo(value ?? 0.0);
|
||||
return null;
|
||||
}, [value]);
|
||||
|
||||
return CircularProgressIndicator(
|
||||
value: animation,
|
||||
color: color,
|
||||
strokeWidth: strokeWidth,
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user