Flutter Scrollbar prevent Scrollbar showing up on horizontal listview - flutter

I have a Scrollbar on top of my widget tree showing on the right side when scrolling vertically. Now further on in my widget tree I have a horizontal ListView. The scrollbar is showing up there too if the user scrolls on horizontal. I don't want the ScrollBar showing up there. Is there any common way to disable showing up on the horizontal axis?
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scrollbar(
child: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height * 5,
margin: EdgeInsets.all(25),
child: Column(
children: <Widget>[
Row(
...
Later on the listview:
Expanded(child:
Consumer<Model>(builder: (context, myModel, child) {
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
itemCount: list.length,
itemBuilder: (ctx, index) => ChangeNotifierProvider.value(
value: list[index],
child: GestureDetector(

Imagine you have a widget that contains two ListViews:
Scrollbar(
controller: scrollController,
child: ListView.builder(
controller: scrollController,
scrollDirection: Axis.vertical,
physics: AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index) {
return SizedBox(
height: 90,
child: ListView.separated(
scrollDirection: Axis.horizontal,
physics: AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index) {
return Container(
height: 100,
width: 100,
color: Colors.blue,
);
},
separatorBuilder: (context, index) {
return SizedBox(
width: 10,
);
},
itemCount: 50,
),
);
},
itemCount: 50,
),
),
A simple solution would be to wrap the ListView with a NotificationListener and set the onNotification to return true. In this case, the horizontal ListView would be the widget in question. This will tell the NotificationListener that the notification has been handled, which will stop it from sending out a ScrollNotification up the Widget Tree.
So the solution would be:
Scrollbar(
controller: scrollController,
child: ListView.builder(
controller: scrollController,
scrollDirection: Axis.vertical,
physics: AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index) {
return SizedBox(
height: 90,
child: NotificationListener<ScrollNotification>(
onNotification: (_) => true,
child: ListView.separated(
scrollDirection: Axis.horizontal,
physics: AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index) {
return Container(
height: 100,
width: 100,
color: themeColor,
);
},
separatorBuilder: (context, index) {
return SizedBox(
width: 10,
);
},
itemCount: 50,
),
),
);
},
itemCount: 50,
),
),
For an in-depth understanding, consider reading up the docs

Related

ListView inside SingleChildScrollView: RenderBox was not laid out

I want to have a horizontally scrollable container and inside it somewhere a ListView, which scrolls vertically:
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: 5,
itemBuilder: (context, index) {
return const SizedBox(
height: 10,
width: 10,
);
},
),
);
but I get this error: RenderBox was not laid out. I already put Expanded around everything imaginable. It has to be a SingleChildScrollView.
I need help.
Provide width on ListView, it will solve the issue.
LayoutBuilder( /// needed to be top level
builder: (context, constraints) => SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SizedBox(
width: constraints.maxWidth,
child: ListView.builder(
primary: false,
physics: ClampingScrollPhysics(),
itemCount: 5,
itemBuilder: (context, index) {
return const SizedBox(
height: 10,
width: 10,
);
},
),
),
),
);
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SizedBox(
width: MediaQuery.of(context).size.width, //you may get different way like LayoutBuilder on top level
child: ListView.builder(
primary: false,
physics: ClampingScrollPhysics(),
itemCount: 5,
itemBuilder: (context, index) {
return const SizedBox(
height: 10,
width: 10,
);
},
),
),
);

Horizontal viewport was given unbounded height. in listview

i have this error in flutter when using this code:
body:Container(
child :Column(
children:<Widget>[
buildListViews1(),
]),),); }
Widget buildListViews1() {
return buildHorizontalListView1();
}
// Horizontal List View Builder method
Widget buildHorizontalListView1() {
return ListView.separated(
padding: EdgeInsets.all(16),
scrollDirection: Axis.horizontal,
separatorBuilder: (context, index) => Divider(
color: Colors.black,
),
itemCount: items.length,
itemBuilder: (context, index) {
return Container(
width: 50,
height: 50,
child: ListTile(
title: Text(items[index]),
),
);
},
);}
}
Flutter does not know what size your ListView should have. Try adding shrinkWrap: true to the ListView.

Vertical ListView of Horizontal Listviews

I am trying to have a vertical list of horizontal listviews. Currently the User Experience is really bad in that scrolling does sometimes not work. This is similar to like a youtube homepage or Spotify where you scroll down and each row is scrollable
Expanded(
flex: 5,
child: Container(
width: double.infinity,
height: 500,
child: ListView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount: skills.length,
itemBuilder: (context, index){
return CategoryHomeScreen(videosInSection: videoRecommended[skills[index]] ?? [], skill: skills[index]);
}),
),
),
The widget referred to in item builder
return Column(
children: [
Padding(
padding:
EdgeInsets.fromLTRB(HomeBrain.headingPaddingLeftSide, 0, 0, 0),
child: Text(
widget.skill,
style: Constants.subHeading,
)),
//these are horizontal scrollviews to see more videos
Container(
height: HomeBrain.videoHeightBox +
HomeBrain.sizeBetweenvideoAndSub +
HomeBrain.videoHeight -
HomeBrain.takeAwayFromContainerSizedOfVideoFram,
child: SizedBox(
height: 0,
width: double.infinity,
child: ListView.builder(
physics: ClampingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: widget.videosInSection.length,
itemBuilder: (context, int index) {
//passes over author, thumbnail url, thumbnail and video url so each tile is unique
return ScreenTile(
authorName: widget.videosInSection[index].userNameBy,
pathToThumbnail: widget.videosInSection[index].thumbNailUrl,
thumbnail: widget.videosInSection[index].thumbnail,
pathToVideo: widget.videosInSection[index].videoUrl,
profilePic: widget.videosInSection[index].profilePic,
videoBrain: widget.videosInSection[index],
);
},
),
),
),
],
);
you can do it this way. This is for demo purposes.
ListView.builder(
itemCount: 15,
itemBuilder: (_, i) {
return _horizontalListView();
},
),
Widget _horizontalListView() {
return SizedBox(
height: 120,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (_, __) => _buildBox(color: Colors.orange),
),
);
Widget _buildBox({required Color color}) => Container(margin: EdgeInsets.all(12), height: 100, width: 200, color: color);

Using both horizontal and vertical listview.builder on a page in flutter

In my application, I want to show two different products on the home screen, horizontally and vertically. But I want to do this with ListView.Builder as they both come as lists. I couldn't find the right usage of this, can you help with this?
SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
height: 200.0,
child: ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: 25,
itemBuilder: (BuildContext context, int index) =>
Card(
child: Center(child: Text('Horizontal List Child')),
),
),
),
ListView.builder(
itemCount: 10,
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
return Expanded(
child: Card(
child:
Center(child: Text('Vertical List Child'))),
);
},
)
],
),
),
I can do it without using ListView.builder but I need to use ListView.builder. The height of the vertical part should be equal to the element inside.
You must need to define the height of any scroll view. I prefer the horizontal scroll view
SingleChildScrollView(
child: Column(
children: [
Container(
height: 150,
child: ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
...
...
...
},
),
),
ListView.builder(
itemCount: 10,
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
...
...
...
},
),
],
)
)
Remove the SingleChildScrollView.
Add an Expanded as parent to the second ListView.
Remove the Expanded from the Card
Scaffold(
body: SafeArea( //in case you dont have appbar
child: CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
const SliverToBoxAdaptar(child:Container(child:ListView(...)))// horizontalList
const SliverList()// verticalSliverList
],
),
),
);
try thiss
Expanded makes item inside becomes full body.
just remove it and the height to make item height equals to card
return Scaffold(
appBar: AppBar(
title: Text("Sample"),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Sample 1"),
),
Container(
height: 100,
child: ListView.builder(
physics: ScrollPhysics(),
itemCount: 5,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Card(
child: Image.network("https://i.picsum.photos/id/9/250/250.jpg?hmac=tqDH5wEWHDN76mBIWEPzg1in6egMl49qZeguSaH9_VI",),
);
}
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Sample 2"),
),
ListView.builder(
physics: ScrollPhysics(),
itemCount: 5,
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
return Card(
child: Image.network("https://i.picsum.photos/id/9/250/250.jpg?hmac=tqDH5wEWHDN76mBIWEPzg1in6egMl49qZeguSaH9_VI"),
);
}
),
],
),
),
),
);

Add RTL to ListView.builder horizontal flutter

I am trying to make ListView.builder horizontal scrolling from right to left
My code:
SliverToBoxAdapter(
child: Container(
height: MediaQuery.of(context).size.height / 4.5,
margin: const EdgeInsets.only(bottom: 5.0, top: 10.0),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return InkWell(/* ... */)
}
),
),
);
You just need to add reverse parameter to the ListView
here is an example:
ListView.builder(
reverse: true,
scrollDirection: Axis.horizontal,
itemCount: list.length,
itemBuilder: (context, position) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Text(list[position]),
color: Colors.grey,
height: 10,
width: 10,
),
);
},
)
for horizontal
ListView.builder(
reverse: true,
scrollDirection: Axis.horizontal,
for vertical
ListView.builder(
reverse: true,
scrollDirection: Axis.vertical,
best way to make it is to wrap your ListView with Directionality widget with TextDirection.rtl
like following code
Directionality(
textDirection: TextDirection.rtl,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return InkWell(/* ... */)
}
),
);