Positioning children widgets at the center and at the end of a Column parent widget - flutter

I have to position 2 children widgets inside a Column parent widget. I want one of them to be positioned in the center and the other at the end of the column. What is the best way to do that?
import 'package:flutter/material.dart';
class Screen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Screen'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center, // this is wrong, it positions both the widgets in the center
children: <Widget>[
Text('This text should be at the center of the column'),
Text('This text should be at the end of the column'),
],
),
);
}
}

you can use the Spacer widget like this:
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Spacer(),
Text('This text should be at the center of the column'),
Spacer(),
Text('This text should be at the end of the column'),
],
),
);

(EDIT: I changed the code and added grey to mine in order to show a comparison, so you can see what I mean when I say it will be offset by half. You have to increase the font size to see the difference.)
It's not quite as easy as the other answers because the first text has to be centered and if you only use two elements in your Column then no matter what you do it's either going to make the top item be off-center by half the height of the bottom text (as in using only two Expandeds) or the design will be rigid and therefore may not display correctly on different sized devices.
So, 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.
Only then will using "alignment: Alignment.center" give the needed result for the top text.
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,
),
),
),
),
),
],
),
],
),
);
}
}

Another way is to use an empty SizedBox at the start and the mainAxisAlignment: MainAxisAlignment.spaceBetween,
class Screen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Screen'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
height: 0.0,
width: 0.0,
),
Text('This text should be at the center of the column'),
Text('This text should be at the end of the column'),
],
),
);
}
}

One of the way could be using Expanded widget along with alignment as for the need
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Screen'),
),
body: Column(
// mainAxisAlignment: MainAxisAlignment.center, // this is wrong, it positions both the widgets in the center
children: <Widget>[
Expanded(child: Container(alignment:Alignment.bottomLeft,child: Text('This text should be at the center of the column'))),
Expanded(child: Container(alignment: Alignment.bottomLeft, child: Text('This text should be at the end of the column'))),
],
),
);
}

Related

create scaffold with global container on top

I need a global area on top to show some ads. This are remains the same for all pages and widgets. So far I've got this:
Stack(
children: [
Column(
children: <Widget>[
Container(
color: Theme.of(context).primaryColor,
width: double.infinity,
height: bannerHeight,
child: MY_BANNER,
),
Expanded(child: child!), // this has to be dynamic
],
),
],
);
What's the problem? It creates an extra padding for the AppBar that I don't know how to remove:
Instead of creating a space on top of AppBar you can put your banner ads below it. For this you can make a custom MyAppBar widget and use this custom widget inside the Scaffold.
class MyAppBar extends StatelessWidget with PreferredSizeWidget {
final String title;
MyAppBar(this.title) : preferredSize = const Size.fromHeight(110);
#override
final Size preferredSize;
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.max,
children: [
AppBar(
title: Text(
title,
),
),
Center(
child: Container( // Place your ad here
color: Colors.red,
width: MediaQuery.of(context).size.width / 2,
height: 50,
),
),
],
);
}
}
and use it like
Scaffold(
appBar: MyAppBar(
"Hello App",
),
),
return Scaffold(
body: SafeArea(
child: Column(
children: [
Row(
children: [
Expanded(
child: MY_BANNER
),
],
),
Expanded(child: child!),
],
),
),
);

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,
),
),
),
),
),
],
),
],
),
);
}
}

How to make row/column of non-fixed sized parent fill the whole space

I am trying to do it with Expanded but I am getting 'RenderFlex children have non-zero flex but incoming width constraints are unbounded.' which is expected because the size of parent is not defined.
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text(
'something',
style: Theme.of(context).primaryTextTheme.headline2,
),
Expanded(
child: Container(),
),
]
)
If your Row is wrapped within an Column widget it will take up all of the available space and give your Row the required Parent width. This will be rendered at the top of the Column.
import 'package:flutter/material.dart';
class TestScreen extends StatelessWidget {
static const routeName = '/testScreen';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test'),
),
body: Column(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text(
'something',
style: Theme.of(context).primaryTextTheme.headline2,
),
Expanded(
child: Container(),
),
],
),
],
),
);
}
}
If you want the widget to take up entire height as well then wrap it again with an Expanded
import 'package:flutter/material.dart';
class TestScreen extends StatelessWidget {
static const routeName = '/testScreen';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test'),
),
body: Column(
children: <Widget>[
Expanded(
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text(
'something',
style: Theme.of(context).primaryTextTheme.headline2,
),
Expanded(
child: Container(),
),
],
),
),
],
),
);
}
}
If you do not give the Row this fixed area it will expand indefinitely off the side of your screen
Non Column solution
body: SingleChildScrollView(
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text(
'something',
style: Theme.of(context).primaryTextTheme.headline2,
),
Expanded(
child: Container(),
),
],
),
),

textAlign: Textalign.center not coming in center?why

class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: CircleAvatar(
radius: 40.0,
child: Image.asset('images/pic.jpg'),
),
),
Text(
"michael dub",
),
Text("FLUTTER DEVELOPER"),
Container(
width: 350.0,
height: 70.0,
child: Card(
child: Row(
children: <Widget>[
Icon(
Icons.phone,
),
Text(
"+12-345-678-910",
textAlign: TextAlign.center,
),
],
)))
],
),
),
);
}
}
in your column, try crossAxisAlignment: CrossAxisAlignment.stretch
EDIT:
if you're trying to do what I think you're trying to do, try adding
mainAxisAlignment: MainAxisAlignment.center
to your row
you need to wrap your text widget with Expanded widget. Default Row Widget will not take full width and it is creating issue.
Check out following code.
Expanded(
child: Text(
"+12-345-678-910",
textAlign: TextAlign.center,
),
),

Creating a Card with a center icon and bottom row

I'm new to Flutter and I'm attempting to create a Card that has a bottom row and a center Icon or Text. I'm sure this is pretty easy, but I'm struggling . I'm not sure of the best way to do this. Should I create a column with two nested columns?
import 'package:flutter/material.dart';
class Test extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Card(
elevation: 5,
margin: EdgeInsets.fromLTRB(16, 16, 16, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(
Icons.ac_unit,
color: Colors.blue,
),
Row(
children: <Widget>[
Expanded(
child: Container(
height: 50,
color: Colors.blue,
),
)
],
)
],
),
),
);
}
}
Try out this code.
Column(
children: <Widget>[
Expanded(
child: Center(
child: Text('\$250'),
),
),
Text('\$ Total'),
],
)
I'm using Expanded to use entire space of container (Column) which will push text to the bottom. And using Center to put a widget (Text in this code) in the middle of the container.