Flutter富文本样式插件styled_text的使用

发布于 1周前 作者 vueper 来自 Flutter

Flutter富文本样式插件styled_text的使用

styled_text 是一个用于在Flutter中创建带有格式化文本的Text widget的插件。它通过使用XML标签来定义文本中的不同部分,并为这些标签定义样式和其他行为。这使得在多语言应用程序中使用格式化文本变得更容易。你还可以通过标签插入图标和小部件。

目录

开始 {#getting-started}

添加依赖

在你的pubspec.yaml文件中添加styled_text依赖:

dependencies:
  ...
  styled_text: ^[version]

导入包

在Dart文件中导入styled_text包:

import 'package:styled_text/styled_text.dart';

转义 & 特殊字符 {#escaping–special-characters}

标签属性必须用双引号括起来,例如:<link href="https://flutter.dev">

你需要转义文本中的特定XML字符:

原始字符 转义字符
" &quot;
&apos;
& &amp;
< &lt;
> &gt;
空格 &space;

换行符 {#line-breaks}

默认情况下,换行符不被忽略,所有的换行符\n会自动转换成<br/>标签。要禁用此行为,你可以将newLineAsBreaks参数设置为false,并在需要换行的地方插入<br/>标签。

使用示例 {#usage-examples}

使文本的一部分加粗 {#an-example-of-making-parts-of-text-bold}

StyledText(
  text: 'Test: <bold>bold</bold> text.',
  tags: {
    'bold': StyledTextTag(style: TextStyle(fontWeight: FontWeight.bold)),
  },
)

用不同的样式高亮显示文本的一部分 {#example-of-highlighting-a-part-of-the-text-by-different-styles}

StyledText(
  text: 'Test: <bold>bold</bold> and <red>red color</red> text.',
  tags: {
    'bold': StyledTextTag(style: TextStyle(fontWeight: FontWeight.bold)),
    'red': StyledTextTag(style: TextStyle(fontWeight: FontWeight.bold, color: Colors.red)),
  },
)

在文本中插入图标 {#example-of-inserting-icons-into-the-text}

StyledText(
  text: 'Text with alarm <alarm/> icon.',
  tags: {
    'alarm': StyledTextIconTag(Icons.alarm),
  },
)

使用标签处理器 {#example-of-using-a-tag-handler}

StyledText(
  text: 'Text with <link href="https://flutter.dev">link</link> inside.',
  tags: {
    'link': StyledTextActionTag(
      (String? text, Map<String?, String?> attrs) => {
        final String link = attrs['href'];
        print('The "$link" link is tapped.');
      },
      style: TextStyle(decoration: TextDecoration.underline),
    ),
  },
)

自定义标签属性处理器示例 {#example-of-using-a-custom-tag-attributes-handler-highlights-text-with-the-color-specified-in-the-text-attribute-of-the-tag}

StyledText(
  text: 'Text with custom <color text="#ff5500">color</color> text.',
  tags: {
    'color': StyledTextCustomTag(
        baseStyle: TextStyle(fontStyle: FontStyle.italic),
        parse: (baseStyle, attributes) {
          if (attributes.containsKey('text') &&
              (attributes['text'].substring(0, 1) == '#') &&
              attributes['text'].length >= 6) {
            final String hexColor = attributes['text'].substring(1);
            final String alphaChannel = (hexColor.length == 8) ? hexColor.substring(6, 8) : 'FF';
            final Color color = Color(int.parse('0x$alphaChannel' + hexColor.substring(0, 6)));
            return baseStyle.copyWith(color: color);
          } else {
            return baseStyle;
          }
        }),
  },
)

在标签位置插入输入框小部件 {#an-example-of-inserting-an-input-field-widget-in-place-of-a-tag}

StyledText(
  text: 'Text with <input/> inside.',
  tags: {
    'input': StyledTextWidgetTag(
      TextField(
        decoration: InputDecoration(
          hintText: 'Input',
        ),
      ),
      size: Size.fromWidth(200),
      constraints: BoxConstraints.tight(Size(100, 50)),
    ),
  },
)

使用可选择的富文本 {#an-example-of-using-a-widget-with-the-ability-to-select-rich-text}

StyledText.selectable(
  text: 'Test: selectable <bold>bold</bold> text.',
  tags: {
    'bold': StyledTextTag(style: TextStyle(fontWeight: FontWeight.bold)),
  },
)

完整示例Demo

以下是一个完整的示例,展示了如何在Flutter应用中使用styled_text插件:

import 'package:flutter/material.dart';
import 'package:styled_text/styled_text.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'StyledText Demo',
      theme: ThemeData(
        primarySwatch: Colors.teal,
      ),
      home: const DemoPage(),
    );
  }
}

class DemoPage extends StatelessWidget {
  const DemoPage({super.key});

  void _alert(BuildContext context, {String text = 'Tapped'}) {
    showDialog<void>(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          content: Text(text),
          actions: <Widget>[
            TextButton(
              child: const Text('OK'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  void _openLink(BuildContext context, Map<String?, String?> attrs) {
    final String? link = attrs['href'];

    showDialog<void>(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('Open Link'),
          content: Text(link ?? 'Unknown link'),
          actions: <Widget>[
            TextButton(
              child: const Text('Ok'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return SelectionArea(
      child: Scaffold(
        appBar: AppBar(
          title: const Text('StyledText Demo'),
        ),
        body: Center(
          child: SingleChildScrollView(
            padding: const EdgeInsets.symmetric(vertical: 32),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                // Simple formatted text
                StyledText(
                  text: 'Test: <b>bold</b> text.',
                  tags: {
                    'b': StyledTextTag(
                      style: const TextStyle(fontWeight: FontWeight.bold),
                    ),
                  },
                ),

                // Nested multiple styles
                StyledText(
                  text: 'Test: <b>bold <i>italic</i> bold</b> text.',
                  tags: {
                    'b': StyledTextTag(
                      style: const TextStyle(fontWeight: FontWeight.bold),
                    ),
                    'i': StyledTextTag(
                      style: const TextStyle(fontStyle: FontStyle.italic),
                    ),
                  },
                ),

                // Text with quotes
                StyledText(
                  text: 'Quote test: <b>&quot;bold&quot;</b> text.',
                  tags: {
                    'b': StyledTextTag(
                      style: const TextStyle(fontWeight: FontWeight.bold),
                    ),
                  },
                ),

                // Multiline text without breaks
                const SizedBox(height: 20),
                StyledText(
                  newLineAsBreaks: false,
                  text: """Multiline text 
(wo breaks)""",
                  tags: {
                    'b': StyledTextTag(
                      style: const TextStyle(fontWeight: FontWeight.bold),
                    ),
                  },
                ),

                // Multiline text with breaks
                const SizedBox(height: 20),
                StyledText(
                  text: """Multiline text
(with breaks)""",
                  tags: {
                    'b': StyledTextTag(
                      style: const TextStyle(fontWeight: FontWeight.bold),
                    ),
                  },
                ),

                // Text with icon
                const SizedBox(height: 20),
                StyledText(
                  text: 'Text with alarm <alarm/> icon.',
                  tags: {
                    'alarm': StyledTextIconTag(
                      Icons.alarm,
                      color: Colors.teal,
                      size: 18,
                      onTap: (text, attributes) =>
                          _alert(context, text: 'Alarm Tapped'),
                    ),
                  },
                ),

                // Text with icon inside styled text
                const SizedBox(height: 20),
                StyledText(
                  text: 'Text with <red>alarm <alarm/> icon</red>.',
                  tags: {
                    'red': StyledTextTag(
                      style: const TextStyle(color: Colors.red),
                    ),
                    'alarm': StyledTextIconTag(
                      Icons.alarm,
                      color: Colors.teal,
                      size: 18,
                      onTap: (text, attributes) =>
                          _alert(context, text: 'Alarm Tapped'),
                    ),
                  },
                ),

                // Text with link
                const SizedBox(height: 20),
                StyledText(
                  text:
                      'Text with <link href="https://flutter.dev">link</link> inside.',
                  tags: {
                    'link': StyledTextActionTag(
                      (_, attrs) => _openLink(context, attrs),
                      style:
                          const TextStyle(decoration: TextDecoration.underline),
                    ),
                  },
                ),

                // Text with action
                const SizedBox(height: 20),
                StyledText(
                  text:
                      'Text with <action><red>red</red> action</action> inside.',
                  tags: {
                    'red': StyledTextTag(
                      style: const TextStyle(color: Colors.red),
                    ),
                    'action': StyledTextActionTag(
                      (text, attributes) => _alert(context),
                      style:
                          const TextStyle(decoration: TextDecoration.underline),
                    ),
                  },
                ),

                // Text with superscript
                const SizedBox(height: 20),
                StyledText(
                  text: "Famous equation: E=mc<sup>2</sup>",
                  tags: {
                    'sup': StyledTextWidgetBuilderTag(
                      (_, attributes, textContent) {
                        return Transform.translate(
                          offset: const Offset(0.5, -4),
                          child: Text(
                            textContent ?? "",
                            textScaleFactor: 0.85,
                          ),
                        );
                      },
                    ),
                  },
                ),

                // Text with subscript
                const SizedBox(height: 20),
                StyledText(
                  text: "The element of life: H<sub>2</sub>0",
                  tags: {
                    'sub': StyledTextWidgetBuilderTag(
                      (_, attributes, textContent) {
                        return Transform.translate(
                          offset: const Offset(0.5, 4),
                          child: Text(
                            textContent ?? "",
                            textScaleFactor: 0.8,
                          ),
                        );
                      },
                    ),
                  },
                ),

                // Text with widget
                const SizedBox(height: 20),
                StyledText(
                  text: 'Text with <input/> inside.',
                  tags: {
                    'input': StyledTextWidgetTag(
                      const TextField(
                        decoration: InputDecoration(
                          hintText: 'Input',
                        ),
                      ),
                      size: const Size.fromWidth(200),
                      constraints: BoxConstraints.tight(const Size(100, 50)),
                    ),
                  },
                ),

                const Divider(height: 40),

                // Selectable text
                StyledText.selectable(
                  text: 'Test: selectable <b>bold</b> text.',
                  tags: {
                    'b': StyledTextTag(
                      style: const TextStyle(fontWeight: FontWeight.bold),
                    ),
                  },
                ),

                const Divider(height: 40),

                // Text with custom color tag
                StyledText(
                  text:
                      'Text with custom <color text="#ff5500">color</color> text.',
                  tags: {
                    'color': StyledTextCustomTag(
                        baseStyle: const TextStyle(fontStyle: FontStyle.italic),
                        parse: (baseStyle, attributes) {
                          if (attributes.containsKey('text') &&
                              (attributes['text']!.substring(0, 1) == '#') &&
                              attributes['text']!.length >= 6) {
                            final String hexColor =
                                attributes['text']!.substring(1);
                            final String alphaChannel = (hexColor.length == 8)
                                ? hexColor.substring(6, 8)
                                : 'FF';
                            final Color color = Color(int.parse(
                                '0x$alphaChannel${hexColor.substring(0, 6)}'));
                            return baseStyle?.copyWith(color: color);
                          } else {
                            return baseStyle;
                          }
                        }),
                  },
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

这个示例展示了如何使用styled_text插件创建包含不同样式的富文本、图标、链接、动作、上标、下标、以及嵌入式小部件的文本。希望这个示例能帮助你更好地理解和使用styled_text插件。


更多关于Flutter富文本样式插件styled_text的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter富文本样式插件styled_text的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用styled_text插件来创建富文本样式的示例代码。styled_text是一个用于在Flutter中处理富文本的插件,它允许你以灵活的方式定义和渲染带有不同样式的文本。

首先,你需要在你的pubspec.yaml文件中添加styled_text依赖:

dependencies:
  flutter:
    sdk: flutter
  styled_text: ^2.0.0  # 请检查最新版本号

然后,运行flutter pub get来安装依赖。

接下来,在你的Dart文件中,你可以这样使用styled_text插件:

import 'package:flutter/material.dart';
import 'package:styled_text/styled_text.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Styled Text Example'),
        ),
        body: Center(
          child: StyledText.builder()
            ..pushStyle(color: Colors.red, fontSize: 20, fontWeight: FontWeight.bold)
            ..addText('Hello, ')
            ..popStyle()
            ..pushStyle(color: Colors.blue, decoration: TextDecoration.underline)
            ..addText('Styled Text!')
            ..popStyle()
            ..build(),
        ),
      ),
    );
  }
}

在这个示例中,我们使用了StyledText.builder()方法来构建一个StyledTextBuilder对象,这个对象允许我们通过链式调用的方式来设置文本的样式和添加文本内容。

  • pushStyle(...)方法用于将一个新的样式推入样式栈中,所有后续添加的文本都会应用这个新样式,直到我们调用popStyle()方法将样式从栈中弹出。
  • addText(...)方法用于添加实际的文本内容。
  • build()方法用于构建最终的StyledText小部件。

你可以根据需要添加更多的样式和文本内容,比如改变文本的对齐方式、添加背景颜色、设置不同的字体样式等等。styled_text插件提供了丰富的API来满足这些需求。

希望这个示例能帮助你理解如何在Flutter中使用styled_text插件来创建富文本样式。如果你有任何其他问题,欢迎继续提问!

回到顶部