问题描述
如何使frameBuilder和loadingBuilder一起工作?
“ loadingBuilder”始终有效(无论是否带有frameBuilder),但“ frameBuilder”仅在单独使用时才有效(即,将loadBuilder注释掉)。
该文档讨论了如何使用loadBuilder“链接” frameBuilder,这并不是内部发生的事情还是我们必须考虑的事情。
Image.network(_imageUrl,height: 400,width: MediaQuery.of(context).size.width,fit: BoxFit.fitWidth,frameBuilder: (BuildContext context,Widget child,int frame,bool wasSynchronouslyLoaded) {
if (wasSynchronouslyLoaded) return child;
return AnimatedOpacity(
opacity: frame == null ? 0 : 1,duration: Duration(seconds: 5),curve: Curves.eaSEOut,child: child,);
},loadingBuilder: (BuildContext context,ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null ?
loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes :
null,),errorBuilder: (BuildContext context,Object exception,StackTrace stackTrace) {
return Text('Failed to load image');
},
编辑:
确切发生的事情:
情况1:当loadBuilder为ALONE时,显示CircularProgressIndicator,并且加载过程完成,然后指示器消失,并且显示的加载图像没有褪色。 (完美)
情况2:当frameBuilder为ALONE时,图像需要花费一定的时间加载(当然有指示符),然后加载的图像将按预期逐渐显示。 (完美)
情况3:同时启用frameBuilder和loadingBuilder时,情况1完全发生,而图像没有任何褪色。 (错)
预期的行为:
正在加载过程中会显示指示器,然后消失,并且图像会显示出褪色效果。
我需要修复此代码并找出问题出在哪里。
解决方法
似乎“链接”是自动发生的,但您仍然需要考虑它们链接在一起的结果。
它们不能一起工作的问题是因为当frame == null
时,显示的是CircularProgressIndicator; AnimatedOpacity
仅在 frame 不为空时显示,因此其不透明度始终为 1,这意味着我们失去了淡出效果。
解决办法是在加载时设置opticity为0,加载时设置为1。
以下代码应该可以工作:
/// Flutter code sample for Image.frameBuilder
// The following sample demonstrates how to use this builder to implement an
// image that fades in once it's been loaded.
//
// This sample contains a limited subset of the functionality that the
// [FadeInImage] widget provides out of the box.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,home: MyStatefulWidget(),);
}
}
bool loading = false;
/// This is the stateless widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
@override
MyStatefulWigdetState createState() => MyStatefulWigdetState();
}
class MyStatefulWigdetState extends State<MyStatefulWidget> {
@override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,border: Border.all(),borderRadius: BorderRadius.circular(20),),child: Image.network(
'https://flutter.github.io/assets-for-api-docs/assets/widgets/puffin.jpg',frameBuilder: (BuildContext context,Widget child,int frame,bool wasSynchronouslyLoaded) {
if (wasSynchronouslyLoaded) {
return child;
}
return AnimatedOpacity(
child: child,opacity: loading ? 0 : 1,duration: const Duration(seconds: 3),curve: Curves.easeOut,);
},loadingBuilder: (BuildContext context,ImageChunkEvent loadingProgress) {
if (loadingProgress == null) {
// The child (AnimatedOpacity) is build with loading == true,and then the setState will change loading to false,which trigger the animation
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() => loading = false);
});
return child;
}
loading = true;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes
: null,);
}
}