Under which circumstances textAlign property works in Flutter? - flutter

In the code below, textAlign property doesn't work. If you remove DefaultTextStyle wrapper which is several levels above, textAlign starts to work.
Why and how to ensure it is always working?
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new DefaultTextStyle(style: new TextStyle(fontSize: 10.0), child: new Column(children: <Widget>[
new Text("Should be left", textAlign: TextAlign.left,),
new Text("Should be right", textAlign: TextAlign.right,)
],))
);
}
}
Both approaches, suggested by Remi apparently don't work "in the wild". Here is an example I nested both inside rows and columns. First approach doesn't do align and second approach makes application just crash:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new Directionality(textDirection: TextDirection.ltr, child: new DefaultTextStyle(
style: new TextStyle(fontSize: 10.0, color: Colors.white),
child: new Column(children: <Widget>[
new Row(children: <Widget>[
new Container(color: Colors.grey, child: new Column(children: <Widget>[
new Align(alignment: Alignment.centerLeft, child: new Text("left")),
new Align(alignment: Alignment.centerRight, child: new Text("right")),
],)),
new Container(color: Colors.grey, child: new Column(children: <Widget>[
new Align(alignment: Alignment.centerLeft, child: new Text("left")),
new Align(alignment: Alignment.centerRight, child: new Text("right")),
],)),
],),
/*new Row(children: <Widget>[
new Container(color: Colors.grey, child: new Column(children: <Widget>[
new SizedBox(width: double.infinity, child: new Text("left", textAlign: TextAlign.left,)),
new SizedBox(width: double.infinity, child: new Text("right", textAlign: TextAlign.right)),
],)),
new Container(color: Colors.grey, child: new Column(children: <Widget>[
new SizedBox(width: double.infinity, child: new Text("left", textAlign: TextAlign.left)),
new SizedBox(width: double.infinity, child: new Text("right", textAlign: TextAlign.right)),
],)),
],)*/]
)));
}
}
What I get from code is
i.e. text is centered, ignoring alignment of Align element.

DefaultTextStyle is unrelated to the problem. Removing it simply uses the default style, which is far bigger than the one you used so it hides the problem.
textAlign aligns the text in the space occupied by Text when that occupied space is bigger than the actual content.
The thing is, inside a Column, your Text takes the bare minimum space. It is then the Column that aligns its children using crossAxisAlignment which defaults to center.
An easy way to catch such behavior is by wrapping your texts like this :
Container(
color: Colors.red,
child: Text(...)
)
Which using the code you provided, render the following :
The problem suddenly becomes obvious: Text don't take the whole Column width.
You now have a few solutions.
You can wrap your Text into an Align to mimic textAlign behavior
Column(
children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Container(
color: Colors.red,
child: Text(
"Should be left",
),
),
),
],
)
Which will render the following :
or you can force your Text to fill the Column width.
Either by specifying crossAxisAlignment: CrossAxisAlignment.stretch on Column, or by using SizedBox with an infinite width.
Column(
children: <Widget>[
SizedBox(
width: double.infinity,
child: Container(
color: Colors.red,
child: Text(
"Should be left",
textAlign: TextAlign.left,
),
),
),
],
),
which renders the following:
In that example, it is TextAlign that placed the text to the left.

Specify crossAxisAlignment: CrossAxisAlignment.start in your column

In Colum widget Text alignment will be centred automatically, so use crossAxisAlignment: CrossAxisAlignment.start to align start.
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(""),
Text(""),
]);

textAlign property only works when there is a more space left for the Text's content. Below are 2 examples which shows when textAlign has impact and when not.
No impact
For instance, in this example, it won't have any impact because there is no extra space for the content of the Text.
Text(
"Hello",
textAlign: TextAlign.end, // no impact
),
Has impact
If you wrap it in a Container and provide extra width such that it has more extra space.
Container(
width: 200,
color: Colors.orange,
child: Text(
"Hello",
textAlign: TextAlign.end, // has impact
),
)

Set alignment: Alignment.centerRight in Container:
Container(
alignment: Alignment.centerRight,
child:Text(
"Hello",
),
)

You can use the container, It will help you to set the alignment.
Widget _buildListWidget({Map reminder}) {
return Container(
color: Colors.amber,
alignment: Alignment.centerLeft,
padding: EdgeInsets.all(20),
height: 80,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
alignment: Alignment.centerLeft,
child: Text(
reminder['title'],
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 16,
color: Colors.black,
backgroundColor: Colors.blue,
fontWeight: FontWeight.normal,
),
),
),
Container(
alignment: Alignment.centerRight,
child: Text(
reminder['Date'],
textAlign: TextAlign.right,
style: TextStyle(
fontSize: 12,
color: Colors.grey,
backgroundColor: Colors.blue,
fontWeight: FontWeight.normal,
),
),
),
],
),
);
}

For maximum flexibility, I usually prefer working with SizedBox like this:
Row(
children: <Widget>[
SizedBox(
width: 235,
child: Text('Hey, ')),
SizedBox(
width: 110,
child: Text('how are'),
SizedBox(
width: 10,
child: Text('you?'))
],
)
I've experienced problems with text alignment when using alignment in the past, whereas sizedbox always does the work.

You can align text anywhere in the scaffold or container except center:-
Its works for me anywhere in my application:-
new Text(
"Nextperience",
//i have setted in center.
textAlign: TextAlign.center,
//when i want it left.
//textAlign: TextAlign.left,
//when i want it right.
//textAlign: TextAlign.right,
style: TextStyle(
fontSize: 16,
color: Colors.blue[900],
fontWeight: FontWeight.w500),
),

Text(' Use textAlign: TextAlign.center',
style: TextStyle(fontWeight: FontWeight.w900,fontSize: 20,),
textAlign: TextAlign.center,)
Always use textAlign When trying to direct you text

Related

Flutter how to move an item to the bottom

I have this two items that once needs to appear in the middle but the other other needs to move to the bottom.
import 'package:flutter/material.dart';
class WelcomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'K',
style: TextStyle(
fontSize: 200,
color: Colors.white,
decoration: TextDecoration.none,
fontStyle: FontStyle.italic,
),
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [Text('hello')],
)
],
),
);
}
}
This is how it looks.
I want to move the Hello Text to the bottom. How can I do that?
You need to use two things for that, to make it work more efficiently. These are:
Expanded Class -> This will provide space, that is, takes up the remaining space
Align class -> This will help you to align the item
Please Note: Align(), itself, cannot aligns, the item, unless space is given. If you just use the Align(), you will not see any change, cos Text('Hello') looks for space, but no space is there.
Code
Container(
width: double.infinity, // <-- Takes up total width of the device
height: double.infinity, // <-- Takes up the total height of the device
color: Colors.blue,
child: Column(
children: [
Expanded(
flex: 2, // <-- Flex takes care of the remaining space ratio
child: Center(
child: Text(
'K',
style: TextStyle(
fontSize: 200,
color: Colors.white,
decoration: TextDecoration.none,
fontStyle: FontStyle.italic,
),
)
)
),
Align(
alignment: Alignment.bottomCenter,
child: Text('Hello', style: TextStyle(color: Colors.white, fontSize: 17.0))
)
]
)
)
Result
If you don't want your K text to move on top, you would have to use Stack. This way, your widget inside can position themselves anywhere they want.
Stack(
alignment:Alignment.center,
children:[
Text("K"),
Align(
alignment:Alignment.bottomCenter,
child:Text("hello"),
),
]
),
Take a look at the stack widget here: https://www.youtube.com/watch?v=liEGSeD3Zt8
return Container(
color: Colors.blue,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Spacer(),
Text(
'K',
style: TextStyle(
fontSize: 200,
color: Colors.white,
decoration: TextDecoration.none,
fontStyle: FontStyle.italic,
),
),
Spacer(),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [Text('hello')],
)
],
),
);
how about this way? add two Spacer

How to center Column widget horizontally in Flutter

I was learning Flutter and wanted to learn to how structure layout. Thus, I decided to use column widget and wanted to ask how to center horizontally column widget having this code: import
'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: MaterialApp(
home: Scaffold(
backgroundColor: Colors.teal,
body: SafeArea(
child: Column(
children: <Widget>[
CircleAvatar(
radius: 50.0,
backgroundImage: AssetImage('images/avatar.jpeg'),
),
Text('SAM',
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 50.0,
color: Colors.white,
fontWeight: FontWeight.bold)),
Text('Flutter developer',
style: TextStyle(
// fontFamily: 'Pacifico',
fontSize: 30.0,
color: Colors.white,
fontWeight: FontWeight.bold))
],
))),
),
);
}
}
You can do this by setting the Column crossAxisAlignment property to CrossAxisAlignment.center
Try wrapping your Column in a Container widget and give it a width property.
Check the code below:
It works perfectly:
'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: MaterialApp(
home: Scaffold(
backgroundColor: Colors.teal,
body: SafeArea(
Container(
// set the height property to take the screen width
width: MediaQuery.of(context).size.width,
child: Column(
// set the crossAxisAlignment property to center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
CircleAvatar(
radius: 50.0,
backgroundImage: AssetImage('images/avatar.jpeg'),
),
Text('SAM',
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 50.0,
color: Colors.white,
fontWeight: FontWeight.bold)),
Text('Flutter developer',
style: TextStyle(
// fontFamily: 'Pacifico',
fontSize: 30.0,
color: Colors.white,
fontWeight: FontWeight.bold))
],
))),
),
),
);
}
}
I hope this helps.
The problem is that your screen is not tacking whole width, so it is centre widget, whatever sized is used.
To used whole width you can provide container size to max size, which will force widget to use full width and it will centre widget.
MaterialApp(
home: Scaffold(
backgroundColor: Colors.teal,
body: SafeArea(
child: Container(
width: MediaQuery.of(context).size.width, // added
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
CircleAvatar(
radius: 50.0,
backgroundImage: AssetImage('assets/images/crown 1.png'),
),
Text('SAM',
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 50.0,
color: Colors.white,
fontWeight: FontWeight.bold)),
Text('Flutter developer',
style: TextStyle(
// fontFamily: 'Pacifico',
fontSize: 30.0,
color: Colors.white,
fontWeight: FontWeight.bold))
],
),
))),
);
Case 1: If you want Column to be center aligned:
//First Way: Use Column Widget inside Center Widget
Center(
child: Column(
children: <Widget>[]
)
//Second Way: Use Container Widget and set alignment to center
Container(
alignment: Alignment.center,
child: Column(
children: <Widget>[]
)
)
Case 2: If you want Column children to be center aligned
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[]
)
if you want to align widgets in center (vertically and horizontally), you can use
Center(
child: Column(
children: <Widget>[]
)
if you want to align horizontally but at the top of the screen then
Column(
crossAxisAlignment: CrossAxisAlignment.stretch, // to cover all the area
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [Text("test data")],
)
],
)
worked for me.
And if you want to center vertically and at the beginning of the screen then
Row(
crossAxisAlignment: CrossAxisAlignment.stretch, // to cover all the area
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [Text("test data")],
)
],
works as well.

Flutter web - setting height to 100% and not 100vh

In HTML creating a page that is divided into 2 columns that span 100% of the screen height is easy
<div id="row">
<div id="column1" style="width:75%; height:100%"></div>
<div id="column2" style="width:25%; height:100%"></div>
</div>
Using Flutter this seems more complicated than it should be, i tried to achieve the above in a couple of ways: (The page's outline is CustomScrollView -> SliverToBoxAdapter -> Row -> Columns)
Using MediaQuery to set the columns' height as deviceSize.height. This failed because as the left column got bigger than the right column, the right column did not expand in size to match.
Using Expanded or Flexible (tight or loose) to try and expand the height. This did not work.
My question is how do i achieve 100% height and not 100vh height in Flutter web?
Edit:
This illustrates the problem, the right column is not expanding in size to match the left column.
CustomScrollView(
slivers: <Widget>[
SliverFillRemaining(
child: Container(
color: Colors.purple,
child: SingleChildScrollView(
child: Row(
children: <Widget>[
Container(
color: Colors.blue,
child: Column(
children: <Widget>[
Text("test"),
SizedBox(height: 300),
Text("test"),
SizedBox(height: 300),
Text("test"),
SizedBox(height: 300),
Text("test"),
SizedBox(height: 300),
],
),
),
Container(
color: Colors.yellow,
child: Column(
children: <Widget>[Text("test")],
),
),
],
),
),
),
),
],
);
Not sure if this is what you want. But based on your statement I think you are looking for two column layout as in here and as shown below in the image.
Following is the code for the same. You can adjust the flex value in the Expanded widget to acquire the required screen width ratio. but if you want to adjust the width each columns like using a drag handle or so, then this alone wont suffice.
import 'package:flutter/material.dart';
class FullHeightDemo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Row(
children: <Widget>[
Expanded(
flex: 4,
child: Container(
color: Colors.red,
child: Center(
child: Text(
'Column-1',
style:
TextStyle(fontWeight: FontWeight.bold, color: Colors.black),
),
),
),
),
Expanded(
flex: 1,
child: Container(
child: Container(
color: Colors.teal,
child: Center(
child: Text(
'Column-2',
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.black),
),
),
),
),
)
],
));
}
}
Specifying the height using MediaQuery inside a Scrollable widget could help
Following code places the columns inside a SingleChildScrollableView widget and specifies the height of the container based on MediaQuery to achieve the same. Will this help.? The LayoutBuilder is only there to show that the using the height from its constraints could also lead to error since in this case its height is also infinite.
import 'package:flutter/material.dart';
class FullHeightDemo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: LayoutBuilder(
builder: (context, constraints) {
var size = MediaQuery.of(context).size;
return Container(
child: Row(
children: <Widget>[
Container(
height: size.height,
// height: constraints.maxHeight,
width: constraints.maxWidth / 2,
color: Colors.red,
child: Center(
child: Text(
'Column 1',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
),
),
Container(
color: Colors.green,
height: size.height,
// height: constraints.maxHeight,
width: constraints.maxWidth / 2,
child: Center(
child: Text(
'Column 2',
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.black),
),
),
)
],
),
);
},
),
);
}
}

How to remove the space between rows in card (Flutter)

I used a card widget in my flutter App that has two rows, the problem that I have is a large space appeared between the two rows as you can see in the following image
how can fix this problem ?
my code that i tried it here :
return Card(
child: Container(
alignment: FractionalOffset.center,
child: Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
child: ListTile(
title: Text(snapshot.data[index].data["title"],
textDirection: TextDirection.rtl,
style: TextStyle(fontSize: 14.0,
fontFamily: 'Cairo',
fontWeight: FontWeight.bold),),
onTap: () => navigateToDetails(snapshot.data[index]),
),
),
),
//SizedBox(width: 1.0),
Expanded(
flex: 1,
child: Container(child: Image.network(snapshot.data[index].data["image_url"],height: 80.0,width: 80.0)),
),
],
),
),
);
add MainAxisAlignment:MainAxisAlignment.center property to your Row widget
followed code should work for you check this out.
return Card(
child: Container(
alignment: FractionalOffset.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
child: ListTile(
title: Text(
snapshot.data[index].data["title"],
textDirection: TextDirection.rtl,
style: TextStyle(
fontSize: 14.0,
fontFamily: 'Cairo',
fontWeight: FontWeight.bold),
),
onTap: () => navigateToDetails(snapshot.data[index]),
),
),
),
//SizedBox(width: 1.0),
Expanded(
flex: 1,
child: Container(
child: Image.network(snapshot.data[index].data["image_url"],
height: 80.0, width: 80.0)),
),
],
),
),
);
you are using expanded widget inside row so that both the widget try to get same width and also try to cover whole width possible.
so that, if you want to remove space between row widget then remove expanded widget and play with MainAxisAlignment property of Row to arrange or manage the space.
you can use values like:
MainAxisAlignment.spaceBetween and MainAxisAlignment.spaceEvenly

Flutter - Text inside an Expanded Widget within a Column overflowing

What I want to achieve is to have a text widget inside a Column of fixed height. When the text is long I want the overflow property which is set to TextOverflow.ellipsis to kick in. The Text widget has its maxLines property set to a high value to allow it to wrap down. But there are other widgets in the column too, both before and after the text widget. The text widget is in an Expanded widget so that it takes up as much room in the column. Full code is pasted below.
The problem with this setup is that the text is overflowing its container parent. I have a border decoration on the container that shows this happening. Why is this happening and how do I fix it.
import 'package:flutter/material.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Overflow"),
),
body: Center(
child: Container(
width: 200.0,
height: 250.0,
child: Card(
child: Column(children: <Widget>[
Image.asset(
"assets/bereket.jpg",
width: double.infinity,
fit: BoxFit.cover,
),
Expanded(
child: Container(
padding: EdgeInsets.all(8.0),
child: (Column(
children: [
Text(
"በረከት ስምኦን፡ «ወይዘሮ አና ጎሜዝ፤ እርስዎ አያገባዎትም! አርፈው ይቀመጡ በልልኝ»",
maxLines: 2,
style: Theme.of(context)
.primaryTextTheme
.subhead
.copyWith(
color: Colors.black,
),
overflow: TextOverflow.ellipsis),
Expanded(
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.green, width: 2.0),
),
child: Text(
"""ባለፉት ሁለት አስርት ዓመታት በኢትዮጵያ ፖለቲካ ከፍተኛ ተጽእኖ ፈጣሪ የነበሩት አቶ በረከት ስምኦን በቅርቡ ከብአዴን ማእከላዊ ኮሚቴ አባልነት መታገዳቸው ይታወሳል።
አቶ በርከት የብአዴን ውሳኔን በተመለከተ እና የወደፊት የፖለቲካ ህይወታቸው ምን ሊሆን እንደሚችል ለቢቢሲ አጋርተዋል።""",
maxLines: 10,
style: Theme.of(context)
.primaryTextTheme
.caption
.copyWith(color: Colors.black),
overflow: TextOverflow.ellipsis,
))),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: 20.0,
height: 20.0,
child: Image.asset("assets/bbc.png"),
),
SizedBox(width: 8.0),
Text('ቢቢሲ - ከሁለት ሰአት በፊት',
style: Theme.of(context)
.textTheme
.caption
.copyWith(fontSize: 10.0))
],
)
],
))))
]))),
),
),
);
}
}
Try wrapping your column with 'Flexible' instead of expandable.
I had the same issue with text overflowing in column and wrapping column itself with 'flexible' allowed to make text smaller.
Flexible(
child: Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text(
'Name',
style: CustomTextStyle.blueTitle14(context),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 4.0),
child: Text('Long text'),
),
],
),
),
),
Based on my experiences, you should assign a fixed width to the Container containing the overflowing text, as per this post. Flutter- wrapping text .
In present version of flutter (presently 3.0) you dont have to use Flexible or Expanded as Column's child automatically expandes to fill the content of child .
For ellipses define the maxLine attribute.
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
"This is very very very very very very very very very very very very very very very very very long text in Row 1 of Column",
maxLines: 2,
style: TextStyle(
backgroundColor: Colors.green, overflow: TextOverflow.ellipsis),
),
Text("This is very very long text in Row 2 of Column",
style: TextStyle(
overflow: TextOverflow.ellipsis,
backgroundColor: Colors.yellow))
],
)