【发布时间】:2019-07-14 20:37:00
【问题描述】:
我正在构建一个 Flutter 应用,但遇到了 ListView.builder 的问题。
我当前的设置是一个包含对象列表的 StreamBuilder。每个对象都绑定到 ListView.builder 中的一项。
我的问题是,当添加新项目并调用 StreamController$add() 时,列表会自动滚动到列表顶部。我正在寻找要维护的列表位置,并由用户(或按钮)滚动到顶部。
我已在列表项中添加了有助于解决其他问题但没有解决此问题的键。我还在列表视图中添加了一个 PageStorageKey,但这没有帮助。我也有一个滚动控制器,但无法弄清楚如何处理这种行为。
如果需要,我可以提供代码示例。提前致谢!
相关代码:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: albatrossDarkTheme,
home: TimelinePage(),
);
}
}
class TimelinePage extends StatefulWidget {
TimelinePage({Key key}) : super(key: key);
@override
_TimelinePageState createState() => _TimelinePageState();
}
class _TimelinePageState extends State<TimelinePage> {
AlbatrossClient _client;
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();
PageStorageKey _pageKey = PageStorageKey(8);
TimelineDatabase _database = TimelineDatabase();
StreamController<List<Tweet>> _controller;
ScrollController _scrollController;
Stream<List<Tweet>> _getStream() {
return _controller.stream;
}
Future<void> _refreshTimeline() async {
_client.refreshTimeline().then((result) {
if (result == 0)
_database.getTimeline(false).then((update) {
_controller.add(update);
});
});
}
_updateTimeline() async {
_database.getTimeline(false).then((update) => _controller.add(update));
}
@override
void initState() {
_client = AlbatrossClient();
_controller = StreamController<List<Tweet>>();
_scrollController = ScrollController(keepScrollOffset: true);
_database.getTimeline(false).then((saved) => _controller.add(saved));
_client.refreshTimeline().then((result) {
if (result == 0)
_database.getTimeline(false).then((update) {
_controller.add(update);
});
});
super.initState();
}
@override
void dispose() {
_controller.close();
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: SearchAppbar(() {
_scaffoldKey.currentState.openDrawer();
}),
drawer: Drawer(
child: DrawerMain.getDrawer(context, _client.getProfile()),
),
body: Container(
child: RefreshIndicator(
onRefresh: _refreshTimeline,
child: StreamBuilder<List<Tweet>>(
stream: _getStream(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
key: _pageKey,
controller: _scrollController,
itemCount:
snapshot.data != null ? snapshot.data.length : 0,
itemBuilder: (context, index) {
return RowTweet(
tweet: snapshot.data[index],
update: _updateTimeline,
animate: true);
},
);
} else
return Container(
alignment: Alignment(0.0, 0.0),
child: CircularProgressIndicator(),
);
},
))),
floatingActionButton: FloatingActionButton(
tooltip: 'Compose Tweet',
onPressed: _composeTweet,
foregroundColor: Colors.white,
child: Image.asset(
"icons/ic_tweet_web.webp",
width: 38,
height: 38,
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
这是我的新尝试:
return Scaffold(
key: _scaffoldKey,
appBar: SearchAppbar(() {
_scaffoldKey.currentState.openDrawer();
}),
drawer: Drawer(
child: DrawerMain.getDrawer(context, _client.getProfile()),
),
body: Container(
child: RefreshIndicator(
onRefresh: _refreshTimeline,
child: _timeline.isNotEmpty
? ListView.builder(
key: _pageKey,
controller: _scrollController,
itemCount: _timeline.length,
itemBuilder: (context, index) {
return RowTweet(
tweet: _timeline[index],
update: _updateTimeline,
animate: true);
})
: Container(
alignment: Alignment(0, 0),
child: CircularProgressIndicator(),
))),
floatingActionButton: FloatingActionButton(
tooltip: 'Compose Tweet',
onPressed: _composeTweet,
foregroundColor: Colors.white,
child: Image.asset(
"icons/ic_tweet_web.webp",
width: 38,
height: 38,
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
【问题讨论】: