[英]how to sync scroll of singlechildscrollview and listview flutter?
How to combine scroll of singlechildscrollview and listview?如何结合singlechildscrollview和listview的滚动? I am trying to create a layout in which there is a singlechildscrollview containing column which wraps some widgets and a listview.我正在尝试创建一个布局,其中有一个包含包含一些小部件和列表视图的列的 singlechildscrollview。 How do I combine the scroll controller of the scroll view and the listview.如何组合滚动视图和列表视图的滚动控制器。 (ie I want the listview to scroll only when the other widgets are scrolled out and out of display and again show only when the listview is reached top.) For instance: in instagram app you have the widgets like userimage, username, followers count, following count, etc and then there is a listview listing the posts of the user. (即,我希望列表视图仅在其他小部件滚动出并退出显示时才滚动,并且仅在列表视图到达顶部时再次显示。)例如:在 Instagram 应用程序中,您有用户图像、用户名、关注者计数等小部件,跟随计数等,然后有一个列表视图列出用户的帖子。 The scroll is connected.卷轴已连接。 How do i achieve this???我如何实现这个???
I can write solution for scrolling parent when nested listview is reaches top.当嵌套列表视图到达顶部时,我可以编写滚动父级的解决方案。 Here is part of me code - I have ListView with 2 elements.这是我的代码的一部分 - 我有 2 个元素的 ListView。 And 2nd is another ListView第二个是另一个 ListView
class _ConferenceScaffoldState extends CommonScaffoldState<ConferenceScaffold> {
final ScrollController controller = ScrollController();
final GlobalKey widgetKey = GlobalKey();
/* widgetKey is for widget in buildHeaderRow() */
StreamController<bool> _streamController = StreamController<bool>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(conference_title),
centerTitle: true,
),
body: getBody(),
);
}
Widget getBody() {
controller.addListener((){
if (widgetKey.currentContext != null) {
double height = widgetKey.currentContext.size.height;
_streamController.add(controller.offset >= height);
}
});
return ListView(
controller: controller,
children: <Widget>[buildHeaderRow(), buildPagerRow()],
);
}
Widget buildPagerRow() => _EventSpeakerPager(scrollCallback, _streamController.stream);
scrollCallback(double position) => controller.position.jumpTo(controller.position.pixels - position);
@override
void dispose() {
controller.dispose();
super.dispose();
}
}
typedef ScrollCallback = void Function(double position);
class _EventSpeakerPager extends StatefulWidget {
_EventSpeakerPager(this.callback, this.stream);
final ScrollCallback callback;
final Stream<bool> stream;
@override
State<StatefulWidget> createState() => _EventSpeakerPagerState();
}
class _EventSpeakerPagerState extends State<_EventSpeakerPager> {
final GlobalKey tabKey = GlobalKey();
bool isChildScrollEnabled = false;
@override
void initState() {
super.initState();
widget.stream.distinct().listen((bool data) {
setState(() {
isChildScrollEnabled = data;
});
});
}
@override
Widget build(BuildContext context) {
ListView eventList = ListView.builder(
physics: isChildScrollEnabled ? AlwaysScrollableScrollPhysics() : NeverScrollableScrollPhysics(),
controller: ScrollController(),
itemBuilder: (buildContext, position) {
if (position.isOdd) return CommonDivider();
return buildEventRow(getEventList()[position ~/ 2], false, null);
},
itemCount: getEventList().length * 2,
);
return Listener(
onPointerMove: (event) {
double pixels = eventList.controller.position.pixels;
if (event.delta.dy > 0.0 && pixels == 0.0) widget.callback(event.delta.dy);
},
child: ...,
);
}
}
UPD Added solution for changing scrolling physics of child with stream UPD添加了使用流更改子项滚动物理的解决方案
I build my Listview, like so:我构建了我的 Listview,如下所示:
List<String> myList = ["one", "two", "three", "four"]; //Just some example list data
ListView.builder(,
itemCount: myList.length,
itemBuilder: (BuildContext context, int index) {
return TileWidget(
myList[index],
index == 0, //this indicates that it is the first item
index == myList.length - 1); //this indicates that it is the last item
},
),
And then I build my 'TileWidget', like so:然后我构建我的“TileWidget”,如下所示:
class TileWidget extends StatelessWidget {
TileWidget(this.tileData, this.isFirstItem, this.isLastItem,);
String tileData;
bool isFirstItem;
bool isLastItem;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
isFirstItem ? Text("this is a title") : Container(),
Text(tileData),
isLastItem ? Text("This is a footer") : Container(),
],
);
}
}
It's not very pretty.它不是很漂亮。 But it is simple and it works.但它很简单而且有效。
This might be a little late, but you can add NeverScrollableScrollPhysics() to the physics param of the ListView like this:这可能有点晚了,但您可以像这样将 NeverScrollableScrollPhysics() 添加到 ListView 的物理参数:
Widget buildLoadedWidget(CarouselCardsLoaded state) {
return ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, i) {
return GestureDetector(
onTap: () async {
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.