gpt4 book ai didi

flutter - 更改选项卡时如何获取Flutter ScrollController以保存ListView.builder()的位置?

转载 作者:行者123 更新时间:2023-12-03 02:50:26 26 4
gpt4 key购买 nike

我用两个选项卡制作了一个简单的示例,每个选项卡都包含一个ListView构建器。我的目标是能够在第一个 ListView 中滚动,切换到第二个选项卡,然后切换回第一个选项卡,并从之前看到相同的滚动位置。

我曾尝试将Keys添加到每个 ListView 中,但这只是一个猜测,因为我不完全了解key。那没有帮助。

为什么ScrollControllers不保存滚动位置?

这是main.dart示例:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}

class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
ScrollController controllerA = ScrollController(keepScrollOffset: true);
ScrollController controllerB = ScrollController(keepScrollOffset: true);
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: <Widget>[
Text('controllerA'),
Text('controllerB'),
],
),
),
body: TabBarView(
children: <Widget>[
ListView.builder(
controller: controllerA,
itemCount: 2000,
itemBuilder: (context, i) {
return ListTile(
title: Text(
i.toString(),
textScaleFactor: 1.5,
style: TextStyle(color: Colors.blue),
));
}),
ListView.builder(
controller: controllerB,
itemCount: 2000,
itemBuilder: (context, i) {
return Card(
child: ListTile(
title: Text(i.toString()),
),
);
}),
],
),
),
);
}
}

这是我想要的骇人但实用的示例。但是,这感觉不像是正确的方法,因为它每帧都重建了两个 Controller 。
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}

class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
double offsetA = 0.0;
double offsetB = 0.0;

@override
Widget build(BuildContext context) {
ScrollController statelessControllerA =
ScrollController(initialScrollOffset: offsetA);
statelessControllerA.addListener(() {
setState(() {
offsetA = statelessControllerA.offset;
});
});

ScrollController statelessControllerB =
ScrollController(initialScrollOffset: offsetB);
statelessControllerB.addListener(() {
setState(() {
offsetB = statelessControllerB.offset;
});
});

return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: <Widget>[
Text('controllerA'),
Text('controllerB'),
],
),
),
body: TabBarView(
children: <Widget>[
ListView.builder(
controller: statelessControllerA,
itemCount: 2000,
itemBuilder: (context, i) {
return ListTile(
title: Text(
i.toString(),
textScaleFactor: 1.5,
style: TextStyle(color: Colors.blue),
));
}),
ListView.builder(
controller: statelessControllerB,
itemCount: 2000,
itemBuilder: (context, i) {
return Card(
child: ListTile(
title: Text(i.toString()),
),
);
}),
],
),
),
);
}
}

最佳答案

您可以使用AutomaticKeepAliveClientMixin将状态保留在“选项卡 View ”中。

例如

class GetListView extends StatefulWidget{
@override
State<StatefulWidget> createState() =>_GetListViewState();

}

class _GetListViewState extends State<GetListView> with AutomaticKeepAliveClientMixin<GetListView>{

@override
Widget build(BuildContext context){
return ListView.builder(

itemCount: 2000,
itemBuilder: (context, i) {
return ListTile(
title: Text(
i.toString(),
textScaleFactor: 1.5,
style: TextStyle(color: Colors.blue),
));
});
}

@override
bool get wantKeepAlive => true;

}

不要在 ListView.builder的子级中使用 TabBarView,而要使用 GetListView

例如
TabBarView(
children: <Widget>[
GetListView(),
ListView.builder(
controller: controllerB,
itemCount: 2000,
itemBuilder: (context, i) {
return Card(
child: ListTile(
title: Text(i.toString()),
),
);
}),
],
),
)

实现此目的的第二种方法是使用 PageStorageKey。 Scrollable使用 PageStorageKey保存滚动偏移量。每次滚动完成时,可滚动页面的存储都会更新。

例如
 ListView.builder(
key: PageStorageKey<String>('controllerA'),
controller: statelessControllerA,
itemCount: 2000,
itemBuilder: (context, i) {
print("Rebuilded 1");
return ListTile(
title: Text(
i.toString(),
textScaleFactor: 1.5,
style: TextStyle(color: Colors.blue),
));
}),

注意:在第二个示例中,小部件将每次使用特定的滚动偏移量进行重建。建议使用第一个解决方案。

关于flutter - 更改选项卡时如何获取Flutter ScrollController以保存ListView.builder()的位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60292911/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com