Reputation: 1579
How to combine scroll of singlechildscrollview and listview? I am trying to create a layout in which there is a singlechildscrollview containing column which wraps some widgets and a listview. How do I combine the scroll controller of the scroll view and the listview. (i.e 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. The scroll is connected. How do i achieve this???
Upvotes: 2
Views: 5026
Reputation: 1802
This might be a little late, but you can add NeverScrollableScrollPhysics() to the physics param of the ListView like this:
Widget buildLoadedWidget(CarouselCardsLoaded state) {
return ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, i) {
return GestureDetector(
onTap: () async {
Upvotes: 2
Reputation: 2645
I build my Listview, like so:
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:
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.
Upvotes: 0
Reputation: 29468
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. And 2nd is another 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
Upvotes: 3