Adding multiple rows or column in body - flutter

Hi trying to figure out why my hamburger is getting misaligned when i add another Expanded() code within the body.
I tried to follow this url to develop a hamburger menu and responsive for all platforms at once.
Flutter Blog
Below is the code that i tried where i added Expanded() below the Row()
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
return Scaffold(
key: _scaffoldKey,
drawer: AppDrawer(),
body: Row(
children: [
Row(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: IconButton(
icon: Icon(Icons.menu, size: 30),
onPressed: () {
_scaffoldKey.currentState.openDrawer();
}),
),
],
),
Expanded(
child: Container(
width: width,
child: Column(
children: [
Expanded(
child: Lottie.network(
'https://assets2.lottiefiles.com/datafiles/6WfDdm3ooQTEs1L/data.json'),
),
Expanded(
child: Column(
children: [
Flexible(
child: Text(
"Multivariate Testing",
style: GoogleFonts.montserrat(
fontSize: 50,
),
),
),
SizedBox(
height: 10,
),
Flexible(
child: Text(
'Run experiments to make key flows more effective.',
style: GoogleFonts.montserrat(
fontSize: 25,
),
),
),
SizedBox(
height: 35,
),
// ignore: deprecated_member_use
TextButton(
onPressed: () {},
child: Text(
'Create Experiment',
style: GoogleFonts.montserrat(
fontSize: 20,
),
),
)
],
),
),
],
),
),
)
],
),
);
}
}
and the output that i am seeing from mobile view. Appreciate any help. Sorry for too big screenshot!

This is because of the default functionality of Row.
So change your first child for your top level Row to this,
Scaffold(
key: _scaffoldKey,
drawer: AppDrawer(),
body: Row(
children: [
Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.all(16),
child: IconButton(
icon: Icon(Icons.menu, size: 30),
onPressed: () {
_scaffoldKey.currentState.openDrawer();
})),
),
Expanded( ...... rest of your code
Here, we are using the Align widget with alignment: Alignment.topCenter.
Align widget takes the entire available space in the parent and then depending on the alignment property, aligns it't child inside it.
So, saying Alignment.topCenter will place it at the top vertically and middle horizontally.
Using an AppBar will unnecessarily complicate your situation since now, the AppBar is going to take up space a the top, but in your case, you want your Lottie view to be visible at the top, so it will overlap.

Because Expanded fills up the whole space and that's why your hamburger is getting misaligned.
Why don't you try using appbar for the hamburger?

Related

How to align an asset image responsive at bottom center in flutter

here is the UI that I'm trying to build
but this is the output
I tried alignment also , but that also didn't working
but when setting a fixed height this is working fine
but I can't fill this using the fit parameter,
here is the code
Scaffold(
backgroundColor: kDarkTheme,
body: SafeArea(
child: Column(
children: [
const SizedBox(height: 10),
Row(
//code for top button
),
const SizedBox(height: 150),
Stack(
children: [
Center(
child: CircleAvatar(
radius: radiusSize + 5,
backgroundColor: kDarkCounterColor,
child: CircleAvatar(
backgroundColor: kDarkTheme,
radius: radiusSize,
),
),
),
Center(
child: Padding(
padding: const EdgeInsets.only(top: 35),
child: Text(
'39',
style: GoogleFonts.italiana(
fontSize: 120, color: kDarkCounterColor),
),
),
),
],
),
const SizedBox(height: 15),
const Text(
'Tap To Count',
style: TextStyle(
fontFamily: 'Helvatica',
color: Color(0xff656158),
),
),
Expanded(
child: Align(
alignment: Alignment.bottomRight,
child: SvgPicture.asset(
kDarkThemeImage,
)),
)
],
),
))
this is the code
then the first error appears again. how could I fix this?
You are using the Expanded widget on a column that doesn't have a set size. Try adding MainAxisSize attribute to your column, like this:
Column(
mainAxisSize: MainAxisSize.max, // Add this like
children: [
...
This will make your column fit the whole available size on the previous widget (a scaffold for the whole screen). Then the expanded widget will fill the remaining space not used by the other widgets inside the column.

How to make ExpansionTile scrollable when end of screen is reached?

In the project I'm currently working on, I have a Scaffold that contains a SinlgeChildScrollView. Within this SingleChildScrollView the actual content is being displayed, allowing for the possibility of scrolling if the content leaves the screen.
While this makes sense for ~90% of my screens, however I have one screen in which I display 2 ExpansionTiles. Both of these could possibly contain many entries, making them very big when expanded.
The problem right now is, that I'd like the ExpansionTile to stop expanding at latest when it reaches the bottom of the screen and make the content within the ExpansionTile (i.e. the ListTiles) scrollable.
Currently the screen looks like this when there are too many entries:
As you can clearly see, the ExpansionTile leaves the screen, forcing the user to scroll the actual screen, which would lead to the headers of both ExpansionTiles disappearing out of the screen given there are enought entries in the list. Even removing the SingleChildScrollView from the Scaffold doesn't solve the problem but just leads to a RenderOverflow.
The code used for generating the Scaffold and its contents is the following:
class MembershipScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MembershipScreenState();
}
class _MembershipScreenState extends State<MembershipScreen> {
String _fontFamily = 'OpenSans';
Widget _buildMyClubs() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Color(0xFFD2D2D2),
width: 2
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
title: Text("My Clubs"),
trailing: Icon(Icons.add),
children: getSearchResults(),
),
)
);
}
Widget _buildAllClubs() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Color(0xFFD2D2D2),
width: 2
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: SingleChildScrollView(
child: ExpansionTile(
title: Text("All Clubs"),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.add)
],
),
children: getSearchResults(),
),
)
)
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
gradient: kGradient //just some gradient
),
),
Center(
child: Container(
height: double.infinity,
constraints: BoxConstraints(maxWidth: 500),
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(horizontal: 40.0, vertical: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Clubs',
style: TextStyle(
fontSize: 30.0,
color: Colors.white,
fontFamily: _fontFamily,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 20,
),
_buildMyClubs(),
SizedBox(height: 20,),
_buildAllClubs()
],
),
),
),
),
],
),
)
),
);
}
List<Widget> getSearchResults() {
return [
ListTile(
title: Text("Test1"),
onTap: () => print("Test1"),
),
ListTile(
title: Text("Test2"),
onTap: () => print("Test2"),
), //etc..
];
}
}
I hope I didn't break the code by removing irrelevant parts of it in order to reduce size before posting it here. Hopefully, there is someone who knows how to achieve what I intend to do here and who can help me with the solution for this.
EDIT
As it might not be easy to understand what I try to achieve, I tried to come up with a visualization for the desired behaviour:
Thereby, the items that are surrounded with dashed lines are contained with the list, however cannot be displayed because they would exceed the viewport's boundaries. Hence the ExpansionTile that is containing the item needs to provide a scroll bar for the user to scroll down WITHIN the list. Thereby, both ExpansionTiles are visible at all times.
Try below code hope its help to you. Add your ExpansionTile() Widget inside Column() and Column() wrap in SingleChildScrollView()
Refer SingleChildScrollView here
Refer Column here
You can refer my answer here also for ExpansionPanel
Refer Lists here
Refer ListView.builder() here
your List:
List<Widget> getSearchResults = [
ListTile(
title: Text("Test1"),
onTap: () => print("Test1"),
),
ListTile(
title: Text("Test2"),
onTap: () => print("Test2"),
), //etc..
];
Your Widget using ListView.builder():
SingleChildScrollView(
padding: EdgeInsets.all(20),
child: Column(
children: [
Card(
child: ExpansionTile(
title: Text(
"My Clubs",
),
trailing: Icon(
Icons.add,
),
children: [
ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Column(
children: getSearchResults,
);
},
itemCount: getSearchResults.length, // try 50 length just testing
),
],
),
),
],
),
),
Your Simple Widget :
SingleChildScrollView(
padding: EdgeInsets.all(20),
child: Column(
children: [
Card(
child: ExpansionTile(
title: Text(
"My Clubs",
),
trailing: Icon(
Icons.add,
),
children:getSearchResults
),
),
],
),
),
Your result screen ->

What widget should I use for center text and left-aside button

I am making layout for flutter application
What I want to do is
-----------------------
|[i] [text] |
| |
Icon should be the left (padding 5px)
And text should be the center of screen.
At first I should use the Column
However my layout is not the same proportion
It might be simple though , how can I make it??
Stack() is one of the many options that you can use. Something like this:
Stack(
children:<Widget>[
Padding(
padding: EdgeInsets.only(left: 5),
child: Icon(Icons.info),
),
Align(
alignment: Alignment.topCenter,
child: Text("I'm on the top and centered."),
),
],
),
One way you can do this is something like this..
Widget build(BuildContext context) {
return Column(
children: [
Padding(
padding: EdgeInsets.all(5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(Icons.info),
Text('text'),
Opacity(opacity: 0, child: Icon(Icons.info)),
],
),
),
Padding(
padding: EdgeInsets.all(5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(Icons.info),
Text('second text'),
Opacity(opacity: 0, child: Icon(Icons.info)),
],
),
),
],
);
}
Result:
I might be late, but I want this answer to be there, if some one would find it better for the development purposes in future time.
We can make a reusable widget, which we can use it inside the main widget. The widget will accept text, and icon to be passed when called
// IconData is the data type for the icons
Widget myWidget(String text, IconData icon) => Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
// this will be used a left-padding param
SizedBox(width: 20.0),
// using it here
Icon(icon, size: 28.0, color: Colors.greenAccent),
SizedBox(width: 5.0),
// this will take the remaining space, and then center the child
Expanded(child: Center(child: Text(text)))
]
);
To use in the main Widget, just do like this:
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// calling our widget here
myWidget('FirstText', Icons.alarm),
SizedBox(height: 20.0), // this is used as a top margin
myWidget('SecondText', Icons.notifications)
]
)
If you wanna check out the sources which I used, please see:
Expanded class
SizedBox class
The result you will get is this:
This was an answer I gave a while ago for this same issue, but the other situation was vertical (a Column) instead of horizontal (a Row). Just swap the Row and Columns out for a Column and Rows in this example and you'll get the idea.
My code has grey added in order to show the difference between the two approaches.
A Stack will work, but it's overkill for this, this kind of problem is part of why we have Expandeds and Flexibles. The trick is to use three Flexibles (2 Expandeds and a Spacer). Put the Spacer on top. It and the bottom Expanded must have the same flex value in order to center the middle Expanded.
import 'package:flutter/material.dart';
class CenteringOneItemWithAnotherItemInTheColumn extends StatelessWidget {
const CenteringOneItemWithAnotherItemInTheColumn({
Key key,
}) : super(
key: key,
);
/// Adjust these values as needed
final int sameFlexValueTopAndBottom = 40; // 40%
final int middleFlexValue = 20; // 20%
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Column Alignment Question'),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Spacer(),
const Text(
'Cent',
style: TextStyle(
fontSize: 64,
),
),
const Spacer(),
const Text(
'Bot',
style: TextStyle(
fontSize: 64,
),
),
],
),
Column(
children: <Widget>[
/// The key is to have the Spacer and the bottom Expanded
/// use the same value for flex. That will cause the middle
/// child of the Column to be centered vertically.
Expanded(
flex: sameFlexValueTopAndBottom,
child: Container(
width: 100,
color: Colors.grey[300],
),
),
Expanded(
flex: middleFlexValue,
child: const Align(
alignment: Alignment.center,
child: Text(
'Cent',
style: TextStyle(
fontSize: 64,
),
),
),
),
Expanded(
flex: sameFlexValueTopAndBottom,
child: Container(
color: Colors.grey[300],
child: const Align(
alignment: Alignment.bottomCenter,
child: Text(
'Bot',
style: TextStyle(
fontSize: 64,
),
),
),
),
),
],
),
],
),
);
}
}

Button with column for child not using align

I'm attempting to layout some buttons in a flutter app towards the bottom of the screen as seen here:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: true,
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/foo.jpeg'),
fit: BoxFit.cover),
),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10),
child: _buttonsOne(),
),
Expanded(
child: Text(''),
),
Padding(
padding: EdgeInsets.only(bottom: 10),
child: _buttonsTwo(),
),
],
),
),
);
Counter buttons is setup thusly:
Widget _buttonsTwo() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_oneButton(),
_twoButton(),
_threeButton(),
_fourButton()
],
);
}
My problem is two of the buttons are using glyphs that cause them to be just right of center. Prior to attempting this layout I structured raised buttons with columns so that I could use an Align to pull these icons to the left a bit, as seen here for one of the buttons:
Widget _threeButton() {
return RaisedButton(
onPressed: () {},
elevation: 10,
color: Colors.red,
textColor: Colors.white,
padding: EdgeInsets.all(10.0),
child: Column(
children: <Widget>[
Align(
alignment: Alignment(-0.4, 0),
child: Icon(
Class.icon_name,
size: 30,
),
),
Text(
_fooCount.toString(),
style: TextStyle(fontSize: 25),
)
],
),
);
}
And here's the result I'm getting:
As you can see, the icons for the two rightmost buttons are still a little to the right. I've tried using RaisedButton.icon to no avail as it causes the icons to overlap the text, even restructuring them in a row to try and make wider buttons. What am I missing?
Try using Transform widget instead of Align and translate the X axis:
Transform(
transform: Matrix4.identity()..translate(-7.0),
child: Icon(
FiveRingsDB.conflict_political,
size: 30,
),
),
Text(
_militaryCount.toString(),
style: TextStyle(fontSize: 25),
)

how to center FloatingActionButton inside the persistentFooterButtons

Can someone explain to me how can i center the FloatingActionButton inside the persistentFooterButtons. im missing something here.
List _footer() {
return <Widget>[
new ButtonBar(
children: <Widget>[
new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new FloatingActionButton(
backgroundColor: Colors.redAccent,
onPressed: () => {},
),
],
),
)
],
)
];}
===
#override Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Question"),
),
body: _body(),
persistentFooterButtons: _footer(),
); }
I looked at the code of Scaffold, below is how persistentFooterButtons created:
new Container(
decoration: new BoxDecoration(
border: new Border(
top: Divider.createBorderSide(context, width: 1.0),
),
),
child: new SafeArea(
child: new ButtonTheme.bar(
child: new SafeArea(
top: false,
child: new ButtonBar(
children: widget.persistentFooterButtons
),
),
),
),
)
You can see here, your buttons are wrapped by a ButtonBar. Now let's look at the ButtonBar code below, the DEFAULT alignment is MainAxisAlignment.end. I guess this follows the Material guidelines.
const ButtonBar({
Key key,
this.alignment: MainAxisAlignment.end,
this.mainAxisSize: MainAxisSize.max,
this.children: const <Widget>[],
}) : super(key: key);
The Flutter framework is being updated, but till today (2018 June 08th), you can not put the buttons to the center using persistentFooterButtons.
Solution: I suggest you follow my answer here to put your buttons at the center-bottom of the screen.
I found an easy solution is to wrap the FloatingActionButton in a sized box that is the same width as the screen.
persistentFooterButtons: <Widget>[
SizedBox(
width: MediaQuery.of(context).size.width,
child: FloatingActionButton(
onPressed: () {
print('Close pressed');
},
child: Text('Close'),
)
)
],
I have the same problem. I achieved the desired result with this:
persistentFooterButtons: [
Container(
width: MediaQuery.of(context).copyWith().size.width,
child: Row(
children: [
Expanded(
child: FlatButton(
child: Text('Your centered button'),
onPressed: (){},
),
)
],
),
)
]
I've used a flatbutton just as example but it works as well with floatinActionButtons.
Hope it helps
Found yet another solution. MaterialTheme (theme_data.dart) has buttonBarTheme attribute. You can modify it like following:
var myTheme = ThemeData(
buttonBarTheme: ButtonBarThemeData(
alignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
),
)
And specify it in your MaterialApp widget:
MaterialApp(theme: myTheme)
For anyone trying something similar, but instead of a FloatingActionButton, a set of, let's say two ElevatedButtons, you can center them like this:
...
persistentFooterButtons: [
Center(
child: Column(
children: [
ElevatedButton(), //Button 1
SizedBox(),
ElevatedButton(), //Button 2
],
),
),
],
...
In hope that anyone might find it useful in the future.
floatingActionButton can be aligned or positioned by making use of floatingActionButtonLocation property, however it is not useful for button placed inside persistentFooterButtons.
The persistentFooterButtons are wrapped inside ButtonBar and we don't have any way to override the ButtonBar default alignment of MainAxisAlignment.end for persistentFooterButtons.
Flutter team could have provided persistentFooterButtonsAlignment property but without it, one can achieve similar layout using following bottomNavigationBar hack, if it is not already being used for something else.
bottomNavigationBar: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Divider(
height: 0,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: FlatButton(
child: Text('Button'),
color: Theme.of(context).primaryColor,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
textColor: Theme.of(context).colorScheme.background,
onPressed: () {},
),
),
],
),