More GestureRecognisers For The TextSpan In Flutter - flutter

I building an application in Flutter and I am in a situation where I got RichText widget with many TextSpan widgets and I need to have two gesture recognizers, one is on double tap and the other is on long press, so how do I do this if it is possible?

Can't you just wrap the entire Text Span in the gesture detector widget? https://api.flutter.dev/flutter/widgets/GestureDetector-class.html

Each textSpan comes with its own text and children property for which you can use the recognizer property and implement different taps as needed.
Consider below example:
Container(
color: Colors.black,
padding: EdgeInsets.all(10),
child: Center(
child: RichText(
text: TextSpan( // <-- 1
text: 'This is a text from first textspan. ',
style: TextStyle(
color: Colors.grey,
fontSize: 20,
fontWeight: FontWeight.bold),
children: <TextSpan>[ // <-- 2
TextSpan(
text: ' This is a text from second textspan ',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold),
recognizer: LongPressGestureRecognizer()
..onLongPress = () {
print('Long pressed');
},
children: <
TextSpan>[ // <-- 3 (children of 2 textspan
TextSpan(
text: ' This is a another text from second textspan',
recognizer: DoubleTapGestureRecognizer()
..onDoubleTap = () {
print('double tapped');
}
)
]
),
]
),
)
)
)
The children: <TextSpan>[] commented as 2 has a text property and corresponding recognizer in which I used LongPressGestureRecognizer(). The same textSpan (2), has children property which again can have a sub text span with a text and corresponding recognizer in which I used DoubleTapGestureRecognizer().
So the output will be : You can long press on This is a text from second textspan and you can double tap on This is another text from second textspan.
Hope this answers your question.

Related

Flutter dynamic clickable part of text

I read different posts on how to make parts of a text clickable. What I did not found and that I need in my case, is that the clickable part of text is set dinamically because I have different translations for each language, so the clickable word can be in different parts of the sentence. I have some files with all the texts that my application uses and those texts contains placeholders, So I want something more or less like this:
title: RichText(
text: TextSpan(
style: Theme.of(context)
.textTheme
.bodyText1
?.copyWith(fontSize: 14.0),
children: <TextSpan>[
TextSpan(
text: labels.label1(new TextSpan(
text: labels.placeholder_value,
style: new TextStyle(color: Colors.blue),
recognizer: new TapGestureRecognizer()
..onTap = () async {
func(context);
},
)
]
),
)
This piece of code of course doesn't work, it is only to show better what I need...I want the TextSpan with blue color and TapGestureRecognizer to be passed as a parameter to label1

How to make words inside a paragraph clickable in flutter?

I have a line that has three buttons inside it. I know that I can use RichText with Gesture Recogniser to make them clickable like HTML <a href=""> tag. But I am new to flutter and don't know how can I achieve that behaviour.
Also is there any better option to do similar thing?
Also I don't want to open an External Link. Just navigate to another page.
I have attached a picture containing what I want to do. Picture of what I want to do
import 'package:flutter/gestures.dart';
and the widget
RichText(
text: TextSpan(
children: [
TextSpan(
text: "By Clicking Sign up you are agree to the ",
),
TextSpan(
text: "Privacy Policy ",
style: TextStyle(
color: Colors.lightGreen,
),
recognizer: new TapGestureRecognizer()
..onTap = () => print("Privacy Policy"),
),
TextSpan(text: "and our "),
TextSpan(
text: "Terms and Conditions ",
style: TextStyle(
color: Colors.lightGreen,
),
recognizer: new TapGestureRecognizer()
..onTap = () => print("Terms and Conditions"),
),
TextSpan(text: "and "),
TextSpan(
text: "Cookie Statement",
style: TextStyle(
color: Colors.lightGreen,
),
recognizer: new TapGestureRecognizer()
..onTap = () => print("Cookie Statement"),
),
TextSpan(text: "."),
],
),
),
does it help?
you can wrap the Text widget with GestureDetector()
GestureDetector(
child: Text(
'Clickable text'
),
onTap: () {
//go to destination page
},
)
In case if you're opening to an external link you can check URL launcher to open websites

Pass params to stateless widget in Flutter

I am trying to do a stateless widget for inline text links.
I am using this answer here https://stackoverflow.com/a/55607224/3808307 to create the links
RichText(
text: TextSpan(
children: [
TextSpan(text: 'This is a going to be a Text which has '),
TextSpan(
text: 'single tap',
style: style,
recognizer: TapGestureRecognizer()
..onTap = () {
// single tapped
},
),
TextSpan(text: ' along with '),
TextSpan(
text: 'double tap',
style: style,
recognizer: DoubleTapGestureRecognizer()
..onDoubleTap = () {
// double tapped
},
),
TextSpan(text: ' and '),
TextSpan(
text: 'long press',
style: style,
recognizer: LongPressGestureRecognizer()
..onLongPress = () {
// long pressed
},
),
],
),
)
, but I would like to have a TextSpan that I can import, and already has the styling applied, passing it a text that would act as label and a function.
Do I need a stateful widget for this, or can I just use a stateless widget?
You can use a stateless widget without a problem.
In the case that you need to change the style of the text when you press the links you will need to use a stateful widget.

How to put mouse cursor on hyper text in TextSpan in Flutter web

I am using something like this to have links in text inside a paragraph
RichText(
text: TextSpan(
children: [
TextSpan(text: 'This is a going to be a Text which has '),
TextSpan(
text: 'single tap',
style: style,
recognizer: TapGestureRecognizer()
..onTap = () {
// single tapped
},
),
],
),
)
Now, it works fine, but I cannot have a hand cursor when rolling over the text?
I was looking on how to do it and found this
MouseRegion(
cursor: SystemMouseCursors.click,
child: Container(
height: 30,
width: 30,
color: Colors.red,
),
),
but is not possible to wrap one of the TextSpans in a Container and MouseRegion.
You can create a custom WidgetSpan like this:
class MouseRegionSpan extends WidgetSpan {
MouseRegionSpan({
#required MouseCursor mouseCursor,
#required InlineSpan inlineSpan,
}) : super(
child: MouseRegion(
cursor: mouseCursor,
child: Text.rich(
inlineSpan,
),
),
);
}
and wrap your TextSpan with it:
MouseRegionSpan(
mouseCursor: SystemMouseCursors.click,
inlineSpan: TextSpan(
text: 'single tap',
style: style,
recognizer: TapGestureRecognizer()
..onTap = () {
// single tapped
},
),
),
Recently, this feature has been added to TextSpans.
As of Flutter 5647407 on master (probably going to be in the 2.1.0 release), the mouse cursor is clickable (hand cursor) by default. So you do not need to take any action other than upgrading Flutter.
Manually specifying
You can manually specify the mouseCursor property:
TextSpan(
text: 'single tap',
style: style,
mouseCursor: MaterialStateMouseCursor.clickable,
recognizer: TapGestureRecognizer()
..onTap = () {
// single tapped
},
),
Furthermore, there are now onEnter and onExit callbacks for responding to the mouse entering and leaving the text span.
Default SystemMouseCursors.click
If you take a look at the commit, you will notice that the default is now SystemMouseCursors.click when you specify a recognizer.

How can I change the color of several words in the TextField Widget?

Im trying to do chat mentions and I need to some how change the color of full name that mentioned in the TextField before send the message.
How can I do that?
Hope i'm not too late :)
I had the same issue and couldn't find any implementation in the main flutter package or any third party packages, so i hacked a little packaage and uploaded it.
it's an extension of the text editing controller that you can supply with a map of Regex patterns and corresponding Text style.
https://pub.dev/packages/rich_text_controller
https://github.com/micwaziz/rich_text_controller
In case someone stumbles across this question (like I did) but requires the textfield to render tap-able links, then here's one way to do it (simplified from our final implementation for better clarity). It's inspired by the RichTextController, but with the definitive focus to allow for taps on the links.
Regarding the regular expression: We tried using linkify, but despite trying all options, it tended to modify the links - which messed up the user input.
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:url_launcher/url_launcher.dart';
class LinkedTextEditingController extends TextEditingController {
final RegExp linkRegexp;
final TextStyle linkStyle;
final Function(String match) onTap;
static RegExp _defaultRegExp =
RegExp(r'((?:(https?:\/\/)?)(www\.)?[-a-zA-Z0-9#:%._\+~#=]{2,256}\.[a-z]{2,5}\b([-a-zA-Z0-9#:%_\+.~#?&//=]*))', caseSensitive: false, dotAll: true);
static void _defaultOnLaunch(String url) async {
final re = RegExp('^https?://');
final fullUrl = re.hasMatch(url) ? url : 'http://$url';
if (await canLaunch(fullUrl)) {
await launch(fullUrl);
}
}
LinkedTextEditingController({
String text,
RegExp regexp,
this.linkStyle,
this.onTap = _defaultOnLaunch,
}) : linkRegexp = regexp ?? _defaultRegExp,
super(text: text);
LinkedTextEditingController.fromValue(
TextEditingValue value, {
RegExp regexp,
this.linkStyle,
this.onTap = _defaultOnLaunch,
}) : linkRegexp = regexp ?? _defaultRegExp,
assert(
value == null || !value.composing.isValid || value.isComposingRangeValid,
'New TextEditingValue $value has an invalid non-empty composing range '
'${value.composing}. It is recommended to use a valid composing range, '
'even for readonly text fields',
),
super.fromValue(value ?? TextEditingValue.empty);
#override
TextSpan buildTextSpan({TextStyle style, bool withComposing}) {
List<TextSpan> children = [];
text.splitMapJoin(
linkRegexp,
onMatch: (Match match) {
children.add(
TextSpan(
text: match[0],
style: linkStyle,
recognizer: onTap == null ? null : TapGestureRecognizer()
..onTap = () => onTap(match[0]),
),
);
return null;
},
onNonMatch: (String span) {
children.add(TextSpan(text: span, style: style));
return span;
},
);
return TextSpan(style: style, children: children);
}
}
as Durdu suggested, you can use RichText to achieve different color text. Just need to put multiple TextSpan with different color using TextStyle. Sample as below
Container(
margin: const EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0),
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
children: [
TextSpan(
text: 'By clicking sign up, you have read and agreed to our ',
style: TextStyle(color: Colors.black54),
),
TextSpan(
text: 'Terms & Conditions',
style: TextStyle(color: Colors.blue),
recognizer: TapGestureRecognizer()
..onTap = () {
print('Tapped on hyperlink');
},
),
TextSpan(
text: '.',
style: TextStyle(color: Colors.black54),
),
],
),
),
),
Hope this clears and solve your problem.
If you just want to change the color or font for the text in the textfield:
Text("Hello",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w900))
If you want to use multiple styles you should check, you should check RichText.
The RichText widget displays text that uses multiple different styles.
RichText(
text: TextSpan(
text: 'Hello ',
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w900)),
children: <TextSpan>[
TextSpan(text: 'bold', style: TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: ' world!'),
],
),
)