Flutter position row at bottom of screen inside a SingleChildScrollView? - flutter

I have a screen with a graph and some buttons and then some nav buttons...
in portrait, everything fits on the screen, but I want the nav buttons to be at the bottom of the screen, and the graph to be at the top of the screen
in landscape-phone, there's not enough room...
So I put the whole thing into a SingleChildScrollView(child:column(child: [stuff, navbuttons]), but that resulted in everything being close together and centered.
I tried SingleChildScrollView(child:column(child: [stuff, Spacer, navbuttons]), but that makes a RenderFlex children have non-zero flex but incoming height constraints are unbounded error.
What's the way to make a "SpacerBigEnough" class?

I've accomplished similar UI by using a CustomScrollView, like so:
CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: Column(
children: [stuff],
),
),
SliverFillRemaining(
hasScrollBody: false,
child: Align(
alignment: Alignment.bottomCenter,
child: navbuttons,
),
)
],
)

Related

How can i prevent scaffold from resize it's self when keyboard open EXCEPT a specific widget

i have broadcast screen ( in full screen) . i have textField on the same broadcast screen on the bottom so we have here Stack like following
Scaffold(
body: Stack(
alignment: Alignment.bottomCenter,
children:[
broadCastScreen()
TextField()
]
)
)
so my layout looks like this
now when i tap on the text field all scaffold resize its self because of the keyboard show up
the good point in this part that my textfieldalways smoothly move to be up the keyboard visible
but the bad part that my broadcast screen resize its self inappropriately for the user experience
so i decide to prevent that annoying party with set resizeToAvoidBottomInset to false
well now everything sound good , but i noticed that my keyboard covering my text field
so How Can i use resizeToAvoidBottomInsetto all my widgets except my textfield part ?
i tried to wrap my textfield with another scaffold with set resizeToAvoidBottomInset to true
and scaffold color to transparent so others widgets be visible and tis work as expected but i completely faced problems with GestureDetector pointers in my first scaffold and thats because my second scaffold stack it
another solution i tried programmatically to set my textfield bottom padding to be the same of my keyboard height using EdgeInsets.fromWindowPadding(WidgetsBinding.instance.window.viewInsets,WidgetsBinding.instance.window.devicePixelRatio);
but that's not perfect way because there is some delay with height keyboard value like 900 millisecond to get the keyboard height Furthermore it i tested it on several difference phones and i got null height with some devices It does not guarantee the measurement of all phones
any other perfect way friend ?
Scaffold(
resizeToAvoidBottomInset: false,
body: Stack(
fit: StackFit.expand,
children: [
SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Content()
]
Positioned(
bottom: 0,
child:
child: TextFormField(
decoration: InputDecoration(filled: true, fillColor:
Colors.red
),
),
)
],
),
);
Simply Wrap your content in SingleChildScrollView and wrap your TextField in Positioned widget set bottom parameter of Positioned to Zero, add
fit: StackFit.expand,
Note: Don't forget to add above code to your Stack Widget
Let's try to do something like this
Scaffold(
body: Stack(
alignment: Alignment.bottomCenter,
children:[
Positioned.fill(child:
broadCastScreen()),
Position(
bottom:0,
child: TextField())
]
)
)

I need "ONLY" the BottomSheet to ignore the keyboard

In the screen below, I have the following text "By creating an account ...." that I would like to always keep at the bottom of the screen and should never scroll up with the keyboard.
Currently the text is placed in bottom sheet but unfortunately, the bottom sheet does scroll up with the keyboard.
Using resizeToAvoidBottomInset: false in the Scaffold will not help since it will make all screen ignore the keyboard.
Is there any way to keep the text at the bottom of the screen and have it ignore the keyboard?
I was able to find a basic solution to this.
I placed the terms and conditions text in the bottomNavigationBar property of the Scaffold like this.
Scaffold(
bottomNavigationBar: const TermsAndConditionsText(),
....
....
)
The trick is to use the MediaQuery.of(context).viewInsets.bottom
The value of .bottom will be updated whenever the Keyboard shows up.
To achieve what you want
1- Define the resizeToAvoidBottomInset: false in the Scaffold.
2- Wrap your "form" in a Stack widget.
3- Add your Widgets which should stick at the bottom of the screen at the same level of your "form" in an Align or Positioned
Stack(
children: [
child: Column(
... //Form
),
const Align(
alignment: Alignment.bottomCenter,
child: Text("Terms And Conditions"),
)
],
),
4- And now the magic trick : wrap your "form" in a Padding with the viewInsets.bottom value
Stack(
children: [
Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: Column(
...// Form
),
),
const Align(
alignment: Alignment.bottomCenter,
child: Text("Terms and Conditions"),
)
],
),
My solution looks more like a "hack" than a proper solution, but I never found any official documentation solving this kind of "problem".

How to scroll horizontally InteractiveViewer with overflowed widgets

So I am pretty new to flutter. I am trying to replicate app that I have already made using only Android Views and Java.
So what I am trying to do is create stack of hidable/showable map layers (roads, marks, etc.). I want it to be zoomable and expanded to the height of the screen. Layers are 1:1 so it will overflow the screen width. That is intended.
So I found out that InteractiveViewer allows me to zoom. As a child I created Stack (with StackFit.expand parameter) of SvgPicture.assets (I am using svg files). Problem is, the InteractiveViewer allows me to zoom only the visible part of the Stack and do not allow me to scroll horizontally to the edges of the Stack.
What should I change to be able to zoom it correctly or scroll to the edges? I was trying to play with SingleChildScrollView, OverflowBox or InteractiveViewer's isConstrained parameter, but no success. Most of the times, the Stack of layers just disappeared. I'm willing to drop the zooming for at least scrolling to left and right. I was playing with SingleChildScrollView that wrapped Stack but no success either.
In the picture below there is a sketch of what it looks like. Orange part is header, rectangle with red border is the overflowed Stack with layers and rectangle with blue border is the area I can zoom within.
Image:
Code is here:
Container(
color: Color(Values.colorBodyMap),
alignment: Alignment.center,
child: Column(mainAxisSize: MainAxisSize.max, children: [
Row(mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.max, children: [
Expanded(
child: Container(
height: 70,
alignment: Alignment.center,
child: AutoSizeText( ... )
)
)
]),
Expanded(
flex: 1,
child: InteractiveViewer(
child: Stack(
fit: StackFit.expand,
children: [for ( ... ) SvgPicture.asset(s, fit: BoxFit.fitHeight)],
)))
]))

How to scroll in Flutter Listview child by child, so image by image, without having two half images shown?

I wanna make a Listview where every items has the 'width' of the screen size, scrolling horizontally between them.
child: ListView(
scrollDirection: Axis.horizontal,
children: [
Container(
child: Image.asset("assets/images/tests/asset0.PNG"),
width: MediaQuery.of(context).size.width,
),
Container(
child: Image.asset("assets/images/tests/asset1.PNG"),
width: MediaQuery.of(context).size.width,
),
],
),
But (like if you swipe between many pictures horizontally on instagram) i want the children to be full on page (not half half or something if you start scrolling between them).
Any ideas?
Use PageView.builder instead ListView

Flutter: how to center a child, but set a limit on how big it can grow on one side of the margin

I have a home/login screen which is made up of a column that fills the entire screen like so:
Column(
children: <Widget>[
Expanded(
child: Container(
child: Logo(),
),
),
showThis ? This() : That(),
],
),
The second child of the column is dynamic and can have different heights, and this screen will have inputs so the keyboard will also affect the height.
I want to center Logo() vertically within the container when it's small (e.g. when keyboard is active), but limit how much the 'top margin' is able to grow, so that when the keyboard is hidden and This()/That() is small enough, Logo() will be in a static position on the screen, say 150 from the top (no longer centred vertically).
One method I have tried was using 2 empty Expanded() above and below Logo() and wrapping the top part in a ConstraintedBox(), but I am not able to get it to behave correctly.
Have you tried with Center() and also if you wanna in a specific position use Stack, for example
Stack(
children: <Widget>[
showThis(),
Positioned(top: 150, child: Logo())
],
)
This is what ended up working for me:
Column(
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
// constrain top spacing with a max height
Flexible(child: Container(height: 160)),
_logo(),
Spacer(),
],
),
),
_bottomWidget(),
],
),