Does any one know how to accomplish the shrinking of the child view in Flutter as show here in the first picture. I used a gridView which does the job very well.
On the second picture I used a row, I tried it with Container and Constrains but it didn't worked out very well. ;D
return new GridView.count(
crossAxisCount: 3,
padding: const EdgeInsets.all(16.0),
mainAxisSpacing: 4.0,
shrinkWrap: true,
crossAxisSpacing: 4.0,
children: widget.foodItems.map((FoodViewModel food){
return new FoodTile(
name: food.name,
icon: food.icon
, onPressed: (bool state) {
food.isSelected = state;
widget?.onFoodItemTaped(food, state);
},
);
}).toList(),
);
Here the row-code without any constrains
return new SingleChildScrollView(
child: new Container(
margin: const EdgeInsets.all(16.0),
child:new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new Container(
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name: "Tile one", onPressed:(bool state){}),
),
new Container(
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name: "Tile two", onPressed:(bool state){}),
),
new Container(
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name: "Tile three", onPressed:(bool state){}),
)
],
)
));
Complete source code to the tile
You should wrap the instances of FoodTile in a Flexible or Expanded so that the Row will apply a flexible layout model to them and space them evenly.
Just if someone is wondering how the end result looks. I'm still a bit unhappy with the "LayoutBuilder-Solution" but it works for me right know.
return new SingleChildScrollView(
child: new Container(
margin: const EdgeInsets.all(16.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Expanded(child: new LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints){
return new Container(
constraints: new BoxConstraints.tightFor(width: constraints.maxWidth, height: constraints.maxWidth),
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name:"hallo",onPressed: (bool state){}),
);
})),
new Expanded(child: new LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints){
return new Container(
constraints: new BoxConstraints.tightFor(width: constraints.maxWidth, height: constraints.maxWidth),
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name:"hallo 2",onPressed: (bool state){}),
);
})),
new Expanded(child: new LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints){
return new Container(
constraints: new BoxConstraints.tightFor(width: constraints.maxWidth, height: constraints.maxWidth),
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name:"hallo 3",onPressed: (bool state){}),
);
})),
],
),
Related
I'm attempting to create a scrollable listview inside of a container which also contains a static image. However, the listview doesn't appear to be scrollable and I get a "bottom overflow by x pixels" artifact on my app.
static List<Widget> getClubs() {
var myClubs = new List<Widget>();
for (var i = 0; i < 10; i++) {
myClubs.add(new Padding(
padding: EdgeInsets.all(8.0),
child: new CircleAvatar(
backgroundImage:
new NetworkImage("https://i.imgur.com/p2oUDLD.png"),
backgroundColor: Colors.black,
radius: 34.0,
)));
}
return myClubs;
}
final leftSection = new Container(
color: Color(0xFF212121),
width: 100,
child: Column(
children: <Widget>[
SizedBox(height: 20.0),
new Image.asset(
'assets/logo.png',
alignment: Alignment.center,
),
SizedBox(height: 10.0),
new Container(
child: new ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(5.0),
children: getClubs(),
))
],
));
You can use Expanded widget or set the height for the Container.
I would also recommend Wrap for anyone running into an issue where a container is sized wrong within the listview, causing an overflow:
new Container(
alignment: Alignment.center,
child: Wrap( //the magic
children: [
new Container(),
],
),
),
Sometimes best way to fix an estimated height is using sizedbox
int heightToBeReduced = 380;
SizedBox(
height: MediaQuery.of(context).size.height - heightToBeReduced,
child: ListView....
)
wrap the Column in an Expanded widget:
Expanded(
child: Column(
),
),
Another way is to wrap the Column in a Flexible widget and specify a flex factor.
Flexible(
flex: 1,
child: Column(
children: [
],
),
),
I used a Flexible in a Row to control the output of the listview builder
Define the scollController
final _scrollController = ScrollController();
Define the ListView builder
ListView builder = ListView.builder(
itemCount: listPerformance?.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return PerformanceCardWidget(performanceView: listPerformance[index]);
});
Define a flexible that outputs the listview builder contents
Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
Flexible(
flex: 6,
fit: FlexFit.loose,
child: Scrollbar(
isAlwaysShown: true,
controller: _scrollController,
child: SingleChildScrollView(
controller: _scrollController, child: builder))
)
])
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 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
),
new Expanded(
child: _searchResult.length != 0 || controller.text.isNotEmpty
? new ListView.builder(
itemCount: _searchResult.length,
itemBuilder: (context, int i) {
return new Card(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Row(children: <Widget>[
//new GestureDetector(),
new Container(
width: 45.0,
height: 45.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.fill,
image: new NetworkImage(
"https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/lakes/images/lake.jpg")))),
new Text(
" " +
userDetails[returnTicketDetails[i]
["user_id"]]["first_name"] +
" " +
(userDetails[returnTicketDetails[i]
["user_id"]]["last_name"]),
style: const TextStyle(
fontFamily: 'Poppins', fontSize: 20.0)),
]),
new Column(
children: <Widget>[
new Align(
alignment: FractionalOffset.topRight,
child: new FloatingActionButton(
onPressed: () {
groupId = returnTicketDetails[i]["id"];
print(returnTicketDetails[i]["id"]);
print(widget.id);
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new Tickets(groupId,widget.id)));
},
heroTag: null,
backgroundColor: Color(0xFF53DD6C),
child: new Icon(Icons.arrow_forward),
)),
new Padding(padding: new EdgeInsets.all(3.0)),
],
)
]));
},
)
: new ListView.builder(
itemCount: _searchResult.length,
itemBuilder: (context, int i) {
return new Card(
child: new ListTile(
//title: new Text(userDetails[returnTicketDetails[i]["user_id"]]["first_name"]),
),
margin: const EdgeInsets.all(0.0),
);
},
),
),
Hi everyone! As I am building dynamically a Card in a ListView, I was thinking rather than keep the FloatingActionButton in each of them as I already do, to implement a onTap method in each card and trigger something.
In other words, I would like to keep the card as simple as possible without many widget around.
Thank you in advance!
As Card is "a sheet of Material", you probably want to use InkWell, which includes Material highlight and splash effects, based on the closest Material ancestor.
return Card(
child: InkWell(
onTap: () {
// Function is executed on tap.
},
child: ..,
),
);
You should really be wrapping the child in InkWell instead of the Card:
return Card(
child: InkWell(onTap: () {},
child: Text("hello")));
This will make the splash animation appear correctly inside the card rather than outside of it.
Just wrap the Card with GestureDetector as below,
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return new ListView.builder(
itemBuilder: (context, i) {
new GestureDetector(
child: new Card(
....
),
onTap: onCardTapped(i),
);
},
);
}
onCardTapped(int position) {
print('Card $position tapped');
}
}
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,
),
],
),