I am trying to align a button at bottom of a scrollable screen. For scrolling I used SingleChildScrollView and inside which I added all the widgets. Now the only issue I face is the button is not sticking at the bottom on scroll. Help would be appreciated.
As you can see in the image, the buy now button and add to cart button aligned at bottom. If we scroll the entire page, the button will not be scrollable, instead it will be sticking at bottom. I want to implement in this way.
You can use an stack and put All the widgets except button as its First child and then the button as another child of stack. Below it the example code -
class MyNewApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
alignment: Alignment.center,
children:[
Container(
height:MediaQuery.of(context).size.height,
width:MediaQuery.of(context).size.width,
child:SingleChildScrollView(
child: Column(
// Provide Your Widget here
),
),
),
Positioned(
bottom:0,
child:Align(
alignment:Alignment.center,
child: RaisedButton(
child:Text("Button"),
onPressed:(){},
),
),
),
],
),
);
}
}
Related
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 want to do a screen where there is a scrollable widget and a non-scrollable widget where the non-scrollable will be on top of the scrollable widget in dart flutter.
I have tried something this: pseudo-code:
Stacked(
children: <Widget>[
SingleChildScrollView(
child: // scrollable widget
),
Align(
alignment: Alignment.bottomCenter,
child: // non-scrollable widget eg container
),
]
)
But the scrollable widget is not scrolling. No error with this implementation but scrolling not working
The problem here is that the non scrollable widget is on top of the scrollable one and tends to block all the touch event to the bottom widget (the scrollable one.)
you have several ways to fix this, the first one is to wrap your non scrollable widget inside an IgnorePointer
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(children: [
ListView.builder(itemBuilder: (context, index) {
return Text("item ${index + 1}");
}),
IgnorePointer(
child: Align(
alignment: Alignment.bottomCenter,
child: Container(color: Colors.red.withAlpha(50))),
),
]));
}
but this will prevent any input on the overlapping widget
If you want to achieve the same, but being able to interact with the overlapping widget, you may want to change the IgnorePointer with a GestureDetector, and play with the behaviors https://api.flutter.dev/flutter/widgets/GestureDetector/GestureDetector.html
I have a pane app with Drawer, which I show in a pane layout when the phone is in landscape mode:
To not animate the drawer between pages, I have put it into a Hero.
class SomePage extends Stateless Widget {
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Hero(
child: Material(
elevation: 4.0,
child: MyDrawer(),
tag: "drawer",
),
Expanded(
child: Scaffold(
appBar: ...,
body: ...
)
),
],
);
}
}
The drawer contains a CustomScrollView.
When the user changes pages using Navigator.pushNamed (I am using MaterialApp with onGenerateRoute), the scroll position of the CustomScrollView is reset.
How can I keep the scroll position between page changes (or how can I synchronize the scroll position of the drawer on different pages)?
In my log in screen attached below, I want the view to stay fixed even when I open the keyboard.
If you see the screenshot of how my screen currently behaves, you can notice that it gets scrolled up(pay attention to the Logo TextField) when the keyboard is opened.
I am currently using SingleChildScrollView to avoid overflow, but even if i do not use a SingleChildScrollView, the screen still repositions after opening the keyboard, only this time, with a pixel overflow.
class LoginScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
children: <Widget>[
_logo(),
LoginForm(),
],
),
),
);
}
}
How can I keep the original positioning of the screen(as shown in the screenshot on the left) even when the keyboard is opened?
Edit: Already tried resizeToAvoidBottomInset, it still scrolls.
In your Scaffold, try putting resizeToAvoidBottomInset property to "false".
You can wrap your content in a Scaffold then set the property resizeToAvoidBottomInset to false so it will not resize your content when the device's Keyboard is shown. I've updated your code so you can use it.
class LoginScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
children: <Widget>[
_logo(),
LoginForm(),
],
),
),
)
);
}
}
I display a custom-made bottom app bar in a Stack because of keyboard padding reasons. The custom widget is fully opaque as it should be until it's a child of a Stack in which case, the content behind it starts to be visible since the color's opacity somehow changes.
As you can see, it's only the "main" color that's transparent. Icons remain opaque.
This is the build method of my custom BottomBar widget which is then just regularly put into a Stack. I have tried using a Material and even a simple Container in place of the BottomAppBar widget but the results are the same.
#override
Widget build(BuildContext context) {
return BottomAppBar(
color: Colors.blue.withOpacity(1),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(MdiIcons.plusBoxOutline),
onPressed: () {},
),
Text('Edited 11:57'),
IconButton(
icon: Icon(MdiIcons.dotsVertical),
onPressed: () {},
),
],
),
);
}
Can you interact with the BottomAppBar ? It looks like an order problem. Try to put the BottomAppBar as last in the Stack children.
Note that BottomAppBar doesn't have a constant size, if you did not add it to Scaffold bottomNavigationBar named parameter has a size if this is not null. Below is peace of code in Scaffold dart file:
double bottomNavigationBarTop;
if (hasChild(_ScaffoldSlot.bottomNavigationBar)) {
final double bottomNavigationBarHeight = layoutChild(_ScaffoldSlot.bottomNavigationBar, fullWidthConstraints).height;
bottomWidgetsHeight += bottomNavigationBarHeight;
bottomNavigationBarTop = math.max(0.0, bottom - bottomWidgetsHeight);
positionChild(_ScaffoldSlot.bottomNavigationBar, Offset(0.0, bottomNavigationBarTop));
}
You can even develop your own Widget without BottomAppBar but if you want things like centerDocked and things like circular notched, you will have to do more stuff (anyway you have flexibility to custom design the way you want).
Here is a simple example to do that(one way to do that):
import 'package:flutter/material.dart';
class CustomBottomBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 50),
color: Colors.greenAccent, // if you want this color under bottom bar add the margin to list view
child: ListView.builder(
itemCount: 100,
itemBuilder: (_, int index) => Text("Text $index"),
),
),
Positioned(
bottom: 0,
child: Container(
color: Colors.amber.withOpacity(.5),
width: MediaQuery.of(context).size.width,
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: List.generate(4, (int index) => Text("Text $index")), // you can make these clickable by wrapping with InkWell or any gesture widget
),
),
),
],
),
);
}
}