सार्वजनिक जानकारी से बना चयन मार्गदर्शन। केवल संदर्भ हेतु।
फ्लटर में उन्नत शैली, गतिशील टेक्स्ट संपादन और गतिशील इंटरैक्शन के लिए एक अत्यधिक कस्टमाइज़ेबल टेक्स्ट विजेट। एनिमेशन, प्रभाव और इंटरैक्टिव तत्वों के साथ रिच टेक्स्ट प्रदर्शन के लिए आदर्श। पैकेज डेवलपर्स को सभी प्रमुख प्लेटफॉर्मों पर दिखावट और व्यवहार के बारे में बहुत नियंत्रण के साथ दृश्य रूप से आकर्षक टेक्स्ट घटक बनाने की अनुमति देता है।
उपयोग
कस्टम स्टाइल के साथ रिच टेक्स्ट रेंडरिंग
गतिशील गतियों के साथ इंटरैक्टिव पाठ तत्व
वास्तविक समय में अपडेट के साथ डायनामिक टेक्स्ट संपादन
टेक्स्ट एनिमेशन और विजुअल प्रभाव
मार्कडाउन या एचटीएमएल सामग्री प्रदर्शन
UI में कस्टम पाठ लेआउट
मुख्य विशेषताएँ
उन्नत टेक्स्ट स्टाइलिंग विकल्प
निर्मित गतिशील स्वीकृति
संपाद्य टेक्स्ट नियंत्रक
क्रॉस-प्लेटफॉर्म संगतता
एनीमेशन और प्रभावों का समर्थन
कस्टम कंपोनेंट्स के लिए विस्तारशील डिज़ाइन
इनके लिए उपयुक्त
समृद्ध पाठ इंटरफ़ेस बनाने वाले विकासकर्ता
पार्टिकल टेक्स्ट तत्वों की आवश्यकता वाले ऐप
जटिल पाठ स्वरूपण की आवश्यकता वाले प्रोजेक्ट्स
गतिशील सामग्री वाले UI-भारी अनुप्रयोग
टेम्स जो टेक्स्ट डिस्प्ले में मार्कडाउन या एचटीएमएल का उपयोग करते हैं
विचार योग्य बातें
जटिल एनीमेशन के लिए अतिरिक्त सेटअप की आवश्यकता हो सकती है
बड़े टेक्स्ट ब्लॉक के साथ प्रदर्शन प्रभाव
मूल उपयोग के अतिरिक्त सीमित दस्तावेज़न
टेक्स्ट कंट्रोलर राज्य के सावधानीपूर्वक निर्देशन की आवश्यकता होती है
अत्यधिक उच्च आवृत्ति के पाठ अद्यतन के लिए अनुकूलित नहीं है
मूल README
संबंधित सोर्स रिपॉज़िटरी के मूल README का स्नैपशॉट। नवीनतम सामग्री के लिए रिपॉज़िटरी देखें।
A highly customisable text widget that enables decorations and gesture actions, and
a special TextEditingController that makes some of the features available also
in a text field.
This package is useful for making partial strings in text (e.g. URLs, email addresses
or phone numbers) react to tap, long-press and hover gestures, or for only highlighting
particular strings with colors and different font settings. You can configure the appearance
and the behaviour using multiple definitions consisting of regular expressions, text styles,
gesture handlers, etc.
Usage by example
Most of the examples here are included in the sample app in the example folder.
Just click on the link below to see it in action on the web.
The app shows the source code with keywords highlighted, which itself is made possible
by this package (plus the highlight package used as an external parser).
⭐ Simplest example
A very basic example of how to apply a colour to URLs and email addresses using preset
matchers.
[!TIP]
To open a browser or another app when a string is tapped or long-pressed, use the
url_launcher package or equivalent in the onTap and/or onLongPress handlers.
⭐ Overwriting a match pattern
An example to replace the default pattern of TelMatcher.
A hashtag has a wide variety of definitions, but here as an example, it is defined
as a string that starts with "#" followed by an alphabet and then alphanumerics,
and is enclosed with white spaces.
SelectiveDefinition allows to select the string to display and the string to
be passed to gesture callbacks individually.
The shownText and actionText functions receive a TextElement object
containing various pieces of information provided by the parser. For its
details, see the document of the text_parser package used internally in
this package.
CustomText(
'Tap [here](Tapped!)',
definitions: [
SelectiveDefinition(
matcher: constLinkMatcher(),
// `shownText` is used to choose the string to display.
shownText: (element) => element.groups[0]!,
// `actionText` is used to choose the string to be passed// to the `onTap`, `onLongPress` and `onGesture` handlers.
actionText: (element) => element.groups[1]!,
),
],
matchStyle: TextStyle(color: Colors.blue),
hoverStyle: TextStyle(color: Colors.blue, decoration: TextDecoration.underline),
onTap: (details) => print(details.actionText),
)
LinkMatcher is handy if used together with SelectiveDefinition, not only for
making a text link but also for just decorating the bracketed strings (without
showing the bracket symbols), in which case [strings]() is used as a marker to
indicate which strings to be decorated.
// "def" and "jkl" are displayed in red.CustomText(
'abc[def]()ghi[jkl]()',
definitions: [
SelectiveDefinition(
matcher: constLinkMatcher(),
shownText: (element) => element.groups[0]!,
),
],
matchStyle: constTextStyle(color: Colors.red),
)
SpanDefinition enables a certain portion of text to be replaced with an arbitrary
InlineSpan. The builder function receives a TextElement object containing
various pieces of information provided by the parser so that you can use it
to flexibly build an InlineSpan.
Text styles, gesture handlers and the mouse cursor type are applied to the entire
InlineSpan returned by the builder function. In this example, hovering is detected
on all the children specified in the second SpanDefinition, i.e. the text in a TextSpan
is decorated based on hoverStyle while the mouse pointer is hovering over the logo
as well as over the text.
This is easily possible by just passing your desired type to mouseCursor.
If a tap handler (onTap or onLongPress) is specified and mouseCursor is not,
SystemMouseCursors.click is automatically used for the tappable region.
A different text style can also be applied on hover using hoverStyle either in CustomText
or in a definition.
CustomText(
'URL: https://example.com/\n''Email: foo@example.com',
definitions: [
constTextDefinition(
matcher: UrlMatcher(),
matchStyle: TextStyle(
color: Colors.grey,
decoration: TextDecoration.lineThrough,
),
// `SystemMouseCursors.forbidden` is used for URLs.
mouseCursor: SystemMouseCursors.forbidden,
),
TextDefinition(
matcher: constEmailMatcher(),
matchStyle: constTextStyle(
color: Colors.lightBlue,
decoration: TextDecoration.underline,
),
tapStyle: constTextStyle(color: Colors.green),
// Text is shadowed while the mouse pointer hovers over it.
hoverStyle: TextStyle(
color: Colors.lightBlue,
shadows: ...,
),
// `SystemMouseCursors.click` is automatically used for// tappable elements even if `mouseCursor` is not specified.
onTap: (details) => print(details.actionText),
),
],
)
[!TIP]
Use hoverStyle and omit tapStyle if you want the same style for tap and hover.
⭐ Event positions and onGesture
An example to trigger an action by a secondary or tertiary button press or a
mouse enter or exit gesture.
The onGesture handler is called on an event of a non-primary button or mouse
gesture.
You can check the event type with gestureKind contained in the GestureDetails
object which is passed to the handler function. The object also has the global
and local positions where an event happened.
[!NOTE]
onGesture does not handle events of the primary button. Use onTap and/or
onLongPress instead.
Unlike onTap and onLongPress, whether onGesture is specified does not
affect text styling.
The handler function is called one microsecond or more after the actual
occurrence of an event.
This is due to a workaround for preventing the function from being called
more times than expected by updates of the text span.
⭐ CustomText.spans
An example of the CustomText.spans constructor that allows to use a list of InlineSpans
instead of plain text.
This constructor is useful if you already have styled spans and want to decorate them
additionally.
In this example, the match pattern matches the range containing multiple InlineSpans
including a WidgetSpan, and the specified styles and gestures are applied to that range.
CustomText.spans(
style: constTextStyle(fontSize: 40.0),
definitions: [
TextDefinition(
// WidgetSpan is matched by `\uFFFC` or `.` in a match pattern.
matcher: constPatternMatcher('Flutter devs\uFFFC'),
matchStyle: constTextStyle(color: Colors.blue),
hoverStyle: TextStyle(color: Colors.blue.shade300),
mouseCursor: SystemMouseCursors.forbidden,
onGesture: (details) => output(details.gestureKind.name),
),
],
spans: [
constTextSpan(text: 'Hi, '),
constTextSpan(
text: 'Flutter',
style: TextStyle(
fontWeight: FontWeight.bold,
shadows: [Shadow(blurRadius: 4.0, color: Colors.cyan)],
),
),
constTextSpan(text: ' devs'),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Builder(
builder: (context) {
// Text style is available also in WidgetSpan via DefaultTextStyle.final style = DefaultTextStyle.of(context).style;
returnIcon(
Icons.flutter_dash,
size: style.fontSize,
color: style.color,
);
},
),
),
],
)
[!NOTE]
Arguments other than text and style in the spans passed to spans are
not used even if specified.
⭐ CustomText with preBuilder
An example of preBuilder that allows to apply decorations and then additionally
apply more decorations and enable gestures.
It has similar use cases to CustomText.spans, but is more helpful when it is
not easy to compose complex spans manually.
The example below makes "KISS" and "Keep It Simple, Stupid!" bold, and then
applies a colour to capital letters contained in them.
CustomText(
'KISS is an acronym for "Keep It Simple, Stupid!".',
definitions: const [
TextDefinition(
// This pattern is used for parsing the TextSpan built// by preBuilder, not for the original text.
matcher: PatternMatcher('[A-Z]'),
matchStyle: TextStyle(color: Colors.red),
),
],
preBuilder: CustomSpanBuilder(
definitions: [
constTextDefinition(
// This pattern is used for parsing the original text.
matcher: PatternMatcher('KISS|Keep.+Stupid!'),
matchStyle: TextStyle(fontWeight: FontWeight.bold),
),
],
),
)
[!NOTE]
Parsing is performed first in the builder and then in CustomText itself.
It is important to understand that the match patterns in the builder are used
for the original text and the patterns in CustomText are used for the TextSpan
built by the builder.
Parsing and building of spans are avoided if not necessary, but still happen
in two steps as written above when unavoidable. Be careful how much it affects
the performance of your app.
Gesture callbacks and mouseCursor in the builder are not used even if specified.
⭐ CustomTextEditingController
An example of CustomTextEditingController that makes some of the CustomText
functionality available in an editable text.
ParserOptions.external helps you when a different parser you already have does
a better job or can do what is difficult with the default parser.
// These empty matchers are used to distinguish the matcher types of// text elements parsed by an external parser.// Each of the elements created by the parser needs to have the type// of one of these matchers or `TextMatcher`. classKeywordMatcherextendsTextMatcher{
constKeywordMatcher() : super('');
}
classStringMatcherextendsTextMatcher{
constStringMatcher() : super('');
}
The external parser must generate a list of TextElements.
If an existing external parser creates hierarchical nodes, they need to be
flattened as this package only supports a flat list.
If a custom parser is used with CustomTextEditingController, the TextElements
generated by the parser must all together constitute the original text.
Otherwise, it will cause unexpected behaviours.
This does not apply to CustomText.
Limitations
decorationColor does not automatically inherit the text colour in Material 3.
See https://github.com/flutter/flutter/issues/129553.
CustomTextEditingController raises an error on iOS simulators (not on real devices)
if the initial text and onTap, onLongPress or onGesture are specified.
See https://github.com/flutter/flutter/issues/97433.
CustomText is dependent on the text_parser package made by the same author.
See its documents for details if you're interested or seek troubleshooting on parsing.