How to align an element in a flexible row in flutter? - flutter

I have a chat bubble with username, timestamp and chat message. It is divided into two rows.
First row is username and timestamp, second row is the chat message.
With the code below it looks like this:
I want the timestamp to be aligned right but the blue box should not be wider then the message line except the message is shorter than username and timestamp.
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
color: Colors.blue,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Username"),
Container(
color: Colors.red,
child: Text("5 mins ago"),
),
],
),
Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width - 120),
child: Text("A long message text 123456789")),
],
))
]);
}
}

Try this:
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text("Username"),
Spacer(),
Container(
color: Colors.red,
child: Text("5 mins ago"),
),
],
),

This will solve your problem.
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
color: Colors.blue,
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.7,
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Username"),
Container(
color: Colors.red,
child: Text("5 mins ago"),
),
],
),
Text("A long message text 123456789"),
],
),
)
],
);
}
}

Related

display widget in a center of column

In my page I have a customized Appbar then I want to display a message with icon, and it should be in the center of the page. i mean the customized Appbar is on the top then in the center of the page we have the icon with the message
child: Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Column(children: [
const CustomAppBar("Réglages et paramétrages", true, false,
returnToHistory: true),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment : MainAxisAlignment.center,
children: const [
Icon(Icons.warning, color: Color(0xFFFF9500), size: 100 ,),
],
),
Row(
children: const [
Text(
"be careful",
textAlign: TextAlign.center,)
],
)
],
),
]),
)),
));
you can try doing it this way by using an expanded widget to adjust the flex of the custom appbar and scrollview
return Scaffold(
body: SafeArea(
child: Column(
children: [
Expanded(
child: const CustomAppBar("Réglages et paramétrages", true, false,
returnToHistory: true),
),
Expanded(
flex: 7,
child: Center(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: const [
Icon(
Icons.warning,
color: Color(0xFFFF9500),
size: 100,
),
Text(
"be careful",
textAlign: TextAlign.center,
)
],
),
),
),
),
],
),
),
);
Remove SingleChildScrollView and wrap the inner column with an expanded widget.
You can create custom appbar as widget and provide on Scaffold's appbar. To do this, you need to implements PreferredSizeWidget
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
final String title;
const CustomAppBar({
Key? key,
required this.title,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: Text(title),
);
}
#override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
And your layout will be
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: const CustomAppBar(title: "Réglages et paramétrages"),
body: SafeArea(
child: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(Icons.warning, color: Color(0xFFFF9500)),
Text(
"be careful ",
textAlign: TextAlign.center,
)
],
),
]),
),
),
),
);
}
You can find more about ui/layout on flutter dev .

How to move a column to the end?

I am trying to align column with text to far right side of the window but somehow its not happening.
Tried with MainAxisAlignment.right , CrossAxisAlignment.right but somehow nothing is working out for me. Below is my Dart code,
class MVTHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
final height = MediaQuery.of(context).size.height;
final width = MediaQuery.of(context).size.width;
return Scaffold(
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
height: 550,
width: width,
child: Row(
children: [
Lottie.network(
'https://assets2.lottiefiles.com/datafiles/6WfDdm3ooQTEs1L/data.json'),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text("Multivariate Testing"),
Text('Run experiments to make key flows more effective.'),
// ignore: deprecated_member_use
TextButton(
onPressed: () {}, child: Text('Create Experiment')),
],
),
],
),
),
Container(
height: height,
width: width,
color: Colors.blueAccent,
)
],
),
));
}
}
I am seeing this in the output
While you are using the Row widget,
Add mainAxisAlignment: MainAxisAlignment.spaceBetween to it.
So your code should be like this
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // <-- Add this
children: [
Lottie.network(
When your Row's children are being rendered, by giving it MainAxisAlignment.spaceBetween, we are essentially telling the Row to place its children as far apart from each other as possible.
In the case of 2 children, it means 1 child to the extreme left and other to the extreme right.

Can't pull Row to down

I am trying to pull row to end of cross-axis (to bottom of the screen).
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(home: HomePage());
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
child: FlutterLogo(
size: 60,
),
),
Container(
child: FlutterLogo(
size: 60,
colors: Colors.red,
),
),
Container(
child: FlutterLogo(
size: 60,
colors: Colors.cyan,
),
),
],
));
}
}
But it's not working. What I am doing wrong?
You have no height set, so wrap the row in a widget that does
eg.
body: new Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
child: FlutterLogo(
size: 60,
),
),
Container(
child: FlutterLogo(
size: 60,
colors: Colors.red,
),
),
Container(
child: FlutterLogo(
size: 60,
colors: Colors.cyan,
),
),
],
)
]
),
There are other widgets that may be better but it depends on your content
https://api.flutter.dev/flutter/widgets/Align-class.html
https://api.flutter.dev/flutter/widgets/Positioned-class.html

How to align a container block to the end of a screen in Flutter?

In my Flutter project, I have initialized a container. Inside that Container I have a child 'column' and inside that I initialized 3 icons as my widget. So, I want to align the entire container block ( White block in the picture given below) to the end of the screen vertically. As far as I know from the documentation, that it can be done by the following command-
mainAxisAlignment: MainAxisAlignment.end
But it is not working here and showing the following output-
And here's my code-
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blue,
body: SafeArea(
child: Container(
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
)
),
),
),
);
}
}
So, I need help to know how I can align the white block into the end of the screen.
Yes this is happening because by default the container and the column are being aligned at the top left corner of the screen. MainAxisAlignment.end is actually working except that your column is so short that the .end and .start are essentially the same in terms of alignments. What you need to do instead is this:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blue,
body: SafeArea(
child: Align(
widthFactor: double.infinity,
heightFactor: double.infinity,
alignment: Alignment.bottomRight,
child: Container(
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
)
),
),
),
),
);
}
}
Try using crossAxisAlignment: CrossAxisAlignment.end instead of mainAxisAlingment.
EDIT:
As #Stephen mentioned you need full height in order to align the children.
Besides that you can also set full width to the container to get the children exactly at the end of the screen.
Note: The top-level widget usually constrains the sub-level widgets!
body: SafeArea(
child: Container(
color: Colors.white,
width: double.infinity,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
)
),
),
If you want to keep the height to be exactly that of the icons, you can use stack instead. It will look something like this:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blue,
body: SafeArea(
child: Stack(
children: <Widget>[
Positioned(
bottom: 0,
left: 0,
right: 0,
top: 0,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),
)
],
),
),
),
);
}
}
You just need to change mainAxisSize: MainAxisSize.min to mainAxisSize: MainAxisSize.max
Currently you column widget is only making itself as tall as it needs to be. changing to MainAxisSize.max will have it expand to the full height you are looking for.
Further reading:
https://medium.com/flutter-community/flutter-layout-cheat-sheet-5363348d037e

How to make a container scroll-able?

The current state of my code:
#override
Widget build(BuildContext context) {
return Container(
decoration: Grad2(),
padding: EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// ...
],
),
);
}
Which resulted in this beautiful Login page, but there is a problem (Bottom overflowed by 45 pixels when keyboard is up):
So i tried to use the SingleChildScrollView but then it resulted in a blank screen:
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: BoxConstraints().maxHeight),
child: Container(
decoration: Grad2(),
padding: EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// ...
],
),
),
),
);
}
But what I've got instead is a white screen. May I know why?
Try this:
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
decoration: Grad2(),
padding: EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// ...
],
),
),
);
}
Turns out, I could make the Container the height of the display, which works by setting the height of the Container to MediaQuery.of(context).size.height. In conclusion, use
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
decoration: Grad2(),
padding: EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// ...
],
),
),
);
}