Flutter Chip的使用

Posted 一叶飘舟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter Chip的使用相关的知识,希望对你有一定的参考价值。

1. 基本介绍

Chip、ActionChip、ChoiceChip、FilterChip 是一个常见的标签控件,会内敛布局,并且有一些常用的点击功能。

2. 示例代码

代码下载地址。如果对你有帮助的话记得给个关注,代码会根据我的 Flutter 专题不断更新。

3. 属性介绍

Chip 属性介绍
avatar左侧图标组件
label@required 文本 Widget
labelStyle文本样式,TextStyle
labelPadding文本外边距 Padding
deleteIcon右侧删除按钮 Widget
onDeleted删除按钮点击事件
deleteIconColor删除按钮颜色
deleteButtonTooltipMessage长按删除按钮的提示语
shape形状,ShapeBorder
clipBehavior裁剪方式,默认为 Clip.none
focusNode焦点控制,Flutter 组件之 FocusNode 详解
autofocus自动聚焦,默认为 false
backgroundColor背景色
padding内边距 Padding
visualDensity紧凑程度,VisualDensity
materialTapTargetSize内边距,默认最小点击区域为 48 * 48,MaterialTapTargetSize.shrinkWrap 为组件实际大小
elevation阴影高度,默认为 0
shadowColor阴影颜色
CircleAvatar 属性介绍
child子控件 Widget
backgroundColor背景色
backgroundImage背景图
onBackgroundImageError背景图加载失败回调
foregroundColortext 颜色
radius半径 (和 maxRadius 以及 minRadius 不能同时存在)
minRadius最小半径 (和 radius 不能同时存在)
maxRadius最大半径 (和 radius 不能同时存在)

4. Chip 详解

import 'package:flutter/material.dart';

class FMChipVC extends StatefulWidget 
  @override
  FMChipState createState() => FMChipState();


class FMChipState extends State <FMChipVC>
  @override
  Widget build(BuildContext context) 
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("Chip"),),
      body: _listView(),
    );
  

  ListView _listView()
    return ListView(
      children: [
        _chipForSimpleText(),
        _chipForSimple(),
        _chipForNormal(),
        _chip(),
      ],
    );
  

  CircleAvatar _circleAvatar()
    return CircleAvatar(
      child: Container(
        height: 30,
        color: Colors.red,
        alignment: Alignment.center,
        child: Text("Avatar child text"),
      ), // avatar 子控件
      backgroundColor: Colors.red, // avatar 背景色
      foregroundColor: Colors.white, // avatar 中 text 颜色
      // avatra 背景图
      backgroundImage: NetworkImage("http://tiebapic.baidu.com/forum/w%3D580/sign=a96ca741eafaaf5184e381b7bc5594ed/7ea6a61ea8d3fd1f2643ad5d274e251f95ca5f38.jpg"),
      // 背景图加载失败回调
      onBackgroundImageError: (error, trace)
        print("onBackgroundImageError");
      ,
      // radius: 200, // avatar 半径 (和 maxRadius 以及 minRadius 不能同时存在)
      maxRadius: 100, // avatar 最小半径 (和 radius 不能同时存在)
      minRadius: 80, // avatar 最大半径 (和 radius 不能同时存在)
    );
  

  Chip _chipForSimpleText()
    return Chip(
        label: Text("Simple Text Chip")
    );
  

  Chip _chipForSimple()
    return Chip(
      label: Text("Simple Chip"),
      avatar: CircleAvatar(backgroundColor: Colors.red,),
    );
  

  Chip _chipForNormal()
    return Chip(
      label: Text("Normal Chip"),
      avatar: CircleAvatar(backgroundColor: Colors.red,),
      deleteIcon: Icon(Icons.ac_unit),
      onDeleted: (),
    );
  
  
  Chip _chip()
    return Chip(
      avatar: _circleAvatar(), // 左侧图标组件
      label: Text("text"), // 文本 Widget
      labelStyle: TextStyle(color: Colors.red, fontSize: 30), // 文本样式,TextStyle
      labelPadding: EdgeInsets.fromLTRB(15, 50, 0, 50), // 文本外边距 Padding

      deleteIcon: Icon(Icons.ac_unit), // 右侧删除按钮 Widget
      deleteButtonTooltipMessage: "deleteButtonTooltipMessage", // 长按删除按钮的提示语
      deleteIconColor: Colors.red, // 删除按钮颜色
      // 删除按钮点击事件
      onDeleted: ()
        print("onDeleted");
      ,
      // Chip 形状
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
        side: BorderSide(
          width: 2,
          color: Colors.red,
        ),
      ),

      // padding: EdgeInsets.zero,
    );
  

5. ActionChip 详解

相比 Chip,ActionChip 增加了 onPressed 的点击事件,同时 ActionChip 移除了 deleteIcon 等相关属性。

  ListView _listView()
    return ListView(
      children: [
        _chipForSimpleText(),
        _chipForSimple(),
        _chipForNormal(),
        _chip(),
        Padding(padding: EdgeInsets.all(10)),
        _actionChip(),
      ],
    );
  

  ActionChip _actionChip()
    return ActionChip(
      avatar: _circleAvatar(),
      onPressed: ()
        print("ActionChip onPressed");
      ,
      label: Text("ActionChip"), // 文本 Widget
      labelStyle: TextStyle(color: Colors.red, fontSize: 30), // 文本样式,TextStyle
      labelPadding: EdgeInsets.fromLTRB(15, 50, 0, 50), // 文本外边距 Padding

      // Chip 形状
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
        side: BorderSide(
          width: 2,
          color: Colors.red,
        ),
      ),
    );
  

6. ChoiceChip 详解

  ListView _listView()
    return ListView(
      children: [
        _chipForSimpleText(),
        _chipForSimple(),
        _chipForNormal(),
        _chip(),
        Padding(padding: EdgeInsets.all(10)),
        _actionChip(),
        Padding(padding: EdgeInsets.all(10)),
        _choiceChip(),
      ],
    );
  

  bool _choiceChipSelected = false;

  ChoiceChip _choiceChip()
    return ChoiceChip(
      avatar: _circleAvatar(), // 左侧图标组件
      label: Text("ChoiceChip"), // 文本 Widget
      labelStyle: TextStyle(color: Colors.red, fontSize: 30), // 文本样式,TextStyle
      labelPadding: EdgeInsets.fromLTRB(15, 50, 0, 50), // 文本外边距 Padding

      selected: _choiceChipSelected, // 是否选中
      selectedColor: Colors.yellow, // 选中背景色
      // 选中点击事件
      onSelected: (value)
        print("ChoiceChip onSelected");
        _choiceChipSelected = value;
        setState(() 

        );
      ,

      // Chip 形状
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
        side: BorderSide(
          width: 2,
          color: Colors.red,
        ),
      ),
    );
  

7. FilterChip 详解

  ListView _listView()
    return ListView(
      children: [
        _chipForSimpleText(),
        _chipForSimple(),
        _chipForNormal(),
        _chip(),
        Padding(padding: EdgeInsets.all(10)),
        _actionChip(),
        Padding(padding: EdgeInsets.all(10)),
        _choiceChip(),
        Padding(padding: EdgeInsets.all(10)),
        _filterChip(),
      ],
    );
  

  bool _filterChipSeleted = false;

  FilterChip _filterChip()
    return FilterChip(
      avatar: _circleAvatar(), // 左侧图标组件
      label: Text("text"), // 文本 Widget
      labelStyle: TextStyle(color: Colors.red, fontSize: 30), // 文本样式,TextStyle
      labelPadding: EdgeInsets.fromLTRB(15, 50, 0, 50), // 文本外边距 Padding

      selected: _filterChipSeleted, // 是否选中
      selectedColor: Colors.white, // 选中背景色
      // 点击回调
      onSelected: (value)
        _filterChipSeleted = value;
        setState(() 

        );
      ,

      showCheckmark: true, // 是否显示勾选框
      checkmarkColor: Colors.yellow, // 勾选框颜色

      // Chip 形状
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
        side: BorderSide(
          width: 2,
          color: Colors.red,
        ),
      ),
    );
  

8. 技术小结

Chip 其实并不难,就是属性较多,多加练习理解各个属性对应样式即可。 


扩展效果

一、效果

二、构造函数解析:

const Chip(
    Key key,
    this.avatar,//左侧的图标
    @required this.label,//这个是必填的参数,控件上显示的文本
    this.labelStyle,
    this.labelPadding,
    this.deleteIcon,//右侧的删除图标
    this.onDeleted,//删除图标的点击事件,如果不写该方法的话,deleteIcon显示不出来
    this.deleteIconColor,
    this.deleteButtonTooltipMessage,//点击删除图标后弹出的文本,类似于tooltip的效果
    this.shape,
    this.clipBehavior = Clip.none,//这个不晓得是啥
    this.backgroundColor,
    this.padding,
    this.materialTapTargetSize,//这个具体也不晓得怎么描述,它的两个值,一个为padded,一个为shrinkWrap,前者自带margin,后者好像没有margin,紧贴附近的控件
    this.elevation,//阴影深度
    this.shadowColor,//阴影颜色
  )

三、例子

import 'package:flutter/material.dart';
import 'package:the_first_one/utils/PageUtil.dart';
import 'InputChipDemo.dart';
import 'FilterChipDemo.dart';
import 'package:fluttertoast/fluttertoast.dart';

class ChipPage extends StatefulWidget 
  @override
  _ChipPageState createState() => _ChipPageState();


class _ChipPageState extends State<ChipPage> 
  int _valueChoice = 0;

  Widget _buildChoiceItem(int index) 
    return ChoiceChip(
      label: Text("ChoiceChip $index"),
      selectedColor: Colors.orange, //选中的颜色
      disabledColor: Colors.orange[100], //没选中的颜色
      onSelected: (bool selected) 
        setState(() 
          _valueChoice = selected ? index : null;
        );
      ,
      selected: _valueChoice == index,
      labelStyle: TextStyle(color: Colors.black54),
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("ChipDemo"),
      ),
      body: Center(
        child: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              SizedBox(height: 10.0),
              Text("一、初步认识"),
              Divider(),
              Chip(
                label: Text("普通的chip"),
                labelStyle: TextStyle(color: Colors.black54),
                backgroundColor: Colors.orange,
              ),
              Chip(
                avatar: Icon(
                  Icons.arrow_forward,
                  color: Colors.black54,
                ),
                label: Text("带avatar的chip"),
                labelStyle: TextStyle(color: Colors.black54),
                backgroundColor: Colors.orange,
              ),
              Chip(
                avatar: CircleAvatar(
                  backgroundImage:
                      AssetImage('assets/images/illustration_1.jpg'),
                  radius: 18.0,
                ),
                label: Text("带avatar的chip"),
                labelStyle: TextStyle(color: Colors.black54),
                backgroundColor: Colors.orange,
              ),
              Chip(
                avatar: CircleAvatar(
                  backgroundImage:
                      AssetImage('assets/images/illustration_1.jpg'),
                  radius: 30.0,
                ),
                padding: EdgeInsets.all(0.0),
                label: Text("padding为0,labelPadding不为0的chip"),
                labelPadding: EdgeInsets.all(15.0),
                labelStyle: TextStyle(
                  color: Colors.black54,
                  fontSize: 10.0,
                  fontWeight: FontWeight.bold,
                ),
                backgroundColor: Colors.orange,
              ),
              Chip(
                label: Text("带deleteIcon的chip"),
                deleteIcon: Icon(Icons.close),
                deleteIconColor: Colors.black54,
                onDeleted: () 
                  print("点击了删除噢");
                ,
                deleteButtonTooltipMessage: "弹出提示",
                labelStyle: TextStyle(color: Colors.black54),
                backgroundColor: Colors.orange,
              ),
              Chip(
                label: Text("圆角矩形的chip"),
                deleteIcon: Icon(Icons.close),
                deleteIconColor: Colors.black54,
                onDeleted: () 
                  print("点击了删除噢");
                ,
                deleteButtonTooltipMessage: "弹出提示",
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(2.0),
                ),
                labelStyle: TextStyle(color: Colors.black54),
                backgroundColor: Colors.orange,
              ),
              Chip(
                label: Text("尺寸最小的chip"),
                materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
                labelStyle: TextStyle(color: Colors.black54),
                backgroundColor: Colors.orange,
              ),
              Chip(
                label: Text("带阴影的chip"),
                shadowColor: Colors.grey,
                elevation: 10.0,
                labelStyle: TextStyle(color: Colors.black54),
                backgroundColor: Colors.orange,
              ),
              Divider(),
              Text("二、例子"),
              ActionChip(
                //自带一个onPress事件,有点击效果
                label: Text("ActionChip"),
                backgroundColor: Colors.orange,
                onPressed: () 
                  Fluttertoast.showToast(msg: "ActionChip");
                ,
              ),
              Wrap(
                spacing: 5.0, //主轴间距
                runSpacing: 8.0, //副轴间距
                children: List<Widget>.generate(2, (int index) 
                  return _buildChoiceItem(index);
                ),
              ),
              RaisedButton(
                  child: Text(
                    "FilterChipDemo",
                    style: TextStyle(color: Colors.black54),
                  ),
                  color: Colors.orange,
                  onPressed: () 
                    PageUtil().pushTo(context, FilterChipDemo());
                  ),
              RaisedButton(
                  child: Text(
                    "InputChipDemo",
                    style: TextStyle(color: Colors.black54),
                  ),
                  color: Colors.orange,
                  onPressed: () 
                    PageUtil().pushTo(context, InputChipDemo());
                  ),
              SizedBox(height: 10.0),
            ],
          ),
        ),
      ),
    );
  

四、其他

关于chip也可以看看以下扩展类,以下排列顺序按照功能的升序排列

  1. ActionChip //比普通的chip多一个onPressed事件
  2. ChoiceChip //允许从一组选项中进行单一选择
  3. FilterChip //自带的比ChoiceChip多一个选中的勾勾的效果
import 'package:flutter/material.dart';

class FilterChipDemo extends StatefulWidget 
  @override
  _FilterChipDemoState createState() => _FilterChipDemoState();


class ActorFilterEntry 
  const ActorFilterEntry(this.name, this.initials);

  final String name;
  final String initials;


class _FilterChipDemoState extends State<FilterChipDemo> 
  final List<ActorFilterEntry> _cast = <ActorFilterEntry>[
    const ActorFilterEntry('Aaron Burr', 'AB'),
    const ActorFilterEntry('Alexander Hamilton', 'AH'),
    const ActorFilterEntry('Eliza Hamilton', 'EH'),
    const ActorFilterEntry('James Madison', 'JM'),
  ];
  List<String> _filters = <String>[];

  Iterable<Widget> get actorWidgets sync* 
    for (ActorFilterEntry actor in _cast) 
      yield Padding(
        padding: const EdgeInsets.all(4.0),
        child: FilterChip(
          avatar: CircleAvatar(child: Text(actor.initials)),
          label: Text(actor.name),
          selected: _filters.contains(actor.name),
          onSelected: (bool value) 
            setState(() 
              if (value) 
                _filters.add(actor.name);
               else 
                _filters.removeWhere((String name) 
                  return name == actor.name;
                );
              
            );
          ,
        ),
      );
    
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("FilterChipDemo"),
      ),
      body: Column(
        children: <Widget>[
          Wrap(
            children: actorWidgets.toList(),
          ),
          Text('Look for: $_filters.join(', ')'),
        ],
      ),
    );
  

  1. InputChip //比FilterChip多一个onPressed和onDeleted
import 'package:flutter/material.dart';

class InputChipDemo extends StatefulWidget 
  @override
  _InputChipDemoState createState() => _InputChipDemoState();


class _InputChipDemoState extends State<InputChipDemo> 
  List<String> list = [
    "摇滚",
    "音乐",
    "机车党",
    "android工程师",
    "全栈",
    "Python",
    "UI设计师",
    "测试小姐姐",
    "后台单身狗",
    "产品老大",
    "路边摊",
    "火锅 串串 麻辣烫",
    "篮球",
    "摄影",
    "户外",
    "客服",
    "超级自恋的小哥哥",
    "直播",
    "不忘初心 继续前行",
    "记性不好",
    "花容月貌",
    "榴莲控",
    "一定要穿美美的衣服"
  ];

  List<String> _filters = <String>[];

  Widget _buildItem(int index) 
    String content = list[index];
    return InputChip(
      avatar: CircleAvatar(
        backgroundImage: AssetImage('assets/images/illustration_1.jpg'),
        radius: 12.0,
      ),
      label: Text(
        content,
        style: TextStyle(fontSize: 12.0),
      ),
      shadowColor: Colors.grey,
      deleteIcon: Icon(
        Icons.close,
        color: Colors.black54,
        size: 14.0,
      ),
      onDeleted: () 
        setState(() 
          list.removeAt(index);
        );
      ,
      onSelected: (bool selected) 
        setState(() 
          if (selected) 
            _filters.add(list[index]);
           else 
            _filters.removeWhere((String name) 
              return name == list[index];
            );
          
        );
      ,
      selectedColor: Colors.orange,
      disabledColor: Colors.grey,
      selected: _filters.contains(list[index]),
      materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
      labelStyle: TextStyle(color: Colors.black54),
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("InputChipDemo"),
      ),
      body: Container(
        padding: EdgeInsets.all(10.0),
        child: Wrap(
          spacing: 5.0,
          //主轴间距
          runSpacing: 8.0,
          //副轴间距
          alignment: WrapAlignment.end,
          //主轴上的对齐方式
          crossAxisAlignment: WrapCrossAlignment.center,
          //副轴上的对齐方式
          children: List<Widget>.generate(
            list.length,
            (int index) 
              return _buildItem(index);
            ,
          ).toList(),
        ),
      ),
    );
  


  1. RawChip //原始chip,通常仅在您想要创建自己的定制芯片类型时使用

五、补充

更多的应用场景,请点击我

以上是关于Flutter Chip的使用的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 标签类控件大全Chip

Flutter 标签类控件大全Chip

Flutter学习日记之Chip标签组件的使用

无法删除在 Flutter iOS 中使用 html/css 创建的 pdf 的页面外边距

在 Flutter 中的 Inkwell 小部件中添加边框半径

flutter - 显示列表距离时设置最大半径