🚀 Flutter 富文本与按钮点击事件实践教程

在日常的 Flutter UI 开发中,我们经常会遇到需要展示多样式文本的场景,比如"部分文字高亮"、"点击某段文字触发操作"等。这篇文章将通过一个完整的示例,带你一步步了解如何在 Flutter 中使用 RichText 展示富文本,并结合各种按钮组件实现交互功能。demo地址


一、富文本 RichText 基础用法

Flutter 提供了 RichText 和 TextSpan 来支持多样式文本渲染。与普通 Text 不同,RichText 可以让你为一段文字中的不同部分设置不同的样式,甚至加入点击事件。

dart 复制代码
RichText(
  text: TextSpan(
    text: 'Hello ',
    style: TextStyle(color: Colors.black, fontSize: 20),
    children: <TextSpan>[
      TextSpan(
        text: 'Flutter ',
        style: TextStyle(
            color: Colors.blue,
            fontWeight: FontWeight.bold,
            fontSize: 22),
        recognizer: _tapRecognizer, // 添加点击事件
      ),
      TextSpan(
        text: 'World!',
        style: TextStyle(
            color: Colors.red, fontStyle: FontStyle.italic),
      ),
    ],
  ),
),

二、为富文本添加点击事件

我们可以使用 TapGestureRecognizer 来为 TextSpan 添加点击事件:

dart 复制代码
late TapGestureRecognizer _tapRecognizer;

@override
void initState() {
  super.initState();
  _tapRecognizer = TapGestureRecognizer()
    ..onTap = () {
      showDialog(
        context: context,
        builder: (context) => AlertDialog(
          title: Text("提示"),
          content: Text("你点击了 Flutter"),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(context),
              child: Text("确定"),
            ),
          ],
        ),
      );
    };
}

@override
void dispose() {
  _tapRecognizer.dispose(); // 释放资源,防止内存泄漏
  super.dispose();
}

三、按钮组件演示

Flutter 提供了多种按钮控件,这里我们展示了常见的四种,并实现了点击后更新文字:

  • ElevatedButton
  • TextButton
  • OutlinedButton
  • IconButton
dart 复制代码
ElevatedButton(
  onPressed: () => _handleButtonClick("ElevatedButton"),
  child: Text("ElevatedButton"),
),

TextButton(
  onPressed: () => _handleButtonClick("TextButton"),
  child: Text("TextButton"),
),

OutlinedButton(
  onPressed: () => _handleButtonClick("OutlinedButton"),
  child: Text("OutlinedButton"),
),

IconButton(
  onPressed: () => _handleButtonClick("IconButton"),
  icon: Icon(Icons.favorite, color: Colors.pink),
)

四、完整示例代码(可直接运行)

dart 复制代码
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';

class ComponentDemoPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _ComponentDemoPageState();
}

class _ComponentDemoPageState extends State<ComponentDemoPage> {
  String _message = "你还没有点击按钮";
  late TapGestureRecognizer _tapRecognizer;

  TextStyle blackStyle = TextStyle(fontWeight: FontWeight.normal, fontSize: 20, color: Colors.black);
  TextStyle redStyle = TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: Colors.red);

  @override
  void initState() {
    super.initState();
    _tapRecognizer = TapGestureRecognizer()
      ..onTap = () {
        showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: Text("提示"),
            content: Text("你点击了 Flutter"),
            actions: [
              TextButton(
                onPressed: () => Navigator.pop(context),
                child: Text("确定"),
              ),
            ],
          ),
        );
      };
  }

  @override
  void dispose() {
    _tapRecognizer.dispose();
    super.dispose();
  }

  void _handleButtonClick(String label) {
    setState(() {
      _message = "你点击了:$label";
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("富文本 & 按钮示例")),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            RichText(
              text: TextSpan(
                text: 'Hello ',
                style: TextStyle(color: Colors.black, fontSize: 20),
                children: <TextSpan>[
                  TextSpan(
                    text: 'Flutter ',
                    style: TextStyle(
                        color: Colors.blue,
                        fontWeight: FontWeight.bold,
                        fontSize: 22),
                    recognizer: _tapRecognizer,
                  ),
                  TextSpan(
                    text: 'World!',
                    style: TextStyle(
                        color: Colors.red, fontStyle: FontStyle.italic),
                  ),
                ],
              ),
            ),
            SizedBox(height: 20),

            Text.rich(
              TextSpan(
                children: [
                  TextSpan(text:'文本是视图系统中常见的控件,它用来显示一段特定样式的字符串,类似', style: redStyle),
                  TextSpan(text:'iOS', style: blackStyle),
                  TextSpan(text:'中的', style: redStyle),
                  TextSpan(text:'UILabel', style: blackStyle),
                ],
              ),
              textAlign: TextAlign.center,
            ),

            SizedBox(height: 30),

            ElevatedButton(
              onPressed: () => _handleButtonClick("ElevatedButton"),
              child: Text("ElevatedButton"),
            ),
            TextButton(
              onPressed: () => _handleButtonClick("TextButton"),
              child: Text("TextButton"),
            ),
            OutlinedButton(
              onPressed: () => _handleButtonClick("OutlinedButton"),
              child: Text("OutlinedButton"),
            ),
            IconButton(
              onPressed: () => _handleButtonClick("IconButton"),
              icon: Icon(Icons.favorite, color: Colors.pink),
            ),
            SizedBox(height: 20),

            Text(
              _message,
              style: TextStyle(fontSize: 16, color: Colors.green),
            ),
          ],
        ),
      ),
    );
  }
}

五、总结

这篇教程向您展示了:

  • 如何在 Flutter 中使用 RichText 和 TextSpan 渲染富文本;
  • 如何使用 TapGestureRecognizer 给文字添加点击事件;
  • 常见按钮组件的使用方法;
  • 如何通过 setState 更新状态和 UI。
相关推荐
前端加油站14 分钟前
在 cursor 成为流行的开发方式后,作为普通开发我们能做什么
前端
Cache技术分享22 分钟前
163. Java Lambda 表达式 - Function 的链式组合
前端·后端
Zestia39 分钟前
页面点击跳转源代码?——element-jumper插件实现
前端·javascript
前端小白199539 分钟前
面试取经:工程化篇-webpack性能优化之优化loader性能
前端·面试·前端工程化
PineappleCoder39 分钟前
大小写 + 标点全搞定!JS 如何精准统计单词频率?
前端·javascript·算法
zhangbao90s40 分钟前
Web组件:使用Shadow DOM
前端
hhy前端之旅41 分钟前
语义版本控制:掌握版本管理的艺术
前端
coding随想41 分钟前
深入浅出DOM操作的隐藏利器:Range(范围)对象——掌控文档的“手术刀”
前端
前端小白199541 分钟前
面试取经:工程化篇-webpack性能优化之减少模块解析
前端·面试·前端工程化
一枚前端小能手42 分钟前
🏗️ 项目越来越大维护不动了,微前端架构了解一下
前端