How to add a DraggableScrollableSheet inside ListView - flutter

body: RefreshIndicator(
onRefresh: _onRefresh,
child: ListView(
children:[
Stack(
children: [
BuildMainProfile(
screenHeight: screenHeight,
screenWidth: screenWidth,
uid: widget.uid,
callBack: widget.callBack,
),
DraggableScrollableSheet(
builder: (BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.blue[100],
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
);
},
)
],
),
] ),
),
The above codes give an error
These invalid constraints were provided to RenderFractionallySizedOverflowBox's layout() function by the following function, which probably computed the invalid constraints in question:
So How can we use DraggableScrollableSheet inside ListView
ListView is only used because of RefreshIndicator, it serves no other purpose. So is there an Alterntive

Related

Draggable scrollable sheet in flutter

When I click on the DraggableHeaderComponent to pull it up, it doesn't work.
When dragging to the bottom of the screen, I want to keep the DraggableHeaderComponent sticky at the top and the rest of the array moving with the scroll.
The image below shows what I mean, but I want to install the header at the bottom.
#override
Widget build(BuildContext context) {
return DraggableScrollableSheet(
minChildSize: 0.145,
initialChildSize: 0.145,
expand: false,
builder: (context, scrollController) => SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
DraggableHeaderComponent(),
Expanded(
child: ListView.separated(
itemCount: list.length,
controller: scrollController,
padding: EdgeInsets.symmetric(vertical: 8),
separatorBuilder: (context, index) => Divider(),
itemBuilder: (context, index) => Component(),
),
)
],
),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SizedBox.expand(
child: DraggableScrollableSheet(
minChildSize: 0.145,
initialChildSize: 0.145,
expand: false,
builder: (context, scrollController) => SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
DraggableHeaderComponent(),
Expanded(
child: ListView.separated(
itemCount: list.length,
controller: scrollController,
padding: EdgeInsets.symmetric(vertical: 8),
separatorBuilder: (context, index) => Divider(),
itemBuilder: (context, index) => Component(),
),
)
],
),
),
),
),
);
}
Just add SizedBox.expand() widget after scaffold widget. Might work.

Flutter : RefreshIndicator with ListView Scroll

i have ListView. and listview have many item. Scroll through the screen.(vertical)
and if scroll position is Top, i want to RefreshIndicator work.
i don't know what i have to do..
now, only worked listview scroll. but when scroll position is Top, not work RefreshIndicator..
this is my code..
#override
Widget build(BuildContext context) {
return FutureBuilder<List<BoadModel>>(
future: getData(),
builder: (context, snapshot) {
List<BoadModel> dataList = snapshot.data ?? [];
if (snapshot.hasError) print(snapshot.error);
return RefreshIndicator(
onRefresh: () async {
setState(() {});
},
child: SingleChildScrollView(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Opacity(
opacity: 0.0,
child: ElevatedButton(
onPressed: () {}, child: Text("button"))),
Text(getCategoryName(widget.categoryPage)),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => WriteBoadPage(
category: widget.categoryPage,
),
),
);
},
child: Text("글쓰기"))
],
),
snapshot.hasData
? Column(
children: [
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: dataList.length,
itemBuilder: (BuildContext context, int index) {
return ListViewItem(
title: dataList[index].title,
nickname: dataList[index].nickname,
time: dataList[index].time,
view: dataList[index].view,
commentCount: dataList[index].comment);
},
),
Row(
children: [Text("dafs")],
)
],
)
: Center(
child: CircularProgressIndicator(),
)
],
),
),
);
},
);
}
I found a solution but there is another problem.
The problem is that I have SingleChildScrollView already in parent widget like shown below:
return SingleChildScrollView( //have SingleChildScrollView already
child: Column(
children: [
RefreshIndicator(
child: SingleChildScrollView(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListViewItem();
},
),
),
onRefresh: () async {}),
],
),
);
So I did it like shown below:
#override
Widget build(BuildContext context) {
return RefreshIndicator(
child: SingleChildScrollView(
child: Column(
children: [
ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListViewItem();
},
),
],
),
),
onRefresh: () async {},
);

Flutter vertical PageView issue with SliverAppBar

I need to have the swipe effect of a vertical PageView and the effect the SliverAppBar.
If I set the scrollDirection: Axis.vertical of the PageView.builder and swipe vertical, when I swipe back I can't get the SliverAppBar.
Setting scrollDirection: Axis.horizontal the SliverAppBar works, but as mentioned I need it vertical.
I didn't found any good way to fix this yet, can you help me to understand?
My final objective is to have the first "screen" with buttons (that´s why I am using the SliverAppBar) and next screens will be a fullscreen image gallery. If you have a better solution that don´t use Slivers or PageView, please advise me.
#override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
expandedHeight: MediaQuery.of(context).size.height*0.85,
flexibleSpace: FlexibleSpaceBar(
background: Image.network(
'https://source.unsplash.com/random?monochromatic+dark',
fit: BoxFit.cover,
),
title: Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Row(
children: [
ElevatedButton(
onPressed: () => print('btn1'),
child: Text('Button 1')),
ElevatedButton(
onPressed: () => print('btn2'),
child: Text('Button 2')),
],
),
),
),
),
];
},
body: _pageView(),
),
);
}
_pageView() {
return PageView.builder(
scrollDirection: Axis.horizontal,
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Container(
padding: EdgeInsets.all(16.0),
child: Image.network(
'https://source.unsplash.com/random?sig=$index',
fit: BoxFit.cover,
),
),
);
},
);
}
}
If you want to view the full example or test it on your side:
https://pastebin.com/PXDHVw6k
Add SliverOverlapAbsorber before SliverAppBar;
NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
context),
sliver: SliverAppBar(
...
),
),
];
},
body: _pageView(),
),
use custom scroll wheel and using sliver.list instead of pageview and also add physics: PageScrollPhysics() to custom scroll wheel to get the same page snapping effect as pageview.
CustomScrollView(
physics: PageScrollPhysics(),
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return ... ;
},
childCount: ...,
),
),
],
),

FutureBuilder rebuilds because of TextField in Flutter

The problem is when I try to input some text into textfield, the keyboard shows up for a second, and then the whole FutureBuilder rebuilds immediately.
Here is my FutureBuilder
body: FutureBuilder(
future: Provider.of<Activities>(context, listen: false).fetchAndSet(),
builder: (context, snapshot) => snapshot.connectionState ==
ConnectionState.waiting
? Center(child: CircularProgressIndicator())
: Consumer<Activities>(
child: Center(
child: const Text('nothing here'),
),
builder: (context, activities, ch) => SingleChildScrollView(
child: Center(
child: Column(children: [
Container(
padding:
EdgeInsets.only(top: mediaQuery.size.height / 40),
child: Text(time, style: TextStyle(fontSize: 30)),
),
DayContainer(mediaQuery, activities),
Container(
height: 300,
child: SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
children: <Widget>[
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: activities.activities.length,
itemBuilder: (context, index) {
return ElementPicker(
mediaQuery,
// this.callbackN,
activities.activities[index]);
})
],
),
),
),
FloatingActionButton(
onPressed: () => activities.addActivity(
'0Adding0', 'Добавить активность', 0.0, 0.0),
child: Icon(Icons.add),
)
]),
),
),
),
)
Inside of ElementPicker, there is another widget in which there is TextField
You need to initialize your futures in the initState so that whenever the widget rebuilds for any reason (in this case opening of the keyboard), you don't perform the fetchAndSet again:
void initState() {
super.initState();
fetchAndSetFuture = Provider.of<Activities>(context, listen: false).fetchAndSet();
}
...
//in build()
FutureBuilder(
future: fetchAndSetFuture,
builder: ...
);

Flutter : Can't get correct size of Card that contain row

I created a card and set a width of container to 300 but i get the card with a width more than 300
return Card(
margin: EdgeInsets.symmetric(horizontal:5,vertical: 10),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
CourseInfoPage(widget.courseId)));
},
child: Container(
width: 300,
height: 200,
color:Colors.yellow,
child: Row(
children: <Widget>[
// courseText(context, course, 180),
// courseImage(course, 150),
Container(width: 100,color:Colors.red),
Container(width:200,color: Colors.green,)
],
),
),
),
);
and when i get it inside ListView like this
Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
child: Selector<CategoriesModel, List<CourseModel>>(
selector: (buildContext, model) => model.getCoursesByCategory(categoryName),
builder: (context, value, child) => value == null
? CircularProgressIndicator()
: ListView.builder(
scrollDirection: Axis.vertical,
itemCount: value.length,
itemBuilder: (BuildContext context, int index) {
return CourseCard(value[index].courseId);
},
),
),
),
I want the card to be exactly 300 and one container to 100 and an other to 200 which make it to be 300 but as you can see in the below screenshot i get this extra yellow space
the problem is in the Listview widget. Listview expands its children. To prevent this from happening, you need to wrap your CourseCard inside an Align widget and give it an alignment. check the following code. also, check this answer for more information.
ListView.builder(
scrollDirection: Axis.vertical,
itemCount: 2,
itemBuilder: (BuildContext context, int index) {
return Align(
alignment: Alignment.center,
child: CourseCard(value[index].courseId),
),
);
},
),