Flutter Nested bottom sheet or slide up panel - flutter

What is the best way to build a "nested bottom sheet" which behaves like this:
https://dribbble.com/shots/14139422-Mobile-banking-app-interactions?
Do I have to use NestedScrollView or CustomScrollView, or a completely different approach?
Update :
This is my result using SlidingUpPanel, but I still have two problems:
When sliding up the panel, the green and red containers stay behind the panel and do not scroll out of view at the top.
In landscape mode the containers are higher than the device, so this approach does not work. I need the panel to be attached to the bottom of the containers, so it is only visible when scrolling down.
Code:
SafeArea(
child: Scaffold(
body: SlidingUpPanel(
minHeight: MediaQuery.of(context).size.height - 479,
maxHeight: MediaQuery.of(context).size.height - 79,
panel: SingleChildScrollView(
child: Column(
children: [Text('Sliding Panel')],
),
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 100,
color: Colors.green,
),
Container(
height: 300,
color: Colors.red,
)
],
),
),
),
),
);
Result:

I believe there is a Widget for what you want to do, since there is a widget for everything in Flutter. here is the link of the package
NOTE : you can also set minimum height of the widget when collapsed in order to control how much of the widget you can show when it is collapsed.
And here is the demo :

Related

how to use TabBar view inside scrollable widget in flutter

I have this design, The first section in the red box is fixed height size, and The second section is the dynamic height (ListviewBuilder) which changed the content based on the tabBar.
My question is How can I use the TabBar view inside the scrollable widget (custom scroll view/listview etc..)
the solution That I currently found is to use a customScrollView and use SliverFillRemaining like that
SliverFillRemaining(
child: TabBarView(
children: [],
),
),
but that adds extra white space at the bottom of the list and I can't remove it by
making hasScrollBody property false
You could probably achieve what you want with this kind of template :
Scaffold(
body: Column(
children: [
Container(
height: MediaQuery.of(context).size.height * .33,
child: Container(/* Content of the first section */),
),
Expanded(
child: DefaultTabController(
length: 2,
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Container(
height: 50,
child: TabBar(
tabs: [Text("Guest"), Text("Service")],
),
),
),
SliverFillRemaining(
child: TabBarView(
children: [
// Your ListView Builder here
],
),
),
],
),
),
),
],
),
);
Seeing the bit of code you posted, it is probably close to what you already have but after test it doesn't adds extra white space at the bottom.
If it continue to display the same behavior, adding a little more context could help us provide a more accurate answer.

How can I ONLY move the TextField when keyboard is shown?

I want to make it so that the elements in the to-do list do not get scrolled out of the screen when the soft keyboard is shown. Using SingleChildScrollView on the Scaffold body and doing nothing else causes the whole body to be scrolled up so that the TextField is visible.
The TaskList itself is a container that has a ListView.builder as a child by the way.
final usableHeight = MediaQuery.of(context).size.height -
appBar.preferredSize.height -
MediaQuery.of(context).padding.top;
return Scaffold(
appBar: appBar,
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: usableHeight * 0.9,
child: TaskList(_userTasks),
),
Container(
height: usableHeight * 0.1,
child: NewTask(_addNewTask),
),
],
),
),
);
I tried changing the task list container height to this, to account for the size of the keyboard when it's visible:
Container(
height: (usableHeight - MediaQuery.of(context).viewInsets.bottom) * 0.9,
child: TaskList(_userTasks),
),
And that almost solved the problem but there's still a tiny bit of scrolling that hides part of the first task, and I don't know what's causing it.
How should I fix this? I'm okay to completely changing my layout logic.
You can simply remove the SingleChildScrollView then pass your widget for adding task to the floatingactionbutton property of scaffold.
final usableHeight = MediaQuery.of(context).size.height -
appBar.preferredSize.height -
MediaQuery.of(context).padding.top;
return Scaffold(
appBar: appBar,
body:
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: usableHeight * 0.9,
child: TaskList(_userTasks),
),
Container(
height: usableHeight * 0.1,
child: NewTask(_addNewTask),
),
],
),
floatingactionbutton : New task()
);
There is also a floatingactionbuttonstyle property which you can use to style alignment and all of floatingactionbutton widget
Hope it work for you
I think you should probably use a Stack here, and position the new task view in the bottom. If you have a lot of tasks, they will then also scroll behind the card (you might want to add a container or sizedbox at the bottom of the list so you can always still see the last item.
body: Stack(
children: [
// the list of tasks, just put the ListView directly (or wrap it in an Expanded)
TaskList(...),
// position the add task
// it will automatically adjust when the keyboard appears
Positioned(
child: Newtask(...),
bottom: 0.0,
),
],
),
https://api.flutter.dev/flutter/widgets/Positioned-class.html

Flutter: Overflow error/Faulty scrolling with SlidingUpPanel

I am using the sliding_up_panel package (version ^2.0.0+1) and I am facing problems with the scroll behaviour of my screen. My widget looks something like this:
return SingleChildScrollView(
child: SlidingUpPanel(
// set minHeight to 0 to only show the SlidingUpPanel when clicking on the edit icon
minHeight: 0,
controller: sliderController,
panel: const RenameWidget(),
body: generateMainBody(context)),
);
With this approach I get a UI that looks like this:
When I click on the edit icon the panel of the SlidingUpPanel opens as intended:
However, you can see on the first screenshot that I have an overflow on the bottom resulting the following error:
A RenderFlex overflowed by 157 pixels on the bottom.
I was trying to solve this by nesting the SlidingUpPanel in a SingleChildScrollView as you can see in the code above. This does not solve the overflow and cuts off some of the content on the bottom.
Next, I tried moving the SingleChildScrollView into the body of the SlidingUpPanel:
return SlidingUpPanel(
minHeight: 0,
controller: sliderController,
panel: const RenameWidget(),
body: SingleChildScrollView(child: generateMainBody(context)));
This solved the overflow error but when scrolling down it still cuts off some of the content.
This is definitely related to the SlidingUpPanel since doing this works just fine (of course without opening anything when clicking the edit icon):
return SingleChildScrollView(child: generateMainBody(context));
I only want the popup to open when clicking on the edit icon. Maybe using minHeight: 0 is not the correct way to achieve this? How do I make the body of the SlidingUpPanel scroll correctly?
Take a look at this flutter class. You don't need a package to achieve what you want to do.
return Scaffold(
body: Container(
height: double.infinity,
width: double.infinity,
child: SlidingUpPanel(
// set minHeight to 0 to only show the SlidingUpPanel when clicking on the edit icon
minHeight: 0,
controller: sliderController,
panel: const RenameWidget(),
body: SingleChildScrollView(child: generateMainBody(context)),
),
),
);
or u can use flutter modal sheet if you want to open a container from bottom when click a icon or button
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: double.infinity,
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FlatButton(onPressed: (){
showModalBottomSheet(context: context, builder: (context){
return Container(
height: 200,
width: double.infinity,
child: Text("This is Bottom modal sheet", style: TextStyle(color: Colors.black)),
);
});
}, child: Text("open Bottom sheet",style: TextStyle(color: Colors.black)))
]),
),
);
}

how to make a widget to be on the bottom of the screen if using SliverStack?

as you can see at the image above, I have a red container stick on the top (right below the app bar). here is the code I use
CustomScrollView(
slivers: [
SliverAppBar(),
_buildStack(),
]
),
Widget _buildStack() {
return SliverStack(
children: [
// I have other widgets here ..
SliverPositioned(
bottom: 0, // <-- I have set the bottom to be zero
child: SliverToBoxAdapter(
child: _buildRedBox(),
),
],
)
}
Widget _buildRedBox() {
return Container(
width: double.infinity,
height: 50,
color: Colors.red,
);
}
I am using sliver tool package so I can access SliverStack and SliverPositioned.
as you can see, I have set the bottom to be zero. but the red box is still on the top. I need to make the red box at the bottom of the screen inside my SliverStack. how to do that ?
Use SliverFillRemaining widget instead of SliverPositioned widget.
SliverFillRemaining will automatically size itself to fill the space between the bottom of the last list item and the bottom of the viewport
SliverFillRemaining(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
_buildRedBox(),
],
),
),

How to make part of flutter widget behave like a stack

What I am Implying to do is that if there is a Column and two containers in it. I want another widget pinned to to the first container which overlaps parts of the 2nd container and move with the first column (if i apply some special scroll effects).
Here is dummy code.
Column(
children: <Widget>[
Container(
height: 300,
child: <Some child widget which is pinned to this box and overlaps the second box>
),
Container(
height: 300,
)
],
)
If I have understood your question properly one way is to use two stack's itself like as follows.
Stack(
children: <Widget>[
Container(
height: 300,
margin: EdgeInsets.all(300),
),
Stack(children: <Widget>[SizedBox(height: 300,),TheWidgetYouWantToOverlap()],)
],
)