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

发布于:2024-05-07 ⋅ 阅读:(23) ⋅ 点赞:(0)
Flutter笔记
Widgets Easier组件库 - 使用标签(Tag)

- 文章信息 -
Author: 李俊才 (jcLee95)
Visit me at CSDN: https://jclee95.blog.csdn.net
My WebSitehttp://thispage.tech/
Email: 291148484@163.com.
Shenzhen China
Address of this article:https://blog.csdn.net/qq_28550263/article/details/138425637
HuaWei:https://bbs.huaweicloud.com/blogs/426978

组件库地址


【介绍】:本文介绍Flutter的Widgets Easier组件库中:Widgets Easier组件库 - 标签(Tag)的使用方法。

flutter-ljc](https://jclee95.blog.csdn.net/)


上一节:《 - | 下一节:《 -


1. 概述

1.1 关于Widgets Easier

本库是一个 Flutter 组件库,旨在提供用于Flutter开发的组件,使得开发者能够更简单地构建出更丰富地界面效果。项目地址为:

1.2 模块安装

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

flutter pub add widgets_easier

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

2. 基本用法

2.1 语义类型

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

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,正如上一节所展示的那样。下面展示lightdark两个主题:

light

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

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则没有圆角:

Tag('radius: 0', radius: 0),

在这里插入图片描述

2.4 尺寸

枚举尺寸

例如:

Tag('SizeEnum.small', size: SizeEnum.small),
Tag('SizeEnum.defaultSize', size: SizeEnum.defaultSize),
Tag('SizeEnum.large', size: SizeEnum.large),

数值尺寸

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

Tag('hignt=50', height: 50),

在这里插入图片描述

收缩属性

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

Tag('shrink: false', shrink: false)

在这里插入图片描述

2.5 可关闭标签

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

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 事件来实现动态编辑标签。例如:

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

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

  
  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);
      });
    }
  }

  
  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 相同,导致视图没有正确更新。

这里,初始的 _tags 列表为 ['Tag 1', 'Tag 2', 'Tag 3'],不断点击第一个Tag的close图标,看起来效果就成了这样:

在这里插入图片描述

在这个过程中:

  1. Flutter 根据这个列表构建了三个 Tag 组件,它们在组件树中的位置分别为 0, 1, 2;

  2. 现在,如果你删除了 ‘Tag 1’,_tags 列表变为 ['Tag 2', 'Tag 3']

  3. Flutter 在更新组件树时,会比较新的组件列表与旧的组件列表:

    • 在位置 0,它发现新的组件列表中有一个 Tag 组件,显示 ‘Tag 2’。但在旧的组件列表中,这个位置显示的是 ‘Tag 1’。因为 Flutter 使用位置来匹配组件,所以它认为这个 Tag 组件没有变化,仍然显示 ‘Tag 1’;

    • 在位置 1,它发现新的组件列表中有一个 Tag 组件,显示 ‘Tag 3’。同样,因为位置匹配,Flutter 认为这个 Tag 组件没有变化,仍然显示 ‘Tag 2’;

    • 在位置 2,它发现新的组件列表中没有 Tag 组件了,所以它会移除这个位置的 Tag 组件。

  4. 最终,视图中显示的 Tag 组件是 ‘Tag 1’ 和 ‘Tag 2’,而不是 ‘Tag 2’ 和 ‘Tag 3’。

后面再次点击时类似。这就导致了在没有使用 key 的情况下,删除操作会导致视图与实际数据不一致。