how to only scroll the children inside scrollview that has another scrollview - flutter

I have ListView and the children that has pdf document wrap inside singleChildScrollView want to only scroll the singleChildScrollView and not the listView
after expansion
Below is my code
Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(right: 15, top: 10),
width: size.width,
child: Text("Title should be Pinned",
textAlign: TextAlign.end,
),
),
SizedBox(
height: 20,
),
Theme(
data: ThemeData(
accentColor: Colors.black,
primaryColor: Colors.white24,
),
child: Expanded(
child: ListView.builder(
itemCount: data.length,
itemBuilder: (context, i) => ExpansionTile(
title: Center(
child: Text(
"After Expansion this should be pinned and only children should be scrollable"
),
),
children: [
Container(
child: SingleChildScrollView( //should be scrollable on expanded and not the title of ExpansionTile
child: SfPdfViewer.network(
'$url',
),
),
),
],
),
),
),
)
],
),

warp your widget in a container and give it a height
use the following parameters inside the scroll widget
shrinkwrap: false,
primary: true

physics: NeverScrollableScrollPhysics():
Add This Line to Your Widget then it will work

Related

how to create horizontal listview builder in flutter?

hi I have Row in flutter and I want add some widget on row with listview.builder, listview sort all item vertically. but I want show them horizontally. in the image below you can see my code and the result.so how can i change the listview.builder to horizontal?
You need set height for your ListView if you want to use it horizontally, and set scrollDirection to Axis.horizontal:
Row(
children: [
IconButton(onPressed: () {}, icon: Icon(Icons.chevron_left)),
Expanded(
child: SizedBox(
height: 10,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 12),
height: 10,
width: 10,
color: Colors.red,
);
},
itemCount: 10,
),
)),
IconButton(onPressed: () {}, icon: Icon(Icons.chevron_right)),
],
),
There is a property in listview scrollDirection you need to set for horizontal scrolling
scrollDirection: Axis.horizontal,
Widget build(BuildContext context) {
Widget horizontalList = new Container(
margin: EdgeInsets.symmetric(vertical: 20.0),
height: 200.0,
child: new ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(width: 160.0, color: Colors.red,),
Container(width: 160.0, color: Colors.orange,),
Container(width: 160.0, color: Colors.pink,),
Container(width: 160.0, color: Colors.yellow,),
],
)
);
);
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: horizontalList,
),
);

How to control widget after listview in stack

I build a flutter app with ads as a carousel slider as a bottom layer of the stack widget, and I have I list view in the top layer of the stack widget
and when the list is scrolled vertically it overlays the ads on the screen.
now I have a problem with the carousel slider, I can't scroll it manually and I can't click any
how to solve it?
demo code:
Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(
children: [
CarouselSlider(
options: CarouselOptions(
autoPlay: true,
),
items: imgList
.map((item) => Center(
child: Image.network(
item,
fit: BoxFit.cover,
)))
.toList(),
),
ListView.builder(
shrinkWrap: true,
padding: const EdgeInsets.only(top: 210),
itemBuilder: (context, index) => Container(
color: Colors.white,
child: Text(
'ITEM $index',
textAlign: TextAlign.center,
),
))
],
));
It depends on how you want to lay your widgets out.
If you want to keep the ads persistent (not to scroll away with list) then keep the layout like :
Scaffold(
body: Column(
children: [
CarouselSlider(),
Expanded(
child: ListView.builder(),
),
],
),
)
Using positioned widget inside stack you can easily position the widgets.
Maybe this will help you.
Stack(
children: [
Positioned(
top: 0,
bottom: 250,
left: 0,
right: 0,
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) => Container(
color: Colors.white,
child: Text(
'ITEM $index',
textAlign: TextAlign.center,
),
)),
),
Positioned(
bottom: 8,
right: 0,
left: 0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: CarouselSlider(
items: imgList.map((i) {
return Builder(
builder: (BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.symmetric(horizontal: 5.0),
decoration: const BoxDecoration(color: Colors.amber),
child: GestureDetector(
child: Image.network(i, fit: BoxFit.fill),
onTap: () {
print("hey");
}));
},
);
}).toList(),
options: CarouselOptions(),
)),
),
],
)

Flutter | How to fill the remaining space of a ListView?

In my Flutter app, I have a ListView:
return Scaffold(
body: SafeArea(
child: Container(
color: Colors.blueAccent,
child: ListView(
children: [
Container(
color: Colors.yellow,
height: 100
),
const SizedBox(height: 10),
// How to make this container fill up the remaining height?
Container(
color: Colors.black,
),
],
),
),
),
);
This produces the following view:
Question: How can I make the second box (with black background color) fill up the remaining space? If the content of the box exceeds the remaining space, the ScrollView will enable scrolling.
Is this possible?
There is a better option here using SliverFillRemaining in combination with CustomScrollView instead of a ListView
in your case the code will look like this.
Container(
color: Colors.blueAccent,
child: CustomScrollView(
shrinkWrap: true, // or false
slivers: <Widget>[
SliverToBoxAdapter(
child:Container(
color: Colors.yellow,
height: 100
),),
SliverToBoxAdapter(
child: SizedBox(height: 10),),
// use SliverFillRemaining to make this container fill up the remaining height?
SliverFillRemaining(
hasScrollBody: false, // if using a column, so the widgets in it, doesn't scroll
child:Container( //this container will fill the remaining space in the ViewPort
color: Colors.black,
),
) ,
],
),
),
Fill the remaining space of a ListView means filling the infinite height. I will prefer using Stack as body in this case, hope you can simply archive this.
How can we do without stack?
In this case, we can get the height and use it on Column and using Expanded on inner child that will fill the remaining spaces even for dynamic height.
I prefer using LayoutBuilder to get height.
body: LayoutBuilder(builder: (context, constraints) {
return SafeArea(
child: Container(
color: Colors.blueAccent,
child: ListView(
children: [
SizedBox(
// 1st child of listView
height: constraints.maxHeight,
child: Column(
children: [
Container(color: Colors.yellow, height: 100),
const SizedBox(height: 10),
Expanded(
child: Container(
color: Colors.black,
),
),
],
),
)
],
),
),
);
}),
You can get size and then set a proportion for each...
And set NeverScrollableScrollPhysics() to ensure no slight scrolling, as per below this appears to get what you are seeking.
Widget build(BuildContext context) {
Size _size = MediaQuery.of(context).size;
return Container(
child: Scaffold(
body: SafeArea(
child: Container(
color: Colors.blueAccent,
child: ListView(
physics: NeverScrollableScrollPhysics(),
children: [
Container(color: Colors.yellow, height: _size.height * 0.20),
SizedBox(height: _size.height * 0.10), // How to make this container fill up the remaining height?
Container(
height: _size.height * 0.70,
color: Colors.black,
),
],
),
),
),
));
}
}
Try below code hope its helpful to you. use MediaQuery here. add MediaQuery height to your black container
Refer blog also here for relative to screen size
Container(
color: Colors.blueAccent,
child: ListView(
shrinkWrap: true,
physics: ScrollPhysics(),
children: [
Container(
color: Colors.yellow,
height: 100,
),
const SizedBox(height: 10),
// How to make this container fill up the remaining height?
Container(
color: Colors.black,
height: MediaQuery.of(context).size.height,
),
],
),
),
Your result screen->

How to scroll individual page when we use tabbar in flutter?

I want to make scrollable page in flutter when we use Tabbar in flutter.
I tried this code but this is not working.
In this code my whole listview I cannot see. How to display whole listview items while using tabbar.
So, how can I solve this problem.
Widget _listofitem() {
return Container(
margin: EdgeInsets.only(top: 10.0),
padding: EdgeInsets.all(8.0),
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: categoryDetail.length,
itemBuilder: (BuildContext context, int index) {
return Container(
padding: EdgeInsets.all(8.0),
width: MediaQuery.of(context).size.width,
height: 100.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.cyanAccent),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: SizedBox(
height: 20,
width: 20,
// child: NetworkImage(categoryDetail[index]),
),
),
SizedBox(
height: 10.0,
),
Text(categoryDetail[index]['category_name'].toString()),
],
),
);
},
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text(
'Invitation Card Application',
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.cyan,
centerTitle: true,
bottom: TabBar(
tabs: myTabs,
controller: _tabController,
)
),
body: TabBarView(
controller: _tabController,
children: myTabs.map((Tab tab) {
return Center(
child: Stack(
children: <Widget>[
_listofitem(),
// _ofitem()
],
),
);
}).toList(),
));
}
I want to change page on individual tab click and also do scroll in that individual page. So I display whole my page. What is the solution for it.
In the ListView.builder() widget you have set the property,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
This is preventing the scroll on the list view. If you want to wrap the list view inside the container with the above properties, then wrap the container in the SingleChildScrollView widget.
SingleChildScrollView(
child: Container(),
);
By this, you can have the scroll effect and you will be able to see all the list view items

How to put a Stack as a child of CustomScrollView

I am using a CustomScrollView. I have added a few slivers in it but one of my children has to be a stack which has a list as on of its two children. I tried using SliverToBoxAdapter but that makes the list in the stack non scrollable which is the obvious behaviour. Is there a way to to write some kind of SliverToSliverAdapter? I tried reading the SliverPadding but its looks too complicated for me to understand. Below is my code:
CustomScrollView(
key: PageStorageKey<String>(name),
slivers: <Widget>[
SliverOverlapInjector(
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(context)),
SliverToBoxAdapter(
child: Stack(
children: <Widget>[
Container(
width: double.infinity,
height: 50,
decoration: BoxDecoration(color: pink),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: ListView.builder(
padding: const EdgeInsets.all(0),
shrinkWrap: true,
itemBuilder: (context, index) {
return buildSongRow(songs[index]);
},
itemCount: songs.length,
),
)
],
)),
],
);
Stack widget use parent's size by default. While parent widget is CustomScrollView that decide it's size mean, it will get infinite height. To solve this issue, we can wrap Stack with SizedBox(height:x).
Next issue comes on Stack about scrolling and widget visibility. Widget render prioritize bottom to top and same for the scroll event. While Container(height:50) is the first child of Stack, it will be paint behind ListView and in this case we can have full-scroll event on ListView.
We can move Container<height:50> at the bottom to paint it over ListView. In this case, scroll-event won't work on Container<h:50> portion.
We can wrap Container<h:50> and ListView with SizedBox by providing height and use Align or Positioned widget to place them on Stack. Also, we can increase itemCount+1 and use an empty SizedBox(height:50)(on index 0) that will take same amount of height as Container(height:50) and help to view only for 1st time on Stack.
I am using LayoutBuilder to get the size/constraints of screen.
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) => CustomScrollView(
slivers: [
const SliverAppBar(
title: Text("Stack On CustomScrollView"),
),
SliverToBoxAdapter(
child: SizedBox(
height: constraints.maxHeight * .3, // used by stack
child: Stack(
children: [
Align(
alignment: Alignment.topCenter,
child: Container(
// dont need to use sizedBox here, height is fixed by container's height:50
height: 50,
color: Colors.pink,
alignment: Alignment.center,
child: const Text("Stack Child: Container<height: 50>"),
),
),
Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
height: constraints.maxHeight * .3 - 50,
child: ListView.builder(
itemCount: 4,
itemBuilder: (context, index) => Container(
alignment: Alignment.center,
height: 50,
color: index.isEven
? Colors.deepOrange
: Colors.deepPurple,
child: Text("ListViewItem:$index"),
),
),
),
),
],
),
),
),
SliverList(
delegate: SliverChildListDelegate(
[
...List.generate(
44,
(index) => Container(
height: 100,
alignment: Alignment.center,
color: index.isEven ? Colors.cyanAccent : Colors.blueGrey,
child: Text("SliverList $index"),
),
),
],
),
),
],
),
),
);