I have a screen like the below Screenshot. Which has a text in the centre of the screen and a button and text in the bottom of the screen, but I got both in the centre of the screen. I include my expected design, my code and my result below. Anyone, please help me. how to place the text in the centre of the screen and the remaining part inthe bottom of the screen.
Expected Screen,
code:
body: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage("assets/images/home_page_background.png"),
fit: BoxFit.cover,
),
),
child: new Container(
child: new Column(
// crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Container(
// margin: new EdgeInsets.only(top: _MARGIN_JAHMAIKA),
child: new Text(
'JAHMAIKA',
style: style72,
),
),
new Container(
// margin: new EdgeInsets.only(top: _MARGIN_BUTTON),
child: new FlatButton(
child: new Container(
padding: new EdgeInsets.only(
left: _PADDING_LARGE,
right: _PADDING_LARGE,
top: _PADDING_SMALL,
bottom: _PADDING_SMALL),
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: new BorderRadius.all(
new Radius.elliptical(40.0, 50.0)),
border: new Border.all(
color: Colors.white,
),
),
child: new Text(
'Create an account',
style: style19,
),
),
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new SignUpPage()),
);
}),
),
new Container(
margin: new EdgeInsets.only(top: _MARGIN_SMALL),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Container(
child: new Text(
'Already have an account?',
textAlign: TextAlign.center,
style: style15White,
),
),
new GestureDetector(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new SignInPage()),
);
},
child: new Container(
margin: new EdgeInsets.only(left: _MARGIN_SMALL),
child: new Text('Login',
textAlign: TextAlign.center, style: style15Green),
),
),
],
),
),
],
),
),
),
);
result:
You could restructure you widgets inside the column in a different way.
You can use a column/container for all the buttons that has to be aligned to bottom and make the other widget as Expanded which takes up the remaining space, pushing the Row with the buttons to the bottom of the screen.
Wrap it in an Align widget wrapped with an Expanded widget to achieve width and height growth, like so:
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Containter(), // << Put your content here
),
Related
I just figured out some problem when I tried to navigate from one page to the other in flutter. The Navigation.push method requires the context variable and I need reference to the context for navigating.
Widget navBox(Color aColor, double left, double top, Icon icon,String action, Route route) {
return Positioned (
left: left,
top: top,
child: InkWell(
borderRadius: BorderRadius.circular(30.0),
onTap: () {
Navigator.push(context, route);
},
child: new Container(
height: 220.0,
width: 220.0,
decoration: BoxDecoration(
color: aColor,
borderRadius: BorderRadius.circular(30.0),
),
child: Padding(
padding: EdgeInsets.all(40.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
icon,
new Text(action, style: TextStyle(color: Colors.white, fontSize: 20.0, fontFamily: 'Oxygen')),
],
),
),
),
),
);
}
I expected to navigate to the other page by the call of this function with proper route defined.
I got the error like:
The following NoSuchMethodError was thrown while handling a gesture
The method 'ancestorStateOfType' was called on null.
Just add a context parameter to the method's signature. But also have in mind that methods shouldn't have so many parameters, because it makes them harder to use.
Wrapping the InkWell with the new Builder or the Material widget solves the problem.
Here's the snippet on how I solved the problem:
child: new Container(
height: 220.0,
width: 220.0,
decoration: BoxDecoration(
color: aColor,
borderRadius: BorderRadius.circular(30.0),
),
child: new Builder(
builder: (context) => InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => GetData()),);
},
child: Padding(
padding: EdgeInsets.all(40.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
icon,
new Text(action, style: TextStyle(color: Colors.white, fontSize: 20.0, fontFamily: 'Oxygen')),
],
),
),
),
),
),
I am only listing the Container widget of the function. So rest of them could be figured out by yourself.
I am designing a login page it overflowed when I click on any text form field it open keyboard and through overflow warning like this see attached image.
I also want a Raised button icon should be on the right side of the button.
Widget build(BuildContext context) {
return Container(
child: Scaffold(
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Container(
decoration: BoxDecoration(
image: new DecorationImage(
image: new AssetImage('assets/login_page_bg_1.jpg'),
fit: BoxFit.cover,
colorFilter: new ColorFilter.mode(
Colors.black.withOpacity(0.55), BlendMode.dstATop))),
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
margin: new EdgeInsets.only(top: 42.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset('assets/logo.png',
width: 250.0, height: 200.21),
],
),
),
),
Expanded(
flex: 2,
child: Container(
margin: new EdgeInsets.only(bottom: 40.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
//form filed goes here
Text('Login As User',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 35.0)),
TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'you#example.com',
labelText: 'Email Address',
),
new Container(
// width: MediaQuery.of(context).size.width,
child: RaisedButton.icon(
color: Color.fromARGB(251, 188, 74, 1),
label: Text('LOGIN'),
icon: Icon(Icons.send,
size: 10.0, color: Colors.black),
onPressed: () {
this.submit();
}, ),)],),),)],)],),),);
Intital state
Error/overflowed State
Set following property to false
Scaffold(
resizeToAvoidBottomInset: false,
...
)
If you're having issues with overflow error, use SingleChildScrollView with it.
Scaffold(
resizeToAvoidBottomInset: false, // set it to false
body: SingleChildScrollView(child: YourBody()),
)
PS: If you like to scroll your widget when the keyboard opens, you can take a look at this answer
This is happening because when the keyboard comes on screen, the height of the canvas to draw decreases. One solution is to wrap your root container inside SingleChildScrollView like this :
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Stack(
fit: StackFit.loose,
children: <Widget>[
Container(
decoration: BoxDecoration(
image: new DecorationImage(
image: new AssetImage('assets/login_page_bg_1.jpg'),
fit: BoxFit.cover,
colorFilter: new ColorFilter.mode(
Colors.black.withOpacity(0.55), BlendMode.dstATop)
)
),
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(height: 42,),
Expanded(
flex: 1,
child: Center(
child:
Image.asset('assets/logo.png',
width: 250.0, height: 200.21),
),
),
Expanded(
flex: 2,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
//form filed goes here
Text('Login As User',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 35.0)),
TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'you#example.com',
labelText: 'Email Address',
)
),
new Container(
// width: MediaQuery.of(context).size.width,
child: RaisedButton.icon(
color: Color.fromARGB(251, 188, 74, 1),
label: Text('LOGIN'),
icon: Icon(Icons.send,
size: 10.0, color: Colors.black),
onPressed: () {
//this.submit();
}, ),)],)),
SizedBox(height: 40,)
],)],),));
It will make your screen scrollable when the height of the content gets more than the available height of the viewport.
A much simpler solution (source) seems to be just setting the Scaffold property resizeToAvoidBottomPadding to false.
This works great with me:
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(...),
body: ...
Add resizeToAvoidBottomPadding: false, and resizeToAvoidBottomInset: false,
to your Scaffold widget.
Wrap your code with a Container, set the Container's parameters height: MediaQuery.of(context).size.height, and width: MediaQuery.of(context).size.width,. Then wrap your Container with a SingleChildScrollView.
Setting resizeToAvoidBottomInset: true and using body: ListView() works as well. This enables you to scroll the page when you open the keyboard.
An even easier version is to just wrap the offending container with a ListView widget. It makes the screen scrollable and is simple to implement. You can use multiple children with this widget.
Scaffold(
body: ListView(
children: <Widget> [
Container(
),
TextView(
),
Column(
),
],
),
)
you should make the scaffold's floating widgets should size themselves to avoid the onscreen keyboard using :
Scaffold(
resizeToAvoidBottomInset: false,
...
)
I am using TabBar and a custom searchview, when I click inside TextField to search and keyboard pops up my all view hides, am attaching screenshots below. Is this flutter issue or I am doing wrong in my code. Please have a look at my code. without popping up keyboard my this is working fine.
return new Scaffold(
body: new Container(
// margin: EdgeInsets.all(10.0),
//color: Colors.white30,
child: new Column(
children: <Widget>[
new Container(
height: 70.0,
color: Theme.of(context).primaryColor,
child: new Padding(
padding: const EdgeInsets.all(8.0),
child: new Card(
child: new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 3.0),
child: new Icon(Icons.search),
),
new Container(
width: MediaQuery.of(context).size.width - 100.0,
// Subtract sums of paddings and margins from actual width
child: new TextField(
controller: controller,
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
// onChanged: onSearchTextChanged,
),
),
new IconButton(icon: new Icon(Icons.cancel), onPressed: () {
controller.clear();
// onSearchTextChanged('');
FocusScope.of(context).requestFocus(new FocusNode());
},),
],
),
)
))),
new Flexible(
child: new ListView.builder(
itemCount: productList == null ? 0 : productList.length,
itemBuilder: (BuildContext context, int index) {
return new Container(
child: new Column(
children: <Widget>[
new Container(
margin: EdgeInsets.all(10.0),
child: new Column(
children: <Widget>[
new Column(
children: <Widget>[
new Padding(padding: const EdgeInsets.only(top: 5.0)),
new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Container(
alignment: FractionalOffset.topLeft ,
width: 250.0,
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Text(productList[index].name,
style: new TextStyle(color: Colors.black,
fontSize: 18.0, fontWeight: FontWeight.bold),
)
],
),
),
new Text("£"+productList[index].price.toString(),
style: new TextStyle(color: Colors.black,
fontSize: 18.0, fontWeight: FontWeight.bold
),),
],
)
],
),
new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Flexible(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start ,
children: <Widget>[
new Text(
productList[index].description,
overflow: TextOverflow.fade ,),
],
))
],
),
new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new ListTileItemAddRemove(productList[index]),
new Padding(padding: EdgeInsets.only(bottom: 10.0))
],
)
],
),
),
new Divider(color: Colors.black,)
],
),
);
}),
),
],
)
),
);
when I click inside TextField all widgets disappears. please see below.
I think flutter widgets are resized when keyboard pops up, I've resolved this issue by setting value false of resizeToAvoidBottomPadding inside Scaffold. Issue has been resolved but still I am looking for the reason behind this issue.
return new Scaffold(
resizeToAvoidBottomPadding : false,
body: new Container(
-
-
-
-
}
I am trying to imitate a searchview similar to attached image, but I am getting following error. I can achieve this using ListTile but I can't set padding to the icons or TextField. So I am trying to achieve this using Row widget. Please have a look at my code and help me to draw this searchbar.
I/flutter (19181): The following assertion was thrown during
performLayout():
I/flutter (19181): BoxConstraints forces an infinite width.
I/flutter (19181): These invalid constraints were provided to
RenderAnimatedOpacity's layout() function by the
I/flutter (19181): following function, which probably computed
the invalid constraints in question:
I/flutter (19181): _RenderDecoration._layout.layoutLineBox (package:flutter/src/material/input_decorator.dart:767:11)
I/flutter (19181): The offending constraints were:
I/flutter (19181): BoxConstraints(w=Infinity, 0.0<=h<=46.0)
Here is my code:
new Container(
height: 70.0,
color: Theme.of(context).primaryColor,
child: new Padding(
padding: const EdgeInsets.all(8.0),
child: new Card(
child: new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Icon(Icons.search),
new Container(
height: double.infinity,
width: double.infinity,
child: new TextField(
controller: controller,
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
// onChanged: onSearchTextChanged,
),
),
new IconButton(icon: new Icon(Icons.cancel), onPressed: () {
controller.clear();
// onSearchTextChanged('');
},),
],
),
)
))),
EDIT: This answer is a quick fix for the above question.
Best practice is Derek Lakin's answer
Answer:
To maximize container's width, set its width to
MediaQuery.of(context).size.width
Check this code:
new Container(
height: 70.0,
color: Theme.of(context).primaryColor,
child: new Padding(
padding: const EdgeInsets.all(8.0),
child: new Card(
child: new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Icon(Icons.search),
new Container(
//height: double.infinity, //This is extra
width: MediaQuery.of(context).size.width - 100.0, // Subtract sums of paddings and margins from actual width
child: new TextField(
controller: controller,
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
// onChanged: onSearchTextChanged,
),
),
new IconButton(icon: new Icon(Icons.cancel), onPressed: () {
controller.clear();
// onSearchTextChanged('');
},),
],
),
)
)))
You're trying to define infinite height and width for the Container that is a parent of the TextField, which wants to use all the space.
The following works by using Expanded to fill the available space:
Container(
height: 70.0,
child: Card(
margin: EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.search),
),
Expanded(
child: TextField(
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
),
flex: 1,
),
IconButton(
icon: Icon(Icons.cancel),
onPressed: () {},
)
],
),
),
),
I want to make a card, a few cards in flutter. On the right side an image and on the left side a information text. I tested it with CircleAvatar and it almost worked like i wanted it to, but I don't want a circle, I want a square image. I removed the CircleAvatar part and put in a new container and a child, but i couldn't use AssetImage, the only thing i could use was image.asset('.jpg'). The image was almost bigger that the phone, because there was no working way to set the size. With the CircleAvatar it worked because I set the radius as size.
When i tried AssetImage() vscode said to me I cannot put it in a widget.
I hope you can help me out (I thing image.asset() isn't the right way). Thank you all
return new MaterialApp(
title: title,
home: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Card(
child: new Column(
children: <Widget>[
new Row(
children: <Widget>[
new Container(
child:
new CircleAvatar(
backgroundImage: new AssetImage('images/lake.jpg'),
radius: 80.0,
child: new Container(
padding: const EdgeInsets.all(0.0),
child: new Text('Sight'),
),
)
),
),
new Container(
child: new Text('long information text'),
)
],
)
],
),
)
],
),
)
);
}
}
You should be able to do this for your row:
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Sample App',
home: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Card(
child: new Column(
children: <Widget>[
new Row(
children: <Widget>[
new Container(
child: new Image.asset(
'images/lake.jpg',
height: 60.0,
fit: BoxFit.cover,
),
),
new Container(
child: new Text('long information text'),
),
],
),
],
),
),
],
),
),
);
}
For an answer in your comment!
You can use ClipRRect,
new ClipRRect(
borderRadius: new BorderRadius.circular(8.0),
child: new AssetImage('images/lake.jpg')
)
also You can do like this:
new Container(
width: 50.0,
height: 50.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.fill,
image: new AssetImage('images/lake.jpg')
)
)),