How to make rich text align vertical center in flutter? - flutter

import 'package:flutter/material.dart';
class DraftPage extends StatefulWidget {
DraftPage({Key key}) : super(key: key);
#override
_DraftPageState createState() => _DraftPageState();
}
class _DraftPageState extends State<DraftPage> {
#override
Widget build(BuildContext context) {
final bottomTextStyle = TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.red,
);
return Scaffold(
appBar: AppBar(
title: Text('Test'),
),
body: Container(
alignment: Alignment.center,
width: 300,
height: 57,
decoration: BoxDecoration(
color: Colors.yellow,
),
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: 'AB',
style: bottomTextStyle,
),
TextSpan(
text: 'CD',
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.w500,
color: Colors.blue,
),
),
TextSpan(
text: 'EF',
style: bottomTextStyle,
),
],
),
textAlign: TextAlign.center,
),
),
);
}
}
As you can see, the AB and EF are at the bottom of CD though I had set TextAlign.center.
Is there any way let AB CD EF align vertical center?

Result
Code
Text.rich(
TextSpan(
children: <InlineSpan>[
TextSpan(
text: 'AB',
style: bottomTextStyle,
),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Text(
'CD',
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.w500,
color: Colors.blue,
),
),
),
TextSpan(
text: 'EF',
style: bottomTextStyle,
),
],
),
),

try this:
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: 'AB\n',
style: bottomTextStyle,
),
TextSpan(
text: 'CD\n',
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.w500,
color: Colors.blue,
),
),
TextSpan(
text: 'EF',
style: bottomTextStyle,
),
],
),
textAlign: TextAlign.center,
),

You can use row to center in a line
Container(
width: 300,
height: 57,
decoration: BoxDecoration(
color: Colors.yellow,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("AB", style: bottomTextStyle,),
Text("CD", style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.w500,
color: Colors.blue,
),),
Text("EF", style: bottomTextStyle,),
],
)
),

Related

How to align icons with richtext in two columns in Flutter?

I am having difficulties to align my icons with my two lines rich text in Flutter. As you can seen in the picture below, I want to align my ONE richtext widget with ONE icon. Example: Richtext containing "Revision Notes" and "Free notes." should be in the same line as the green icon tick. If I try using just one liner of text, the tick will align with it, but now if I have two liners rich text, it won't align.
Appreciate any help!
Picture:
Code:
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: const <TextSpan>[
TextSpan(
text: 'Revision notes\n',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold)),
TextSpan(text: 'Free notes.'),
],
),
),
RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: const <TextSpan>[
TextSpan(
text: 'Quizzes\n',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold)),
TextSpan(text: 'Free quizzes.'),
],
),
),
RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: const <TextSpan>[
TextSpan(
text: 'No Ads\n',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold)),
TextSpan(text: 'All annoying ads gone.'),
],
),
),
RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: const <TextSpan>[
TextSpan(
text: '10 Flashcards\n',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold)),
TextSpan(text: 'Create your own 10 flashcards.'),
],
),
),
RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: const <TextSpan>[
TextSpan(
text: 'Textbooks\n',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold)),
TextSpan(text: 'Download all textbooks in PDF.'),
],
),
),
RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: const <TextSpan>[
TextSpan(
text: 'State Trial Papers\n',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold)),
TextSpan(text: 'Download all trial papers in PDF.'),
],
),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(
Icons.done_rounded,
color: Colors.green,
size: 24.0,
),
Icon(
Icons.done_rounded,
color: Colors.green,
size: 24.0,
),
Icon(
Icons.done_rounded,
color: Colors.green,
size: 24.0,
),
Icon(
Icons.done_rounded,
color: Colors.green,
size: 24.0,
),
Icon(
Icons.close,
color: Colors.red,
size: 24.0,
),
Icon(
Icons.close,
color: Colors.red,
size: 24.0,
),
],
),
]),
Solution 1
I would first try to put the rich text widget and the corresponding icon in one Row centering elements vertically, instead of two separate columns which makes it a little more complicated. Like this (just 1 a row example):
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: const <TextSpan>[
TextSpan(
text: 'Revision notes\n',
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold)),
TextSpan(text: 'Free notes.'),
],
),
),
const Icon(
Icons.done_rounded,
color: Colors.green,
size: 24.0,
),
],
),
],
)
The mainAxisAlignment attribute will align your elements pushing them one to the left and one to the right of the screen.
The crossAxisAlignment attribute will align the element by centering them vertically.
Solution 2
If you still need two columns, then you can read the heights of the single rows on the left with LayoutBuilder and use that size for the height of the icon.
Another way is giving all rows fixed height since you always have title and subtitle of the same sizes (better test smaller screens for this one), so you work around the problem entirely. I would leave this one as last solution.
Use a Row and put a Space between them (i used a Spacer here, you can use a SizedBox or something like that):
Row(
children: [
RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: const <TextSpan>[
TextSpan(
text: 'Revision notes\n',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold)),
TextSpan(text: 'Free notes.'),
],
),
),
Spacer(),
Icon(
Icons.close,
color: Colors.red,
size: 24.0,
),
],
),
I recommend that you make a widget for create each line, so your code will be more readable. Look my example:
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: const Text('Material App Bar'),
),
backgroundColor: Colors.amber,
body: SizedBox(
width: 300,
child: ListView(
children: const [
CustomListTile(
title: 'Revision notes',
subtitle: 'Free notes',
trailing: Icon( Icons.check, color: Colors.greenAccent, )),
CustomListTile(
title: 'Quizzes',
subtitle: 'Free quizzes',
trailing: Icon( Icons.check, color: Colors.greenAccent, )),
CustomListTile(
title: 'No Ads',
subtitle: 'All ... ',
trailing: Icon( Icons.check, color: Colors.greenAccent, )),
CustomListTile(
title: 'Flashcards',
subtitle: 'Create your own...',
trailing: Icon( Icons.close, color: Colors.redAccent, )),
CustomListTile(
title: 'Textbooks',
subtitle: 'Download all ...',
trailing: Icon( Icons.close, color: Colors.redAccent, )),
],
),
),
),
);
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class CustomListTile extends StatelessWidget {
const CustomListTile({
super.key,
required this.title,
required this.subtitle,
required this.trailing
});
final String title;
final String subtitle;
final Icon trailing;
#override
Widget build(BuildContext context) {
return ListTile(
title: Text( title, style: const TextStyle( fontSize: 20 ), ),
subtitle: Text( subtitle, style: const TextStyle( fontSize: 14 ), ),
trailing: trailing,
);
}
}
This was my output:

Align text vertically flutter

I think the best way to explain my issue is with images, so this is what I want to achieve, dont mind the styling of either image.
But when I try to implement it myself, the bottom text gets indented.
Here are my code. Note I am new to flutter, so tips are also appreciated.
SizedBox(
width: 580,
height: 95,
child: Material(
color: panelBackground,
borderRadius: BorderRadius.circular(5),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 25),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
const Text(
"Project Name",
style: TextStyle(
fontSize: 36,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 5),
RichText(
text: const TextSpan(
text: "Made by: ",
style: TextStyle(
fontSize: 14,
color: Color(0xFF838383),
),
children: [
TextSpan(
text: '/',
style: TextStyle(
color: Colors.amber,
fontWeight: FontWeight.bold)),
TextSpan(
text: '6u5t4v',
style: TextStyle(
color: Colors.amberAccent,
letterSpacing: 2,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic))
])),
],
),
Column(
children: [Text("rating here")],
),
const SidebarIcon(
icon: Icon(Icons.save),
)
],
),
),
),
),
Just set crossAxisAlignment to start
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Project Name",
style: TextStyle(
fontSize: 36,
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
you have to warp Text with Align Widget and given following code
Align(alignment:Alignment.topLeft, child:"your Widget")

big text in title and trailing

My code prints device characteristics. But if the text is too long, then the text is displayed ugly(as in the photo 1). I tried to fix it in different ways, but only title changes for me, trailing remains unchanged.
Can it be done in this way, if the text is long, then title is displayed in one line, and the next trailing (as in the photo 2)?
body: SingleChildScrollView(
child: Align(
alignment: Alignment.topCenter,
child: Column(
children: [
Container(
constraints: const BoxConstraints(maxWidth: 800),
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(5.0),
),
child: Card(
child: Column(
children: [
ListTile(
title: const Text('Brand:', style: TextStyle(fontWeight: FontWeight.w400, fontSize: 25)),
trailing: Text('${device.brand} ', style: const TextStyle(fontWeight: FontWeight.w400, fontSize: 20 ))),
const Divider(color: Colors.black, endIndent: 10, indent: 10),
ListTile(
title: const Text('Operation system:', style: TextStyle(fontWeight: FontWeight.w400, fontSize: 25)),
trailing: Text('${device.operation_system} ', style: const TextStyle(fontWeight: FontWeight.w400, fontSize: 20 ))),
const Divider(color: Colors.black, endIndent: 10, indent: 10),
ListTile(
title: const Text('Version of OS:', style: TextStyle(fontWeight: FontWeight.w400, fontSize: 25)),
trailing: Text('${device.version_OS} ', style: const TextStyle(fontWeight: FontWeight.w400, fontSize: 20 ))),
const Divider(color: Colors.black, endIndent: 10, indent: 10),
],
),
),
),
]
)
)
)
One option would be to remove trailing from ListTile and use RichText and TextSpan for title like so:
ListTile(
title: RichText(
text: TextSpan(
style: Theme.of(context).textTheme.headline6,
children: [
const TextSpan(
text: 'Version of OS: ',
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 25,
),
),
TextSpan(
text: '${device.version_OS}',
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 20,
),
),
],
),
),
),
Try below code hope its helpful to you.
Card(
child: ListTile(
leading: Text(
'Version of OS',
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 20,
overflow:TextOverflow.ellipsis,
),),
title: Text('Your version with version 1.0'),
trailing: Text('Nokia'),
),
),

set center text Flutter

I want to set layout Wedding Oraganizer , Prewedding text and Our services button to MainAxisAlignment.center and 345 Moo layout in bottom........................................................................................................................................
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.pink[200],
body: Padding(
padding: EdgeInsets.fromLTRB(30, 40, 30, 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Wedding Organizer',
style: TextStyle(
fontFamily: 'SourceSansPro',
fontWeight: FontWeight.bold,
fontSize: 35,
color: Colors.white),
),
Text(
'Pre-wedding, Photo, Party',
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 25.5,
color: Colors.white),
),
SizedBox(height: 20.0),
RaisedButton(
child: Text('Our services',
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 17,
color: Colors.white)),
color: Colors.red,
onPressed: () {},
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Text('345 Moo 1 Tasud Chiang Rai, Thailand',
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 17,
color: Colors.grey[300])),
),
)
],
))),
);
}
}
My result
I want to output:
You can use a Spacer widget to put spaces in between the views instead of using an Expanded and Align widget on the same Text.
I made modifications to your code and came up with the desired output:
Scaffold(
backgroundColor: Colors.pink[200],
body: Padding(
padding: EdgeInsets.fromLTRB(30, 40, 30, 10),
child: SizedBox.expand( // new line
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Spacer(), // new line
Text(
'Wedding Organizer',
style: TextStyle(
fontFamily: 'SourceSansPro',
fontWeight: FontWeight.bold,
fontSize: 35,
color: Colors.white),
),
Text(
'Pre-wedding, Photo, Party',
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 25.5,
color: Colors.white),
),
SizedBox(height: 20.0),
RaisedButton(
child: Text('Our services',
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 17,
color: Colors.white)),
color: Colors.red,
onPressed: () {},
),
Spacer(), // new line
Text('345 Moo 1 Tasud Chiang Rai, Thailand',
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 17,
color: Colors.grey[300]))
],
),
),
),
);
RESULT:
Here is a code what you want.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.pink[200],
body: Padding(
padding: EdgeInsets.fromLTRB(30, 40, 30, 10),
child: Column(
children: <Widget>[
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Wedding Organizer',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'SourceSansPro',
fontWeight: FontWeight.bold,
fontSize: 35,
color: Colors.white),
),
Text(
'Pre-wedding, Photo, Party',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 25.5,
color: Colors.white),
),
SizedBox(height: 20.0),
RaisedButton(
child: Text('Our services',
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 17,
color: Colors.white)),
color: Colors.red,
onPressed: () {},
),
],
),
),
Text('345 Moo 1 Tasud Chiang Rai, Thailand',
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 17,
color: Colors.grey[300])),
],
),
),
),
);
}
}

How do I handle this Text widget in Flutter?

I have a function that returns an AlertDialog. Here's a screenshot of what it looks like: https://i.stack.imgur.com/ZPVFI.jpg. And here's the code for it:
void _showDialog(BuildContext context, List details) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
titlePadding: const EdgeInsets.all(5),
contentPadding: const EdgeInsets.only(left: 10, right: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10))
),
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
details[3].toString(),
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 40)
),
]
),
content: Container(
color: Colors.green,
width: double.infinity,
height: 150,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text(
'Data: ',
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold)
),
Text(
details[0],
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20)
),
],
),
Row(
children: <Widget>[
Text(
'Tipologia: ',
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold)
),
Text(
details[2].toLowerCase(),
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20)
),
],
),
details[5] != ''
? Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
'Descrizione: ',
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold)
),
],
),
Container(
//width: 100,
child: Text(
details[5],
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20),
overflow: TextOverflow.ellipsis,
maxLines: 5,
textAlign: TextAlign.justify,
),
)
],
)
: Offstage(
child: Text('invisible')
),
Row(
children: <Widget>[
details[4] == 'SI'
? Text(
'Il voto fa media.',
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold)
)
: Text(
'Il voto non fa media.',
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold)
)
],
),
],
),
),
actions: <Widget>[
FlatButton(
child: Text(
"Chiudi",
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 15)
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
The rows containing "Data" and "Tipologia" are no issue. But after "Descrizione" there's a Text widget that contains a string of variable length. I'd like said text to be displayed on multiple lines, starting right after "Descrizione: " (just like "pratico" starts right after "Tipologia: "). How do I do it?
Edit: here's how it looks like now https://i.stack.imgur.com/fKajB.jpg
I'd suggest you go with RichText() instead of Row() with Texts
Just Like What follows
RichText(
textAlign: TextAlign.left,
text: TextSpan(
children: [
TextSpan(children: [
TextSpan(
text: 'Descrizione: ',
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold),),
TextSpan(
text: details[5],
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20),
),
]),
],
),
so your code should look like
void _showDialog(BuildContext context, List details) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
titlePadding: const EdgeInsets.all(5),
contentPadding: const EdgeInsets.only(left: 10, right: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10))
),
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
details[3].toString(),
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 40)
),
]
),
content: Container(
color: Colors.green,
width: double.infinity,
height: 150,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text(
'Data: ',
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold)
),
Text(
details[0],
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20)
),
],
),
Row(
children: <Widget>[
Text(
'Tipologia: ',
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold)
),
Text(
details[2].toLowerCase(),
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20)
),
],
),
details[5] != ''
? Column(
children: <Widget>[
RichText(
textAlign: TextAlign.left,
text: TextSpan(
children: [
TextSpan(children: [
TextSpan(
text: 'Descrizione: ',
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold),),
TextSpan(
text: details[5],
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20),
),
]),
],
)
: Offstage(
child: Text('invisible')
),
Row(
children: <Widget>[
details[4] == 'SI'
? Text(
'Il voto fa media.',
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold)
)
: Text(
'Il voto non fa media.',
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold)
)
],
),
],
),
),
actions: <Widget>[
FlatButton(
child: Text(
"Chiudi",
style: test.GoogleFonts.quicksand(color: Colors.black, fontSize: 15)
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
All you have to do is make a couple simple changes to your code
details[5] != ''
? Container(
width: double.infinity,
child: Row(
crossAxisAlignment: CrossAxisAlignment
.start, // This will change how the multi-line text is aligned
children: <Widget>[
Text(
'Descrizione: ',
style: test.GoogleFonts.quicksand(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.bold),
),
Flexible(
child: Text(
details[5],
style: test.GoogleFonts.quicksand(
color: Colors.black, fontSize: 20),
overflow: TextOverflow.ellipsis,
maxLines: 5,
textAlign: TextAlign.justify,
),
),
],
),
)
: Offstage(child: Text('invisible')),
Let me know if you need anything else