我目前正在开发一个阅读器并使用PageView
来滑动图像页面。如何使下一页预加载,以便用户可以滑动到下一页而无需等待页面加载?我不想先下载所有页面,因为它会加载服务器并冻结我的应用程序。我只想在用户浏览当前页面时下载一两页。
以下是我的代码的摘录。
PageController _controller;
ZoomableImage nextPage;
Widget _loadImage(int index) {
ImageProvider image = new CachedNetworkImageProvider("https://example.com/${bookId}/${index+1}.jpg}");
ZoomableImage zoomed = new ZoomableImage(
image,
placeholder: new Center(
child: CupertinoActivityIndicator(),
),
);
return zoomed;
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Container(
child: PageView.builder(
physics: new AlwaysScrollableScrollPhysics(),
controller: _controller,
itemCount: book.numPages,
itemBuilder: (BuildContext context, int index) {
return index == 0 || index == 1 ? _loadImage(index) : nextPage;
},
onPageChanged: (int index) {
nextPage = _loadImage(index+1);
},
),
),
);
}
谢谢!
答案 0 :(得分:6)
我最终使用包cached_network_image中的FutureBuilder
和CachedNetworkImageProvider
来预取所有图片。这是我的解决方案:
PageController _controller;
ZoomableImage currPage, nextPage;
Future<List<CachedNetworkImageProvider>> _loadAllImages(Book book) async {
List<CachedNetworkImageProvider> cachedImages = [];
for(int i=0;i<book.numPages;i++) {
var configuration = createLocalImageConfiguration(context);
cachedImages.add(new CachedNetworkImageProvider("https://example.com/${bookId}/${index+1}.jpg}")..resolve(configuration));
}
return cachedImages;
}
FutureBuilder<List<CachedNetworkImageProvider>> _futurePages(Book book) {
return new FutureBuilder(
future: _loadAllImages(book),
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.hasData) {
return new Container(
child: PageView.builder(
physics: new AlwaysScrollableScrollPhysics(),
controller: _controller,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
ImageProvider image = snapshot.data[index];
return new ZoomableImage(
image,
placeholder: new Center(
child: CupertinoActivityIndicator(),
),
);
},
onPageChanged: (int index) {},
),
);
} else if(!snapshot.hasData) return new Center(child: CupertinoActivityIndicator());
},
);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: _futurePages(widget.book),
);
}
答案 1 :(得分:6)
简单!只需设置allowImplicitScrolling: true, // in PageView.builder
答案 2 :(得分:0)
正如在cached_network_image
库之前提到的人那样,这是一个解决方案,但并不适合我的情况。我的项目中有整页PageView
(适合宽度和高度),当我尝试上一个代码时,我的PageView
将首先显示空白页,然后显示图像。
我开始阅读PageView
源代码,最后我找到了一种适合我的个人需求的方法。基本思想是更改PageView
源代码的cacheExtent
这是关于cacheExtent的工作方式的描述:
视口在可见区域之前和之后都有一个区域,用于缓存当用户滚动时将变得可见的项目。
即使尚未(在屏幕上)看到属于该高速缓存区域的项目,也将对其进行布局。 cacheExtent描述了缓存区域在视口的前缘和后缘之前延伸了多少像素。
直接更改flutter的源代码是一个坏主意,因此我创建了a new PrelodPageView widget并在需要预加载功能的特定位置使用它。
编辑:
我添加了另外一个参数preloadPagesCount
用于自动预加载多个页面。