You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何获取用户自定义多样式文本并在应用内展示?

Flutter 文本样式输入与展示实现方案

一、实现带样式选择的文本输入功能

通过TextField搭配底部样式选择栏,结合状态管理就能实现自选样式的文本输入,以下是基础落地方案:

1. 定义样式状态与输入控制器

先声明需要控制的样式参数和文本控制器:

bool isBold = false;
bool isItalic = false;
Color textColor = Colors.black;
double fontSize = 16.0;
final TextEditingController _inputController = TextEditingController();

2. 底部样式选择栏

在页面底部添加样式操作组件,用Row包裹功能按钮即可:

Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  padding: const EdgeInsets.symmetric(vertical: 8),
  children: [
    // 粗体切换
    IconButton(
      icon: Icon(Icons.format_bold, color: isBold ? Colors.blue : Colors.grey),
      onPressed: () => setState(() => isBold = !isBold),
    ),
    // 斜体切换
    IconButton(
      icon: Icon(Icons.format_italic, color: isItalic ? Colors.blue : Colors.grey),
      onPressed: () => setState(() => isItalic = !isItalic),
    ),
    // 颜色选择
    IconButton(
      icon: const Icon(Icons.color_lens),
      onPressed: () async {
        final Color? pickedColor = await showDialog(
          context: context,
          builder: (ctx) => AlertDialog(
            title: const Text('选文本颜色'),
            content: SingleChildScrollView(
              // 这里可以用flutter_colorpicker第三方包,或者自定义颜色选择组件
              child: Container(
                height: 300,
                child: GridView.builder(
                  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5),
                  itemCount: Colors.primaries.length,
                  itemBuilder: (_, index) {
                    final color = Colors.primaries[index];
                    return GestureDetector(
                      onTap: () => Navigator.pop(ctx, color),
                      child: Container(color: color, margin: const EdgeInsets.all(2)),
                    );
                  },
                ),
              ),
            ),
            actions: [
              TextButton(
                onPressed: () => Navigator.pop(ctx),
                child: const Text('确定'),
              ),
            ],
          ),
        );
        if (pickedColor != null) setState(() => textColor = pickedColor);
      },
    ),
    // 字号选择
    DropdownButton<double>(
      value: fontSize,
      items: const [
        DropdownMenuItem(value: 14.0, child: Text('14')),
        DropdownMenuItem(value: 16.0, child: Text('16')),
        DropdownMenuItem(value: 18.0, child: Text('18')),
        DropdownMenuItem(value: 20.0, child: Text('20')),
      ],
      onChanged: (value) => setState(() => fontSize = value!),
    ),
  ],
)

3. 关联样式与输入框

让输入框实时应用选中的样式,实现预览效果:

TextField(
  controller: _inputController,
  style: TextStyle(
    fontWeight: isBold ? FontWeight.bold : FontWeight.normal,
    fontStyle: isItalic ? FontStyle.italic : FontStyle.normal,
    color: textColor,
    fontSize: fontSize,
  ),
  decoration: const InputDecoration(
    hintText: '输入文本...',
    border: OutlineInputBorder(),
    contentPadding: EdgeInsets.all(12),
  ),
  maxLines: null,
)

如果需要支持分段不同样式(比如部分文字加粗、部分变颜色),可以基于TextEditingController监听光标选区,记录每个片段的样式信息,实现逻辑相对复杂,基础场景用整段样式即可覆盖需求。

二、展示带样式的文本

根据保存的文本内容和样式参数,用RichText组件就能实现带样式的文本展示:

1. 保存样式与文本

可以把文本和样式封装成一个模型类,方便存储和传递:

class StyledTextModel {
  final String content;
  final bool isBold;
  final bool isItalic;
  final Color textColor;
  final double fontSize;

  StyledTextModel({
    required this.content,
    required this.isBold,
    required this.isItalic,
    required this.textColor,
    required this.fontSize,
  });
}

// 保存示例
final savedStyledText = StyledTextModel(
  content: _inputController.text,
  isBold: isBold,
  isItalic: isItalic,
  textColor: textColor,
  fontSize: fontSize,
);

2. 渲染带样式的文本

用RichText构建对应的富文本:

RichText(
  text: TextSpan(
    text: savedStyledText.content,
    style: TextStyle(
      fontWeight: savedStyledText.isBold ? FontWeight.bold : FontWeight.normal,
      fontStyle: savedStyledText.isItalic ? FontStyle.italic : FontStyle.normal,
      color: savedStyledText.textColor,
      fontSize: savedStyledText.fontSize,
    ),
  ),
  padding: const EdgeInsets.all(16),
)

如果是分段多样式的文本,只需要把每个带样式的片段拆成独立的TextSpan,组合后传入RichText的text参数即可。

内容的提问来源于stack exchange,提问作者srckto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:21:25