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:
Related
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")
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,),
],
)
),
I want to set a black heart between "m" and "ms". and also I want to use "TextAlign.justify". if I use "TextAlign.center" then it's working fine. but if I use "TextAlign.justify" so the black heart is not set in the correct place. If I remove the "WidgetSpan" widget and add "TextSpan" for a black heart so also it's working. but I want to add bottom padding.
Please guys help me.
Thanks
Text.rich(
TextSpan(
children: <InlineSpan>[
TextSpan(
text: MyString.txtAboutUs ,
style: TextStyle(
fontSize: FontSize.size14,
fontFamily: MyFont.poppins_regular)),
TextSpan(
text: " m",
children: <InlineSpan>[
WidgetSpan(
baseline: TextBaseline.ideographic,
alignment: PlaceholderAlignment.top,
child: Container(
padding: EdgeInsets.only(bottom: 3),
child: Text("🖤", style: TextStyle(
fontSize: FontSize.size8,
fontFamily: MyFont.poppins_regular) ),
)
),
TextSpan(
text: "ms ",
style: TextStyle(
fontSize: FontSize.size14,
fontFamily: MyFont.poppins_medium,
color: Colors.black,
fontWeight: FontWeight.bold)),
],
style: TextStyle(
fontSize: FontSize.size14,
fontFamily: MyFont.poppins_medium,
color: Colors.black,
fontWeight: FontWeight.bold)),
TextSpan(
text: MyString.txtAboutImmediately,
style: TextStyle(
fontSize: FontSize.size14,
fontFamily: MyFont.poppins_regular)),
],
),
textAlign: TextAlign.justify,
),
Try to below simple Text Widget
Text('you add 🖤 here'),
// OR
Text('you add \u{2764} here} '),
Updated Answer using RichText
Center(
child: Text.rich(
TextSpan(
children: <TextSpan>[
TextSpan(
text: 'You add ',
style: TextStyle(
fontSize: 10.0,
color: Colors.black,
),
),
TextSpan(
text: '🖤',
),
TextSpan(
text: 'Here',
),
],
),
textAlign: TextAlign.center,
style: TextStyle(fontSize: 10.0,),
),
),
Screen like
replace padding with transform.
WidgetSpan(
baseline: TextBaseline.ideographic,
alignment: PlaceholderAlignment.top,
child: Container(
transform: Matrix4.translationValues(0, -3, 0),
margin: EdgeInsets.only(bottom: 8),
child: Text(
"🖤",
style: TextStyle(
// fontSize: FontSize.size8,
// fontFamily: MyFont.poppins_regular,
),
),
),
),
I have the next widget:
class PoinstsDisplayState extends State<PoinstsDisplay> {
#override
Widget build(BuildContext context) {
return new Container(
width: MediaQuery.of(context).size.width*0.9,
margin: EdgeInsets.only(top: 20.0),
padding: EdgeInsets.all(10.0),
decoration: BoxDecoration(
color: Color(0xff2b2b2b),
borderRadius: BorderRadius.circular(10.0),
),
child: new Text(
'5000 Pts',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
fontFamily: 'Karla'
),
)
);
}
}
That looks like this:
That have the perfect position, now I want to style the number 5000 and the 'Pts' text separately but I have not managed to make it work (center two text like the image), I am try with a Row, more Containers, the Center Class etc, etc.
This is a perfect use of the rich text constructor with a couple of TextSpans.
Taking from the 2nd sample in the flutter docs, try:
Text.rich(
TextSpan(
children: <TextSpan>[
TextSpan(text: '5000 ', style: TextStyle(color: Colors.white)),
TextSpan(text: 'pts', style: TextStyle(color: Colors.red)),
],
),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
fontFamily: 'Karla'
),
)
You probably want to use some combination of mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, and placing some padding or an empty Container with a set width between the two text widgets for the space.
class PointsDisplay extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
'5000',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25.0,
fontFamily: 'Karla'
),
),
Container(width: 5.0,height: 0,),
Text(
'Pts',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
fontFamily: 'Times'
),
),
],
);
}
}
When you have a WidgetSpan as a children of TextSpan, you can use:
WidgetSpan(
child: Icon(Icons.access_time),
alignment: PlaceholderAlignment.middle
)
Use RichText: Video | Document
RichText(
textAlign: TextAlign.center,
text: TextSpan(
text: 'Hello ',
children: const <TextSpan>[
TextSpan(text: 'bold', style: TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: ' world!'),
],
),
)
i see this code for rich text in flutter:
return Row(
children: <Widget>[
?
Container(
child: RichText(
text: TextSpan(
text: "Hello",
style: TextStyle(fontSize: 20.0,color: Colors.black),
children: <TextSpan>[
TextSpan(text:"Bold"),
style: TextStyle( fontSize: 10.0, color: Colors.grey),
),
],
),
),
)
this print
Hellobold
but i need to separe both text one aling to left other to right, like this
Hello bold
how i do this?
thanks
I don't know your exact Use Case - But One way of getting what you require:
Row(
children: <Widget>[
Expanded(
child: RichText(
text: TextSpan(children: [
TextSpan(text: 'Singh', style: TextStyle(fontSize: 22.0,color: Colors.grey))
])),
),
RichText(
text: TextSpan(children: [
TextSpan(text: 'Kaur', style: TextStyle(fontSize: 28.0,color: Colors.redAccent))
])),
],
),
if you want to use textalign in RichText use WidgetSpan and Text widget
WidgetSpan(
child: Text(
'your text',
textAlign: TextAlign.left,
textDirection: TextDirection.ltr,
),
),
I think this will can help you:
RichText(
text: TextSpan(
children: [
WidgetSpan(
child: Padding(
padding: const EdgeInsets.fromLTRB(1, 10, 10, 0),
child: Icon(
Icons.developer_mode_sharp,
),
),
),
TextSpan(
text: ' Tinkle is Powered By:',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black),
),
],
),
),
Text(
'Together Marketing Agency',
textAlign: TextAlign.right,
style: TextStyle(
fontSize: 16, color: Colors.black, fontWeight: FontWeight.w500),
),
To Align your Text when using RichText widget, Simply add textAlign: TextAlign() to your RichText Property.
return Row(
children: <Widget>[
?
Container(
child: RichText(
textAlign: TextAlign.justify //You can change it to any aligment style that you want.
text: TextSpan(
text: "Hello",
style: TextStyle(fontSize: 20.0,color: Colors.black),
children: <TextSpan>[
TextSpan(text:"Bold"),
style: TextStyle( fontSize: 10.0, color: Colors.grey),
),
],
),
),
)
Container(
width: double.infinity,
child: Text.rich(
TextSpan(
text: 'This is a ',
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: 'bold',
style: TextStyle(fontWeight: FontWeight.bold),
recognizer: TapGestureRecognizer()
..onTap = () {
// Handle the tap event
},
),
TextSpan(text: ' and normal text'),
],
),
textAlign: TextAlign.center,
),
)