I am developing an app in Flutter with Dart and am generally finding layout quite straightforward. However, I am running into a problem which I think is related to default padding between widgets.
I have two flutter ButtonRows in a Column which render with a quite large gap between them which I would like to eliminate. I guess it is caused by padding and have tried various approaches with no success so far. An extract from the code is as follows:
#override
Widget build(BuildContext context) {
return new Scaffold(
...
body: new Column(
...
children: <Widget>[
...
new Container(
margin: new EdgeInsets.all(0.0),
child: new Padding(
padding: new EdgeInsets.all(0.0),
child: new ButtonBar(
...
children: <Widget>[
new MaterialButton(
...
),
new MaterialButton(
...
),
),
),
),
),
new Container(
margin: new EdgeInsets.all(0.0),
child: new Padding(
padding: new EdgeInsets.all(0.0),
child: new ButtonBar(
...
children: <Widget>[
new MaterialButton(
...
),
new MaterialButton(
...
),
],
),
),
),
],
),
);
}
You have different ways to customize buttons:
customize ButtonTheme for ButtonBar
use Row instead of ButtonBar
implement your own button via InkWell
etc
What to use depends on your cases/requirements. Here quick example of different ways:
class ButtonRowWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Buttons"),
),
body: new Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
new Container(
child: new Text("widget ButtonBar:"),
margin: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
),
new ButtonBar(children: <Widget>[
new FlatButton(
child: new Text("Button 1"),
onPressed: () => debugPrint("Button 1"),
),
new FlatButton(
child: new Text("Button 2"),
onPressed: () => debugPrint("Button 2"),
)
]),
new Container(
child: new Text("widget ButtonBar with custom ButtomTheme:"),
margin: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
),
new ButtonTheme(
minWidth: 44.0,
padding: new EdgeInsets.all(0.0),
child: new ButtonBar(children: <Widget>[
new FlatButton(
child: new Text("Button 1"),
onPressed: () => debugPrint("Button 1"),
),
new FlatButton(
child: new Text("Button 2"),
onPressed: () => debugPrint("Button 2"),
),
]),
),
new Container(
child: new Text("widget Row with FlatButton:"),
margin: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
),
new Row(
children: <Widget>[
new FlatButton(
child: new Text("Button 1"),
onPressed: () => debugPrint("Button 1"),
),
new FlatButton(
child: new Text("Button 2"),
onPressed: () => debugPrint("Button 2"),
),
],
),
new Container(
child: new Text("widget Row with InkWell"),
margin: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
),
new Row(
children: <Widget>[
new InkWell(
child: new Text("Button 1"),
onTap: () => debugPrint("Button 1"),
),
new InkWell(
child: new Text("Button 2"),
onTap: () => debugPrint("Button 2"),
),
],
)
]),
);
}
}
Debug paint can be helpful in this case.
Also, the ButtonBar itself has a buttonPadding attribute that you can customize.
Overrides the surrounding ButtonThemeData.padding to define the
padding for a button's child (typically the button's label).
If null then it will use the surrounding ButtonBarTheme.buttonPadding.
If that is null, it will default to 8.0 logical pixels on the left and
right.
ButtonBar(
buttonPadding: EdgeInsets.all(0),
children: <Widget>[
FlatButton(
child: Text('Hello'),
onPressed: () => print(),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
],
),
Related
How to make two buttons expand equally over the entire width of the Navigation Drawer?
The main thing will be
ListTile(
title: Row(
children: <Widget>[
Expanded(child: RaisedButton(onPressed: () {},child: Text("Clear"),color: Colors.black,textColor: Colors.white,)),
Expanded(child: RaisedButton(onPressed: () {},child: Text("Filter"),color: Colors.black,textColor: Colors.white,)),
],
),
)
Complete Code
class SO extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
decoration: BoxDecoration(
color: Colors.blue,
),
),
ListTile(
title: Text('Item 1'),
onTap: () {
// Update the state of the app
// ...
},
),
ListTile(
//contentPadding: EdgeInsets.all(<some value here>),//change for side padding
title: Row(
children: <Widget>[
Expanded(child: RaisedButton(onPressed: () {},child: Text("Clear"),color: Colors.black,textColor: Colors.white,)),
Expanded(child: RaisedButton(onPressed: () {},child: Text("Filter"),color: Colors.black,textColor: Colors.white,)),
],
),
)
],
),
),
);
}
}
This worked for me
Row(
children: <Widget>[
RaisedButton(
onPressed: () {
Route route =
MaterialPageRoute(builder: (context) => MinionFlare());
Navigator.push(context, route);
},
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.4,
child: Text("Minion"),
),
),
RaisedButton(
onPressed: () {
Route route = MaterialPageRoute(
builder: (context) => EmojiRatingBar());
Navigator.push(context, route);
},
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.4,
child: Text("Emoji")),
),
],
),
You can wrap each button with Expanded.
Row(
children : <Widget>[
Expanded(
child: Button(
child: Text("Clear")
)
),
Expanded(
child: Button(
child: Text("Filter")
)
),
])
Container(
height: 100,
child: Row(
children : <Widget>[
Expanded(
child: RaisedButton(
onPressed: () {},
color: Color(0xff0000ff),
child: Text("Left Button", style: TextStyle(color: Colors.white),)
)
),
Expanded(
child: RaisedButton(
onPressed: () {},
color: Color(0xffd4d4d4),
child: Text("Right Button")
)
),
])
)
I'm trying to add a floating action button to an image. The button will be used to change the selected image. I want the button to float over the bottom right of the image. So far all I can do is add the floating action button directly below the image. Thanks for any help!
#override
Widget build(BuildContext context) {
// Create the view scaffold. Use a list view so things scroll.
return new Scaffold(
appBar: new AppBar(
title: new Text("My Title"),
),
body: new ListView(
children: [
new Container(
padding: EdgeInsets.zero,
child: new Image.asset(
"assets/images/background_image.png",
fit: BoxFit.fitWidth,
),
),
new FloatingActionButton(
child: const Icon(Icons.camera_alt),
backgroundColor: Colors.green.shade800,
onPressed: () {},
),
new Divider(),
new ListTile(
title: new Text('Email'),
leading: const Icon(Icons.email),
onTap: () {},
),
new Divider(),
],
),
);
}
You may use a Stack and Positioned widget, you can read about those widgets here:
Stack:
https://docs.flutter.io/flutter/widgets/Stack-class.html
Positioned:
https://docs.flutter.io/flutter/widgets/Positioned-class.html
return new Scaffold(
appBar: new AppBar(
title: new Text("My Title"),
),
body: new ListView(
children: [
Stack(
children: <Widget>[
new Container(
padding: EdgeInsets.zero,
child: new Image.asset(
"assets/images/background_image.png",
fit: BoxFit.fitWidth,
)),
Positioned(
right: 0.0,
bottom: 0.0,
child: new FloatingActionButton(
child: const Icon(Icons.camera_alt),
backgroundColor: Colors.green.shade800,
onPressed: () {},
),
),
],
),
new Divider(),
new ListTile(
title: new Text('Email'),
leading: const Icon(Icons.email),
onTap: () {},
),
new Divider(),
],
),
);
I want to my card button fit together like Reddit App. How can do that?
Outside the main Row has a Container and Container' has padding height 15.0 . How can Row's widget fit that height 15.0 responsively.
Reddit card buttons
My app card buttons
This is my code;
#override
Widget build(BuildContext context) {
return new SafeArea(
top: false,
bottom: false,
child: new Card(
child: new Column(
children: <Widget>[
new Container(
padding: EdgeInsets.fromLTRB(5.0, 15.0, 5.0, 3.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Container(
color: Colors.blueGrey,
child: new Row(
children: <Widget>[
new Icon(Icons.arrow_drop_up),
new Text('Vote'),
new Icon(Icons.arrow_drop_down),
],
),
),
new Container(
color: Colors.blueGrey,
child: new Row(
children: <Widget>[
new Icon(Icons.mode_comment),
new Text('Comment'),
],
),
),
new Container(
color: Colors.blueGrey,
child: new Row(
children: <Widget>[
new Icon(Icons.share),
new Text('Share'),
],
),
),
],
),
)
],
),
),
);
}
Hello and welcome to Flutter :)
First of all you have used too much padding i.e. 15.0 so that is why your grey boxes are smaller than that of Reddit example.
I have taken a simpler approach and designed a sample control for you. Hope you like it.
import 'package:flutter/material.dart';
void main() {
runApp(RedditButtonsExample());
}
class RedditButtonsExample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Reddit Buttons Example",
home: HomePage(),
theme: ThemeData(
primaryColor: Colors.white,
accentColor: Colors.white,
),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Reddit Buttons Example'),
),
body: Column(
children: <Widget>[
Expanded(child: Icon(Icons.insert_emoticon)),
RedditButtonsCard(), //Example widget.
],
),
);
}
}
//This is the example control that you need.
class RedditButtonsCard extends StatelessWidget {
const RedditButtonsCard({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Card(
color: Colors.black,
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
FlatButton.icon(
textColor: Colors.white,
icon: Icon(
Icons.thumbs_up_down,
color: Colors.white,
),
label: Text('Vote'),
onPressed: () {},
),
FlatButton.icon(
color: Colors.white30,
textColor: Colors.white,
icon: Icon(
Icons.mode_comment,
color: Colors.white,
),
label: Text('Comment'),
onPressed: () {},
),
FlatButton.icon(
textColor: Colors.white,
icon: Icon(
Icons.share,
color: Colors.white,
),
label: Text('Share'),
onPressed: () {},
),
],
),
),
);
}
}
I used Table and TableRow and I found what I wanted. Off the topic but I want to say this; I found this solution in my dream. I said my self "you have to use DataTable or something then you got what you want." My subconscious full of with Flutter I guess. :D
#override
Widget build(BuildContext context) {
return new SafeArea(
top: false,
bottom: false,
child: new Card(
child: new Column(
children: <Widget>[
new Table(
children: [
new TableRow(
children: [
new InkWell(
onTap: () {},
child: Padding(
padding: const EdgeInsets.fromLTRB(5.0, 15.0, 5.0, 15.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Icon(FontAwesomeIcons.arrowAltCircleUp, color: Colors.white),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: new Text('Vote', style: TextStyle(color: Colors.white)),
),
new Icon(FontAwesomeIcons.arrowAltCircleDown, color: Colors.white),
],
),
),
),
new InkWell(
onTap: () {},
child: Padding(
padding: const EdgeInsets.fromLTRB(5.0, 15.0, 5.0, 15.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Icon(Icons.mode_comment, color: Colors.white),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: new Text('Comment', style: TextStyle(color: Colors.white)),
),
],
),
),
),
new InkWell(
onTap: () {},
child: Padding(
padding: const EdgeInsets.fromLTRB(5.0, 15.0, 5.0, 15.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Icon(Icons.share, color: Colors.white),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: new Text('Share', style: TextStyle(color: Colors.white)),
),
],
),
),
),
],
),
],
),
],
),
),
);
}
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(
-
-
-
-
}
Currently, I am trying to create a card template to insert into a list view. I want the column with the icon buttons to be positioned on the far right. I cannot seem to find a way to say that the column containing the icon buttons needs to be flushed to the right.
new Expanded(
child: new ListView(
shrinkWrap: true,
padding: const EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0),
children: <Widget>[
new Card(
child: new Row(
children: <Widget>[
new Padding(
padding: const EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 0.0),
),
new Image(
//image: new AssetImage("assets/ic_access_alarm_red_24dp.png"),
image: new AssetImage("assets/pastDue.png"),
height: 50.0,
width: 50.0,
),
new Padding(
padding: const EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 0.0),
),
new Column(
children: <Widget>[
new Text("This is the title"),
new Text("This is the Description"),
new Text("This is the date"),
],
),
new Column(
children: <Widget>[
new IconButton(
icon: new Icon(Icons.note_add),
onPressed: () {
select("AddCalibration");
}
),
new IconButton(
icon: new Icon(Icons.edit),
onPressed: () {
select("EditInstrument");
}
)
],
)
],
)
),
const Text("I am"),
const Text("A ListView"),
],
)
)
This is a capture of what it currently looks like.
Thank you, vbandrade!
This definitely solved my problem.
new Expanded(
child: new ListView(
shrinkWrap: true,
padding: const EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0),
children: <Widget>[
new Card(
child: new ListTile(
leading: new Image(
image: new AssetImage("assets/pastDue.png"),
height: 50.0,
width: 50.0,
),
title: new Column(
children: <Widget>[
new Text("This is the title"),
new Text("This is the Description"),
new Text("This is the date"),
],
),
trailing: new Column(
children: <Widget>[
new IconButton(
icon: new Icon(Icons.note_add),
onPressed: () {
select("AddCalibration");
}),
new IconButton(
icon: new Icon(Icons.edit),
onPressed: () {
select("EditInstrument");
})
],
),
),
),
const Text("I am"),
const Text("A ListView"),
],
))
This is the end result.
use the Expanded widget to push the icons to the right
new Expanded(child: new Container())
so in your example :
new Column(
children: <Widget>[
new Text("This is the title"),
new Text("This is the Description"),
new Text("This is the date"),],
),
new Expanded(child: new Container()),
new Column(
children: <Widget>[
new IconButton(
icon: new Icon(Icons.note_add),
onPressed: () {}),