Flutter项目中ListView的滚动不流畅
Posted
技术标签:
【中文标题】Flutter项目中ListView的滚动不流畅【英文标题】:ListView's scroll is not smooth in Flutter project 【发布时间】:2018-12-18 09:15:06 【问题描述】:我刚开始学习 Flutter。我遇到了一个大问题,那就是在复杂列表中滚动不好。假设我们的 ListView 中有 5 种不同的项目类型,并且某些项目类型必须显示图像并且它是无限滚动的。我阅读了很多关于 Flutter 的 ListView 的文章和帖子,我看到的所有内容都是带有文本的简单列表。怎样才能平滑滚动?
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return new MaterialApp(
title: 'Startup Name Generator',
home: new RandomWords(),
);
class RandomWords extends StatefulWidget
@override
RandomWordsState createState() => new RandomWordsState();
class RandomWordsState extends State<RandomWords>
final List<WordPair> _suggestions = <WordPair>[];
final TextStyle _biggerFont = const TextStyle(fontSize: 18.0);
List<int> items = List.generate(10, (i) => i);
ScrollController _scrollController = new ScrollController();
bool isPerformingRequest = false;
@override
void initState()
super.initState();
_scrollController.addListener(()
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent)
_getMoreData();
);
@override
void dispose()
_scrollController.dispose();
super.dispose();
_getMoreData() async
if (!isPerformingRequest)
setState(() => isPerformingRequest = true);
List<int> newEntries = await fakeRequest(
items.length, items.length + 10); //returns empty list
if (newEntries.isEmpty)
double edge = 50.0;
double offsetFromBottom = _scrollController.position.maxScrollExtent -
_scrollController.position.pixels;
if (offsetFromBottom < edge)
_scrollController.animateTo(
_scrollController.offset - (edge - offsetFromBottom),
duration: new Duration(milliseconds: 500),
curve: Curves.easeOut);
setState(()
items.addAll(newEntries);
isPerformingRequest = false;
);
Future<List<int>> fakeRequest(int from, int to) async
return Future.delayed(Duration(seconds: 1), ()
return List.generate(to - from, (i) => i + from);
);
Widget _buildProgressIndicator()
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Center(
child: new Opacity(
opacity: isPerformingRequest ? 1.0 : 0.0,
child: new CircularProgressIndicator(),
),
),
);
@override
Widget build(BuildContext context)
return new Scaffold(
appBar: AppBar(
title: Text(""),
),
body: ListView.builder(
itemCount: items.length + 1,
itemBuilder: (context, index)
if (index == items.length)
return _buildProgressIndicator();
else
if (index % 5 == 0)
return Image.network(
"http://sanctum-inle-resort.com/wp-content/uploads/2015/11/Sanctum_Inl_Resort_Myanmar_Flowers_Frangipani.jpg",
height: 200.0,
);
else if (index.isOdd)
return Container(
padding: EdgeInsets.all(16.0),
child: ListTile(
leading: Icon(Icons.person),
title: Text('This is title'),
),
);
else
return ListTile(title: new Text("Number $index"));
,
controller: _scrollController,
),
);
【问题讨论】:
只是在开发模式下变慢还是在发布版本时变慢? @JoranDob 我没有在发布版本中进行测试,但它不应该在调试版本中发生。 【参考方案1】:我认为问题在于,当用户已经到列表末尾并且没有更多项目时,您请求异步数据,然后它正在执行加载数据的虚假请求,但这需要一秒钟所以这就是为什么它令人震惊的原因
_scrollController.position.maxScrollExtent
这将获取滚动列表的末尾,因此它会在用户位于列表末尾的位置开始加载,您可以使用偏移量更改此值,以便更早开始加载
要对此进行测试,您可以尝试更改:
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent)
收件人:
if (_scrollController.position.pixels ==
(_scrollController.position.maxScrollExtent - 50))
还有
Future<List<int>> fakeRequest(int from, int to) async
return Future.delayed(Duration(seconds: 1), ()
return List.generate(to - from, (i) => i + from);
);
收件人:
List<int> fakeRequest(int from, int to)
return List.generate(to - from, (i) => i + from);
【讨论】:
其实平滑滚动问题不是基于它的。假设我们已经有 100 个项目,包括图像项目。在这种情况下,滚动将不再流畅。以上是关于Flutter项目中ListView的滚动不流畅的主要内容,如果未能解决你的问题,请参考以下文章
在 Flutter 中使用 InheritedWidget 时 ListView 失去滚动位置
堆栈中 ListView 顶部的 GestureDetector 阻止滚动 - Flutter Web