是否可以以某种方式预加载应用程序上的图像开始?就像我的抽屉里有背景图像,但是第一次打开抽屉时,我可以看到图像闪烁,就像从资产中取出然后显示一样,一旦我第一次看到它,就会给我带来不好的体验抽屉的开口行为正常,因为它已被缓存。我想在应用程序加载时预取它,所以没有这种效果。
答案 0 :(得分:14)
在构建抽屉之前,使用precacheImage
函数开始加载图像。例如,在包含抽屉的小部件中:
class MyWidgetState extends State<MyWidget> {
@override
void initState() {
// adjust the provider based on the image type
precacheImage(new AssetImage('...'));
super.initState();
}
}
答案 1 :(得分:6)
关于这个主题有一篇很好的文章:https://alex.domenici.net/archive/preload-images-in-a-stateful-widget-on-flutter
它应该看起来像这样
class _SampleWidgetState extends State<SampleWidget> {
Image image1;
Image image2;
Image image3;
Image image4;
@override
void initState() {
super.initState();
image1 = Image.asset("assets/image1.png");
image2 = Image.asset("assets/image2.png");
image3 = Image.asset("assets/image3.png");
image4 = Image.asset("assets/image4.png");
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
precacheImage(image1.image, context);
precacheImage(image2.image, context);
precacheImage(image3.image, context);
precacheImage(image4.image, context);
}
@override
Widget build(BuildContext context) {
return Container(
child: Stack(
children: <Widget>[
image1,
image2,
image3,
image4,
],
),
);
}
}
答案 2 :(得分:4)
precacheImage()
函数(在大多数答案中使用)返回一个Future
,对于某些用例场景,它确实非常有用。例如,在我的应用程序中,我需要加载外部图像,并且像其他所有人一样,不想经历闪烁。所以我最终得到了这样的东西:
// show some sort of loading indicator
...
precacheImage(
NetworkImage(),
context,
).then((_) {
// replace the loading indicator and show the image
// (may be with some soothing fade in effect etc.)
...
});
请注意,在上面的示例中,我想说明如何Future
被潜在地使用。评论只是为了帮助表达想法。实际的实现必须以Fluttery
的方式完成。
答案 3 :(得分:2)
要摆脱“闪烁”,您可以简单地将FadeInImage
class与transparent_image
结合使用,它们会褪色而不是立即出现。就您而言,用法如下:
// you need to add transparent_image to your pubspec and import it
// as it is required to have the actual image fade in from nothing
import 'package:transparent_image/transparent_image.dart';
import 'package:flutter/material.dart';
...
FadeInImage(
placeholder: MemoryImage(kTransparentImage),
image: AssetImage('image.png'),
)
答案 4 :(得分:1)
我遇到以下问题:图像需要一些空间。因此,加载后,它将UI推低,这对UX不利。我决定创建一个生成器以显示一个空的(或正在加载的)容器,直到图像加载完毕,然后再显示我的UI。
看起来像precacheImage
返回的将来已解决。对我而言,最棘手的部分是FutureBuilder
和snapshot.hasData
,它们始终是false
,因为null
解决了未来。因此,我添加了将来的转换以修复snapshot.hasData
:
precacheImage(this.widget.imageProvider, context).then((value) => true)
我不确定是否可以多次调用precacheImage
,所以我决定将其包装到StatefulWidget
中。
您可以检查最终的构建器here
通过以下方式使用构建器:
return PreloadingImageBuilder(
imageProvider: AssetImage("assets/images/logo-main.png"),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Scaffold(
...
);
} else {
return Container();
}
},
);
答案 5 :(得分:0)
我在使用initState内部的precacheImage()的上层解决方案时遇到了问题。下面的代码解决了它们。另外请注意,在调试模式下可能看不到预期的结果,而在发布模式下则看不到预期的结果。
Image myImage;
@override
void initState() {
super.initState();
myImage= Image.asset(path);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
precacheImage(myImage.image, context);
}