Make text styling more effective with RichText widget

Darshan Kawar
Flutter Community
Published in
7 min readJul 26, 2019

As the name suggests, RichText provides more options to the way a text is displayed on the screen.

The style property of text widget is used to apply various styles to a text, but a limitation of it is, the style gets applied to the entire text irrespective of whether the text is a single line or multiline. Consider below snippet to render a single line of text on screen:

Container(
padding: EdgeInsets.all(10),
child: Center(
child: Text(
'The future belongs to those who prepare for it today.')
)
)

With above code, if we apply fontSize as 20, fontStyle as italic, the style will be applied to entire text, as below.

But, what if, we only want to underline a word from above text or show certain words of text as bold/italic or in different color and rest of the text as normal text?

RichText widget helps to answer and achieve the above cases.

RichText structure

RichText uses TextSpan as a parent object that has its own style property along with a text parameter which we can input the actual text. The parent object then can have a number of TextSpan objects as children who have their own style property that can be applied to respective text.

With above basic overview of RichText widget, let’s now see how we can make use of this widget in realtime.

Use case 1:

Most of the apps have login screen and an option to create an account. The create account section is usually a combination of regular text followed by colored text, like StackOverflow login screen as below:

The text Don't have an account? Sign up is a single line text, with last part of it being a clickable word to take user towards their sign up screen.

Approach

We’ll divide the text into two parts. In the first part, we’ll use the parent TextSpan object and will input the regular text Don't have an account? with the color property as Colors.black.

child: Center(
child: RichText(
text: TextSpan(
text: 'Don\'t have an account?', style: TextStyle(color: Colors.black, fontSize: 18),

In the second part, we’ll use children objects of TextSpan to input text Sign up and pass the color property as Colors.blue

children: <TextSpan>[
TextSpan(text: ' Sign up', style: TextStyle(color: Colors.blueAccent, fontSize: 18)
)
]

The output is:

Another cool thing about using RichText widget is that, the TextSpan the object comes with their own TapGestureRecognizer() which helps to implement onTap() action on specific parts of the text as needed. In our example, since the user can tap on Sign up text to navigate to the desired screen, we’ll make use of recognizer property that makes the text tappable, as shown in the entire code snippet below:

Note: Before using TapGestureRecognizer() , we’ll need to import ‘package:flutter/gestures.dart’;

Container(
padding: EdgeInsets.all(10),
child: Center(
child: RichText(
text: TextSpan(
text: 'Don\'t have an account?',
style: TextStyle(
color: Colors.black, fontSize: 18),
children: <TextSpan>[
TextSpan(text: ' Sign up',
style: TextStyle(
color: Colors.blueAccent, fontSize: 18),
recognizer: TapGestureRecognizer()
..onTap = () {
// navigate to desired screen
}
)
]
),
),
)
)

By using recognizer property, we won’t need to wrap RichText widget with another widget such as GestureDetector to expose and use tap() for navigation.

Use Case 2:

Just like sign up section as we saw above, there is also a section to display user agreement in various login screens, like Xoom (an online money transfer app) has below UI:

To implement last section, we can divide the text into three parts as below:

  • First part : parent TextSpan with text (By Logging In,) and style (Colors.black)
child: RichText(
text: TextSpan(
text: 'By Logging In,',
style: TextStyle(
color: Colors.black, fontSize: 15),
  • Second part: first of children of TextSpan object with text(you accept the Xoom) and style (Colors.black)
children: <TextSpan>[
TextSpan(text: ' you accept the Xoom',
style: TextStyle(
color: Colors.black, fontSize: 15)
),
  • Third part: second of children of TextSpan object with text(User Agreement) and style (Colors.blue and fontWeight as bold) and recognizer to tap.
TextSpan(
text: ' User Agreement',
style: TextStyle(color: Colors.blueAccent, fontWeight: FontWeight.bold),
recognizer: TapGestureRecognizer()
..onTap = () {
// navigate to desired screen
}
)

Output is:

Use Case 3:

Here, we’ll make use of multiline text/paragraph that will have some of the words underlined with a different color. Consider github login screen which has a text paragraph as shown below:

Approach

Since the text apart from open source and business are straightforward plain text, we’ll focus on implementing only the above words and not regular text.

Inside TextSpan object, we’ll use style property and assign a white color to open source and business terms respectively along with TextDecoration.underline to achieve the expected style, as shown below:

TextSpan(text: 'open source',
style: TextStyle(
color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, decoration: TextDecoration.underline),
recognizer: TapGestureRecognizer()
..onTap = () {
// open desired screen
}
),
TextSpan(
text: 'business,',
style: TextStyle(
color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, decoration: TextDecoration.underline),
recognizer: TapGestureRecognizer()
..onTap = () {
// open desired screen
}
),

The entire code snippet is as below:

Container(
color: Colors.black,
padding: EdgeInsets.all(10),
child: Center(
child: RichText(
text: TextSpan(
text: 'GitHub is a development platform inspired by the way you work. From ',
style: TextStyle(
color: Colors.grey,
fontSize: 20,
fontWeight: FontWeight.bold),
children: <TextSpan>[
TextSpan(text: 'open source',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
decoration: TextDecoration.underline),
recognizer: TapGestureRecognizer()
..onTap = () {
// open desired screen
}
),
TextSpan(
text: ' to ',
style: TextStyle(color: Colors.grey,
fontSize: 20,
fontWeight: FontWeight.bold)
),
TextSpan(
text: 'business,',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
decoration: TextDecoration.underline),
recognizer: TapGestureRecognizer()
..onTap = () {
// open desired screen
}
),
TextSpan(
text: ' you can host and review code, manage projects, and build software alongside 36 million developers.',
style: TextStyle(color: Colors.grey,
fontSize: 20,
fontWeight: FontWeight.bold)
)
]
),
)
)
)

And the output is:

We saw how RichText helps to make the text’s appearance and functionality more effective and gives the developers more options to implement the text in a certain way, whether the text is single line or a paragraph and can achieve number of such use cases in a text not limited to only login screens of various apps but can be useful in other functionalities/screens of the apps as well.

That’s all I have in this article. Thanks for reading and feel free to comment below your thoughts or any suggestions/feedback on this article. I am available on Twitter, LinkedIn, and Github.

My other articles on Flutter are:

--

--

Darshan Kawar
Flutter Community

Open Source Support Engineer For Flutter @nevercodeHQ. Android Nanodegree Certified. Previously, Android Automation Test Engineer.