Фликеры hero в связке с cached_network_image
У меня есть список спикеров, при нажатии на любой из элементов я перехожу на страницу с деталями об этом спикере. При переходе маленький аватар превращается в большой, с помощью Hero
виджета. Данные аватары - это CachedNetworkImage
. В нормальном состоянии (когда изображение успешно загружается из сети) все работает отлично. Но, если смоделировать ситуацию, когда изображение не загружается, или возникает другая ошибка, то errorWidget
у CachedNetworkImage
, начинает мерцать при переходе.
Гифка как это сейчас выглядит: https://imgur.com/a/E7ogQhV
(Извините за неудобную ссылку, просто не могу загрузить гифку через сайт почему-то)
Я пробовал зафетчить картинку самостоятельно, и в зависимости от кода ответа, выбирать: отображать виджет для плейсхолдера или CachedNetworkImage
, но, возникло другое поведение, при котором, в случае уже успешной загрузки изображения, отображался в начале виджет плейсхолдер
class NetworkImageWidget extends StatefulWidget {
const NetworkImageWidget({
super.key,
required this.imageUrl,
this.width,
this.height,
this.fit = BoxFit.cover,
});
final String? imageUrl;
final double? width;
final double? height;
final BoxFit? fit;
@override
State<NetworkImageWidget> createState() => _NetworkImageWidgetState();
}
class _NetworkImageWidgetState extends State<NetworkImageWidget> {
@override
void initState() {
super.initState();
// fetchImage();
}
bool isImageReal = false;
bool get _isImageInvalid =>
(widget.imageUrl?.isEmpty ?? true) ||
(!widget.imageUrl!.startsWith('http') || !isImageReal);
// Future<void> fetchImage() async {
//
// final response = await http.get(Uri.parse(widget.imageUrl!));
// if (response.statusCode == 200) {
// setState(() => isImageReal = true);
// } else {
// setState(() => isImageReal = false);
// }
// }
@override
Widget build(BuildContext context) {
// if (_isImageInvalid) {
// return _PlaceHolderImageWidget(
// width: widget.width,
// height: widget.height,
// fit: widget.fit,
// );
// }
return CachedNetworkImage(
imageUrl: widget.imageUrl!,
width: widget.width,
height: widget.height,
fit: widget.fit,
// cacheManager: CacheManager,
placeholder: (_, __) => _CircleImageShimmer(
width: widget.width,
height: widget.height,
),
errorWidget: (_, __, ___) => _PlaceHolderImageWidget(
width: widget.width,
height: widget.height,
fit: widget.fit,
),
);
}
}
class _CircleImageShimmer extends StatelessWidget {
const _CircleImageShimmer({
required this.width,
required this.height,
});
final double? width;
final double? height;
@override
Widget build(BuildContext context) {
final appColor = AppColorScheme.of(context);
return Shimmer.fromColors(
baseColor: appColor.shimmer,
highlightColor: appColor.shimmerHighlight,
child: Container(
color: Colors.white,
width: width,
height: height,
),
);
}
}
class _PlaceHolderImageWidget extends StatelessWidget {
const _PlaceHolderImageWidget({this.width, this.height, this.fit});
final double? width;
final double? height;
final BoxFit? fit;
@override
Widget build(BuildContext context) => Image.asset(
Images.largePlaceholder,
width: width,
height: height,
fit: fit,
);
}
Это код моего виджета для CachedNetworkImage
, который я затем оборачиваю в Hero
виджет