背景:目前,我正在使用远程服务器图像查看器,我使用 FutureBuilder
来显示图像和图像之间的切换,它可以正常工作,但是在切换图像之间会在几毫秒内显示空白屏幕。
问题:我想在 FutureBuilder
加载时保留旧的图像小部件,或者在旧图像小部件上显示加载圆圈,而不是在加载时显示新的空白加载页面。或者其他没有 Futurebuilder
的解决方案(例如可滚动小部件)?
框架代码:
class Viewer extends StatefulWidget {
Viewer(this.filename, {Key key}) : super(key: key);
final String filename;
@override
_ViewerState createState() {
return _ViewerState();
}
}
class _ViewerState extends State<Viewer> {
int _index = 0;
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Container(
child: showImage(context, _index),
),
onPanDown: (DragDownDetails e) {
//it will change _index to move to next image when tap down
_index+=1;
}
);
}
Widget showImage(BuildContext context, int index) {
return FutureBuilder<SmbHalfResult>(
future: () async {
//load image from remote server or from memory cache,the SmbHalfResult contain a Uint8List image.
return SmbHalfResult();
}(),
builder: (BuildContext context, AsyncSnapshot<SmbHalfResult> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return Text("Error: ${snapshot.error}");
} else {
//show image.
return Image.memory(snapshot.data.result.content);
}
} else {
// show loading circle,it will new a blank page,but I even want to display old image other than a blank page when loading.
return Center(child: CircularProgressIndicator());
}
},
);
}
}
答案 0 :(得分:1)
最后我得到PreloadPageView,参数为physics: new NeverScrollableScrollPhysics()
和preloadPageController.jumpToPage(index)
,它完全满足了我的需求,没有任何闪烁。
GestureDetector(
child: Container(
child: PreloadPageView.builder(
preloadPagesCount: 5,
itemBuilder: (BuildContext context, int index) =>
FutureImage(index, widget.filename),
controller: preloadPageController,
physics: new NeverScrollableScrollPhysics(),
)),
onPanDown: (DragDownDetails e) {
Offset globalPosition = e.globalPosition;
RenderBox findRenderObject = context.findRenderObject();
Size size = findRenderObject.size;
Area area = getArea(globalPosition, size);
if (area == Area.lef) {
index--;
preloadPageController.jumpToPage(index);
} else if (area == Area.right) {
index++;
preloadPageController.jumpToPage(index);
}
},
)
答案 1 :(得分:0)
Provider将是一个很好的解决方案。
在您的窗口小部件树中,查看器窗口小部件上方的窗口小部件必须看起来像这样
ChangeNotifierProvider<SmbHalfResult>(
create: (context) {
var smbHalfResult = SmbHalfResult();
smbHalfResult.fetchImage(0);
return smbHalfResult;
},
child: Viewer();
)
SmbHalfResult 类的外观应与此类似
class SmbHalfResult extends ChangeNotifier{
Uint8List image;
void fetchImage(int index) async {
this.image = await downloadImage(index);
notifyListeners();
}
}
最后您的实际用户界面必须是这样
class _ViewerState extends State<Viewer> {
int _index = 0;
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Container(
child: Consumer<SmbHalfResult>(
builder: (context, model) {
if(model.image != null) return Image.memory(model.image);
return CircularProgressIndicator();
}
),
),
onPanDown: (DragDownDetails e) {
Provider.of<SmbHalfResult>(context, listen: false).fetchImage();
}
);
}
}