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)))
]),
),
);
}
Related
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
I'm making a learning app with flutter.
In our app, you have to put a button over the picture.
So, using positioned on the picture, I made it like the picture below.
#override
Widget build(BuildContext context){
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Image(
image: AssetImage("assets/oral_structure.png"),
fit: BoxFit.fitWidth
),
Positioned(
top:385, left:17,
child: FlatButton(
child: Text('ㅂ', style: TextStyle(fontSize: 30,fontWeight: FontWeight.bold)),
shape: CircleBorder(),
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => B()),);
},
)
),//ㅂ
However, the problem with this is that the position of the buttons changes when using a phone with a large screen.
What can be done to prevent this?
The button seems always in the same place. It should be independent of screen size.
I suspect your problem is rather with the fontSize of the text.
Try to remove the fontSize:, it should fix your problem
EDIT 1:
the problem is with fit: StackFit.expand, that forces the button to expand. You can keep it but wrap your button inside a SizedBox
const SizedBox(
width: 200.0,
height: 100.0,
child: FlatButton(// your code here...),
)
Try to get the width and height of screen, and calculate base on that with a radio.
I need help. At the moment I'm trying to implement a background on my login page.
My problem is that I use a custom shape painter which shows my background.
To make my login page more dynamic I have added a function resizeToAvoidBottomInset: true, to move the textfield over the keyboard.
But now I have the problem that my background will be smaller if I click on my text field.
Here is my login page:
My code:
class _DebugPage extends State<DebugPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: customSubAppBar('Debug', context),
body: Stack(
children: [
//my custom shape painter
Expanded(
child: CustomeShapePainer(),
),
//my custom widgets
_body(context),
],
),
);
}
}
Is there a way to set the background on fix size?
I think you can try set widget CustomeShapePainer wrap Widget Stack. I don't remember exactly but in some projects I did
child: SingleChildScrollView(
child: Container(
color: AppConstants.bgColor,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: CustomPaint(
painter: CurvePainter(),
child: Stack
I have a SingleChildScrollView and inside it I have a list with some cards, that you can remove ou add more. I need to fix an add button at the bottom of the screen, when the card list is not scrollable yet, but when the card list increase size and the scrollview is able to scroll now (to see all the content), the button must follow the list and not keep fixed at the bottom anymore.
For now, what I did to solve this, was check the scroll view every time that a card is added ou removed, if I checked that the screen is now scrollable or not scrollable I change some properties of my build widget:
SingleChildScrollView(
controller: _scrollController,
physics: AlwaysScrollableScrollPhysics(),
child: Container(
height: isNotScrollable
? _pageSize - (_appBarSize + _notifySize)
: null,
padding: const EdgeInsets.symmetric(
horizontal: Constraints.paddingNormal),
child: Column(
.....
and after the list render I create the button like this
isNotScrollable
? Expanded(
child: Container(),
)
: Container(),
CVButton(
color: Palette.white,
Basically, my idea is: if the screen is not scrollable yet (the list content fits in the screen size) I will set a height to the container inside scrollview and add a Expanded() widget before the add button (so the button will stay in the bottom of the container), but if the screen is scrollable (the list content not fits inside the screen size) so I remove the container height and the Expanded widget, then the button will follow the list now as normally.
I don't know if this is the better way to deal with that, I want to know if there is some way to do this without this 'dinamic' way that I am doing, only with fixed widgets and not changing the widget according to the state of the scrollview.
An example when the list becomes scrollable and the button will keep at list bottom
Here the list is not scrollable yet but the button must be at the screen bottom and not list bottom
(I dont wanna use bottomNavBar)
Anyone has any idea how I can solve this?
I have a solution for this. check the code bellow. I added some buttons to add or remove cards. The main trick is to use constraints like minHeight.
import 'package:flutter/material.dart';
class BottomButton extends StatefulWidget {
#override
_BottomButtonState createState() => _BottomButtonState();
}
class _BottomButtonState extends State<BottomButton> {
List<Widget> cards = [];
#override
Widget build(BuildContext context) {
var appBar2 = AppBar(
actions: [
IconButton(
icon: Icon(Icons.add),
onPressed: () {
_addCard();
}),
IconButton(
icon: Icon(Icons.remove),
onPressed: () {
_removeCard();
}),
],
);
return Scaffold(
appBar: appBar2,
body: Container(
height: MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.top + appBar2.preferredSize.height),
alignment: Alignment.topCenter,
child: ListView(
primary: true,
children: [
Container(
constraints: BoxConstraints(
minHeight: MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.top +
appBar2.preferredSize.height),
),
alignment: Alignment.topCenter,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
constraints: BoxConstraints(
minHeight: MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.top +
appBar2.preferredSize.height +
50),
),
alignment: Alignment.topCenter,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: cards,
),
),
ElevatedButton(
child: Text('this is a button'),
onPressed: () {},
),
],
),
)
],
),
),
);
}
void _addCard() {
Widget card = Card(
child: Container(
height: 100,
color: Colors.red,
padding: EdgeInsets.all(2),
),
);
setState(() {
cards.add(card);
});
}
void _removeCard() {
setState(() {
cards.removeLast();
});
}
}
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 :