Flutter笔记:Widgets Easier组件库 - 使用标签(Tag)

Flutter笔记 Widgets Easier组件库 - 使用标签(Tag)

1. 概述

1.1 关于Widgets Easier

本库是一个 Flutter 组件库,旨在提供用于Flutter开发的组件,使得开发者能够更简单地构建出更丰富地界面效果。对于iOS开发者来说,在完成Flutter应用开发后,可以使用AppUploader这样的iOS开发助手工具来简化应用的上架流程。

1.2 模块安装

在你的Flutter项目中,运行下面的命令:

bash 复制代码
flutter pub add widgets_easier

即可安装最新版本的 Widgets Easier 库。

2. 基本用法

2.1 语义类型

通过Tag组件的type参数可以使用一个语义性色彩。例如:

dart 复制代码
const Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: [
    Tag('tag', type: SemanticEnum.primary),
    Tag('tag', type: SemanticEnum.secondary),
    Tag('tag', type: SemanticEnum.info),
    Tag('tag', type: SemanticEnum.success),
    Tag('tag', type: SemanticEnum.warning),
    Tag('tag', type: SemanticEnum.danger),
    Tag('tag', type: SemanticEnum.fatal),
  ],
),

2.2 样式主题

受启发与Element-plus,Tag 有3个样式主题,plainlightdark,默认情况下为palin

light
dart 复制代码
const Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: [
    Tag('tag', theme: TagThemeEnum.light, type: SemanticEnum.primary),
    Tag('tag', theme: TagThemeEnum.light, type: SemanticEnum.secondary),
    Tag('tag', theme: TagThemeEnum.light, type: SemanticEnum.info),
    Tag('tag', theme: TagThemeEnum.light, type: SemanticEnum.success),
    Tag('tag', theme: TagThemeEnum.light, type: SemanticEnum.warning),
    Tag('tag', theme: TagThemeEnum.light, type: SemanticEnum.danger),
    Tag('tag', theme: TagThemeEnum.light, type: SemanticEnum.fatal),
  ],
),
dark
dart 复制代码
const Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: [
    Tag('tag', theme: TagThemeEnum.dark, type: SemanticEnum.primary),
    Tag('tag', theme: TagThemeEnum.dark, type: SemanticEnum.secondary),
    Tag('tag', theme: TagThemeEnum.dark, type: SemanticEnum.info),
    Tag('tag', theme: TagThemeEnum.dark, type: SemanticEnum.success),
    Tag('tag', theme: TagThemeEnum.dark, type: SemanticEnum.warning),
    Tag('tag', theme: TagThemeEnum.dark, type: SemanticEnum.danger),
    Tag('tag', theme: TagThemeEnum.dark, type: SemanticEnum.fatal),
  ],
),

2.3 圆角

默认有一个大小为4的圆角,若要手动修改可以通过指定radius参数。radius参数接受一个double值。例如,设置radius为0则没有圆角:

dart 复制代码
Tag('radius: 0', radius: 0),

2.4 尺寸

枚举尺寸

例如:

dart 复制代码
Tag('SizeEnum.small', size: SizeEnum.small),
Tag('SizeEnum.defaultSize', size: SizeEnum.defaultSize),
Tag('SizeEnum.large', size: SizeEnum.large),
数值尺寸

通过height参数可以指定数值作为尺寸。height一经指定,则size失效。例如,指定高度为50:

dart 复制代码
Tag('hignt=50', height: 50),
收缩属性

通过指定shrink属性为flase,可以使一个标签尽可能占满一行,例如:

dart 复制代码
Tag('shrink: false', shrink: false)

2.5 可关闭标签

通过指定 closable: true,将展示一个关闭图标。例如:

dart 复制代码
const Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: [
    Tag('tag', closable: true, type: SemanticEnum.primary),
    Tag('tag', closable: true, type: SemanticEnum.secondary),
    Tag('tag', closable: true, type: SemanticEnum.info),
    Tag('tag', closable: true, type: SemanticEnum.success),
    Tag('tag', closable: true, type: SemanticEnum.warning),
    Tag('tag', closable: true, type: SemanticEnum.danger),
    Tag('tag', closable: true, type: SemanticEnum.fatal),
  ],
),

2.6 动态编辑标签示例

可以通过点击标签关闭按钮后触发的 onClose 事件来实现动态编辑标签。例如:

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

class DynamicTagsExample extends StatefulWidget {
  const DynamicTagsExample({super.key});

  @override
  State<DynamicTagsExample> createState() => _DynamicTagsExampleState();
}

class _DynamicTagsExampleState extends State<DynamicTagsExample> {
  final List<String> _tags = ['Tag 1', 'Tag 2', 'Tag 3'];
  final String _newTagButtonText = '+ 添加 Tag';

  void _handleClose(int index) {
    setState(() {
      _tags.removeAt(index);
    });
  }

  void _handleSubmitted(String value) {
    if (value.isNotEmpty) {
      setState(() {
        _tags.add(value);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Wrap(
      spacing: 8,
      runSpacing: 8,
      children: [
        Text('$_tags'),
        for (int index = 0; index < _tags.length; index++)
          Tag(
            key: UniqueKey(), // 重要
            _tags[index],
            type: SemanticEnum.primary,
            theme: TagThemeEnum.light,
            closable: true,
            onClose: (_) {
              _handleClose(index);
            },
          ),
        Tag(
          _newTagButtonText,
          type: SemanticEnum.danger,
          editable: true,
          restoreAfterSubmitted: true,
          onSubmitted: _handleSubmitted,
        ),
      ],
    );
  }
}

这个例子恰好是一定要指定key的例子,顺便说一下一种错误情况。

在没有使用 key 的情况下,Flutter 在构建组件树时,会根据组件的位置来匹配新旧组件。当删除一个 Tag 时,其后面的 Tag 会向前移动,占据被删除的 Tag 的位置。但是,Flutter 并不知道这种位置的变化,它仍然认为在原来的位置上的 Tag 与之前的 Tag相同,导致视图没有正确更新。

相关推荐
cyforkk6 小时前
Spring Boot @RestController 注解详解
java·spring boot·后端
canonical_entropy7 小时前
可逆计算:一场软件构造的世界观革命
后端·aigc·ai编程
重庆穿山甲7 小时前
从0到1:用 Akka 持久化 Actor + Outbox + RocketMQ 做到“订单-库存最终一致”
后端
我不只是切图仔8 小时前
我只是想给网站加个注册验证码,咋就那么难!
前端·后端
专注VB编程开发20年8 小时前
CSS 的命名方式像是 PowerShell 的动词-名词结构,缺乏面向对象的层级关系
开发语言·后端·rust
野犬寒鸦8 小时前
力扣hot100:相交链表与反转链表详细思路讲解(160,206)
java·数据结构·后端·算法·leetcode
爱吃烤鸡翅的酸菜鱼9 小时前
【Spring】原理:Bean的作用域与生命周期
后端·spring
JohnYan9 小时前
工作笔记 - 微信消息发送和处理
javascript·后端·微信