颤振:当到达嵌套Listview的底部时,继续在顶部Listview中滚动
我希望创建以下内容:当到达内部Listview的顶部或底部时,我希望继续在顶部Listview中滚动。参见GIF: 一个选项是,当到达底部时(使用控制器的侦听器),将内部Listview的物理设置为NeverScrollablePhysics,但是如果您想再次向上滚动,这将不起作用 请参阅下面的代码,提前感谢颤振:当到达嵌套Listview的底部时,继续在顶部Listview中滚动,listview,flutter,dart,flutter-listview,Listview,Flutter,Dart,Flutter Listview,我希望创建以下内容:当到达内部Listview的顶部或底部时,我希望继续在顶部Listview中滚动。参见GIF: 一个选项是,当到达底部时(使用控制器的侦听器),将内部Listview的物理设置为NeverScrollablePhysics,但是如果您想再次向上滚动,这将不起作用 请参阅下面的代码,提前感谢 class TestAppHomePage extends StatefulWidget { @override TestAppHomePageState createState() =
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');
}
}
class TestAppHomePage扩展StatefulWidget{
@凌驾
TestAppHomePageState createState()=>new TestAppHomePageState();
}
类TestAppHomePageState扩展了状态{
ScrollController_ScrollController=ScrollController();
@凌驾
void initState(){
打印(“设置”);
}
@凌驾
小部件构建(构建上下文){
归还新脚手架(
主体:容器(
颜色:颜色。绿色,
子:ListView(
主要:错误,
//控制器:\ u滚动控制器,
子项:[topWidget(),topWidget(),topWidget(),topWidget()],
),
),
);
}
Widget topWidget(){
回程卡(
颜色:颜色,紫色,
保证金:所有(16),
子:容器(
身高:400,
子:列(
儿童:[
容器(高度:100,颜色:颜色。白色),
扩大(
子:ListView(
控制器:\ u滚动控制器,
子项:List.generate(
40,
(索引){
返回someText(索引);
},
).toList())
],
),
));
}
小部件someText(inti){
返回文本('Text no$i');
}
}
我和OP在同一个项目上工作,但因为还没有人响应,我想我会分享我自己的摆弄、思考过程以及我到目前为止所拥有的东西。我会更新这个答案
首先,我试图阻止创建一个包含大量锅炉板代码的解决方案,但我担心我这样做可能有点过分了。我很确定我的解决方案是不正确的,因为编译器给了我警告
毫无疑问,我的想法是:1.我需要一种在内部列表中捕获用户输入的方法。因此,创建一个自定义的卷轴是有意义的。
2.innerlist在所有情况下都能正常工作,这一点很重要。因此,它总是调用super来处理这个问题。
3.我需要传递一个函数,该函数接受我捕获的输入,并假装该输入被传递到外部列表中
//导入和填充。。
类CustomScroll扩展了BountingScrollPhysics{
最终功能外部控制器;
CustomScroll({this.outerController,ScrollPhysics parent}):超级(父:父);
@凌驾
自定义滚动应用程序(滚动应用程序){
返回自定义滚动条(
outerController:outerController,父级:buildParent(祖先));
}
@凌驾
模拟Create弹道模拟(位置、双速度){
if(position.pixels>=position.maxScrollExtent&&velocity>=0.0){
外部控制器(速度);
}
返回超弹道模拟(位置、速度);
}
}
类ListInList扩展了StatefulWidget{
createState()=>ListInAListState();
}
类ListInAListState使用TickerProviderStateMixin扩展状态{
List innerController=List();
ScrollController外部控制器=ScrollController();
最终的外部物理=弹跳CrollPhysics();
void innerListener(双速度,ScrollController-outerController)
{
最终模拟=外部物理。创建弹道模拟(外部控制器。位置,速度);
ScrollActivity\u test=弹道ScrollActivity(outerController.position.activity.delegate,sim,this);
如果(_test!=null)
外部控制器.位置.不活动(_测试);
}
小部件构建(构建上下文){
返回ListView.builder(
itemBuilder:buildItem,controller:outerController,itemCount:4,Physical:outerPhysics);
}
小部件buildItem(BuildContext上下文,int索引){
最终innerController=ScrollController();
添加(innerController);
返回列(子项:[
容器(高度:100,颜色:颜色。蓝色),
ListView.builder(
物理:CustomScroll(外部控制器:(速度)=>innerListener(速度,外部控制器)),
itemBuilder:BuildLoremipsum,
控制器:innerController,
物品数目:20),,
]);
}
Widget buildloremipsum(上下文、索引){
返回容器(
身高:30,
颜色:(索引%2==0)
?颜色。来自RGBO(255,0,0,1)
:Color.fromRGBO(255,255,0,1));
}
}
因此,基本上,只有
createballiticsimulation
和函数innerListener
才是代码中真正有趣的部分,其他一切都只是示例的一部分 有人解决了这个问题吗?我也需要。如果我们设置shrinkWrap:true
,它将破坏ListView中的重用机制。如果物品数量很大,这将非常缓慢。看看这个答案:,为我解决了它
// 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));
}
}