listview - 颤振:到达嵌套列表视图的底部时继续在顶部列表视图中滚动
问题描述
我希望创建以下内容:当到达内部 Listview 的顶部或底部时,我想继续在顶部 Listview 中滚动。见 GIF:
一个选项是在到达底部时将内部 Listview 的物理设置为 NeverScrollablePhysics(使用控制器的侦听器),但是如果您想再次向上滚动,这将不起作用。
请参阅下面的代码,在此先感谢!
class TestAppHomePage extends StatefulWidget {
@override
TestAppHomePageState createState() => new TestAppHomePageState();
}
class TestAppHomePageState extends State<TestAppHomePage> {
ScrollController _scrollController = ScrollController();
@override
void initState() {
print('set up');
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Container(
color: Colors.green,
child: ListView(
primary: false,
// controller: _scrollController,
children: <Widget>[topWidget(), topWidget(), topWidget(), topWidget()],
),
),
);
}
Widget topWidget() {
return Card(
color: Colors.purple,
margin: EdgeInsets.all(16),
child: Container(
height: 400,
child: Column(
children: <Widget>[
Container(height: 100, color: Colors.white),
Expanded(
child: ListView(
controller: _scrollController,
children: List.generate(
40,
(index) {
return someText(index);
},
).toList()))
],
),
));
}
Widget someText(int i) {
return Text('text no $i');
}
}
解决方案
我和 OP 在同一个项目上工作,但因为还没有人回应,我想我会分享我自己的摆弄、思考过程和我现在所拥有的东西。我会更新这个答案
首先,我试图阻止使用大量样板代码创建解决方案,但恐怕我这样做可能有点过分了。我很确定我的解决方案不正确,因为编译器会给我警告。
事不宜迟,我的想法是:
1. 我需要一种方法来捕获内部列表中用户的输入。因此,创建自定义 ScrollPhysics 是有意义的。
2. 重要的是,innerlist 在所有情况下都能正常工作。因此,它总是调用 super 来处理它。
3. 我需要传递一个函数,该函数接受我捕获的输入,并假装该输入被传递到外部列表中。
// imports and stuff..
class CustomScroll extends BouncingScrollPhysics {
final Function outerController;
CustomScroll({this.outerController, ScrollPhysics parent}): super(parent: parent);
@override
CustomScroll applyTo(ScrollPhysics ancestor) {
return CustomScroll(
outerController: outerController, parent: buildParent(ancestor));
}
@override
Simulation createBallisticSimulation(ScrollMetrics position, double velocity) {
if (position.pixels >= position.maxScrollExtent && velocity >= 0.0) {
outerController(velocity);
}
return super.createBallisticSimulation(position, velocity);
}
}
class ListInAList extends StatefulWidget {
createState() => ListInAListState();
}
class ListInAListState extends State<ListInAList> with TickerProviderStateMixin {
List<ScrollController> innerControllers = List();
ScrollController outerController = ScrollController();
final outerPhysics = BouncingScrollPhysics();
void innerListener(double velocity, ScrollController outerController)
{
final sim = outerPhysics.createBallisticSimulation(outerController.position, velocity);
ScrollActivity _test = BallisticScrollActivity(outerController.position.activity.delegate,sim,this);
if (_test != null)
outerController.position.beginActivity(_test);
}
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: buildItem, controller: outerController, itemCount: 4, physics: outerPhysics);
}
Widget buildItem(BuildContext context, int index) {
final innerController = ScrollController();
innerControllers.add(innerController);
return Column(children: [
Container(height: 100, color: Colors.blue),
ListView.builder(
physics: CustomScroll(outerController: (velocity) => innerListener(velocity, outerController)),
itemBuilder: buildLoremImpsum,
controller: innerController,
itemCount: 20),
]);
}
Widget buildLoremImpsum(context, index) {
return Container(
height: 30,
color: (index % 2 == 0)
? Color.fromRGBO(255, 0, 0, 1)
: Color.fromRGBO(255, 255, 0, 1));
}
}
所以,基本上,只有createBallisticSimulation
和函数innerListener
才是代码中真正有趣的部分,其他一切都只是示例的一部分。
推荐阅读
- javascript - 客户端的 Three.js webgl + javascript LAG
- php - PHP file_get_contents($url); 字段仅针对某些 url 打开流
- python - 通过计算熊猫另一列中的不同值来创建新列
- azure-devops - 与 Azure DevOps 集成时出现声纳 qube 错误
- mysql - 一次从 2 个 mysql 表中获取信息
- java - Oracle LDAP 使用 Java 将用户移动到不同的 OU
- r - 日期问题(错误:'from' 的长度必须为 1)
- c# - UNO WASM 应用程序在发布到本地文件夹后打开时卡在启动画面上
- python - 如果 Windows 版本低于目标,Python 脚本终止
- java - 使用 Java 进行 Swift AES 加密