
Discover more from Jeffrey’s Newsletter
I'm a software developer and entrepreneur sharing insights on app development, entrepreneurship, and business lessons learned building my second B2C mobile app business.
Continue reading
How to add hyperlinks to Flutter's RichText widget
Before building out the above terms of service and privacy policy widget, I hadn't delved much into Flutter's RichText class. Figuring out how to add the hyperlinks was a bit more involved than expected, but thanks to this StackOverflow thread, the widget was built quickly and worked well.
Note that opening the URLs requires using the url_launcher package and, in my case, a service class that wraps its functionality (not shown below).
Here's my implementation:
class TermsAndPrivacy extends StatefulWidget {
@override
_TermsAndPrivacyState createState() => _TermsAndPrivacyState();
}
class _TermsAndPrivacyState extends State<TermsAndPrivacy> {
TapGestureRecognizer _termsOfServiceLink;
TapGestureRecognizer _privacyPolicyLink;
@override
void initState() {
super.initState();
_termsOfServiceLink = TapGestureRecognizer()..onTap = _termsOfServiceOnTap;
_privacyPolicyLink = TapGestureRecognizer()..onTap = _privacyPolicyOnTap;
}
@override
void dispose() {
_termsOfServiceLink.dispose();
_privacyPolicyLink.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(left: 20, right: 20),
child: Center(
child: Column(
children: [
Text(
'By using Clearful, you agree to our ',
style: Theme.of(context).textTheme.overline,
),
RichText(
textAlign: TextAlign.center,
text: TextSpan(
children: [
TextSpan(
text: 'Terms of Service',
style: Theme.of(context)
.textTheme
.overline
.copyWith(fontWeight: FontWeight.w800),
recognizer: _termsOfServiceLink
..onTap = _termsOfServiceOnTap,
),
TextSpan(
text: ' and ',
style: Theme.of(context).textTheme.overline,
),
TextSpan(
text: 'Privacy Policy',
style: Theme.of(context)
.textTheme
.overline
.copyWith(fontWeight: FontWeight.w800),
recognizer: _privacyPolicyLink..onTap = _privacyPolicyOnTap,
),
TextSpan(
text: '.',
style: Theme.of(context).textTheme.overline,
),
],
),
),
],
),
),
);
}
Future<void> _termsOfServiceOnTap() async {
await locator<UrlLauncher>().launchUrl(url: termsOfServiceUrl);
}
Future<void> _privacyPolicyOnTap() async {
await locator<UrlLauncher>().launchUrl(url: privacyPolicyUrl);
}
}