跳至主要內容
Flutter单选多选、Popover的实现

Flutter单选多选、Popover的实现

Comrade Wang大约 5 分钟移动端flutter

Flutter单选多选、Popover的实现

最近开发Flutter项目时发现,Flutter的组件DropdownButton使用时会有一些使用上的局限性(尤其是在Flutter Web中),所以在项目开发中,使用了两个组件做为DropdownButton组件的补充和拓展。本文旨在介绍组件,比较应用向,如果对组件想要更深入了解,请阅读官方文档。

官方文档地址:https://pub.dev/packages/dropdown_searchopen in new window 参考资料:https://morioh.com/p/bd8d453ec55eopen in new window

单选列表

参数名类型描述
itemsList<T>本地设置的选项列表
popupPropsPopupPropspopup的设置class
itemAsStringDropdownSearchItemAsString<T> 自定义options中显示的名称
onChangedValueChanged<T?>?当一个item被选中后的回调
selectedItemT?单选时选中对象
selectedItemsList<T>多选的时候选中的列表
Expanded(  
  child: DropdownSearch<LabelList>(  
    items: options,  
    popupProps: const PopupProps.menu(),  
    itemAsString: (option) => option.labelName,  
    onChanged: (value) {  
      setState(() {  
        selectedLabelList = value!;  
        valueOptions = value.labelValues;  
      });    
    },
    selectedItem: selectedLabelList,  
  ),)

这样你就得到了一个简单不带筛选功能的单选Select。

多选列表

参数名类型描述
itemsList<T>本地设置的选项列表
popupPropsPopupPropsMultiSelectionpopup的设置class
itemAsStringDropdownSearchItemAsString<T> 自定义options中显示的名称
onChangedValueChanged<T?>?当一个item被选中后的回调
selectedItemsList<T>多选的时候选中的列表
compareFnDropdownSearchCompareFn<T>?比对items与selectedItems的参数(用于回显选中状态)
Expanded(  
  child: DropdownSearch<Trigger>.multiSelection(  
    items: valueOptions,  
    popupProps: PopupPropsMultiSelection.menu(  
      showSearchBox: true,  
      searchFieldProps: TextFieldProps(  
          controller: TextEditingController(text: ''),  
          decoration:  
              const InputDecoration(hintText: '搜索标签')),  
    ),    
    itemAsString: (option) => option.value,  
    onChanged: (selectedList) {  
      setState(() {  
        triggerSelected = [...selectedList];  
      });    
    },    
    selectedItems: triggerSelected,  
    compareFn: (item1, item2) =>  
        item1.valueId == item2.valueId,  
  ),)

这样你也就获得了一个带有筛选功能多选框组。

官方文档地址:https://pub.dev/packages/dropdown_button2open in new window

(其实官网文档写的很详细,下面提供参数翻译和一个小例子)

OptionDescriptionTypeRequired
items用户可以选择的项目列表List<DropdownMenuItem>Yes
hint在用户选择一个项目之前显示的占位符WidgetNo
disabledHint如果下拉菜单被禁用,显示的占位符。WidgetNo
value当前选择的[DropdownMenuItem]的值TNo
onChanged当用户选择一个项目时被调用ValueChanged<T?>No
onMenuStateChange当下拉菜单被打开或关闭时被调用Function(bool isOpen)No
selectedItemBuilder所选项目将如何在按钮上显示DropdownButtonBuilderNo
buttonHeight按钮的高度doubleNo
buttonWidth按钮的宽度doubleNo
buttonPadding按钮的内部填充物EdgeInsetsGeometryNo
buttonDecoration按钮的装饰BoxDecorationNo
buttonElevation按钮的高度intNo
buttonSplashColor按钮InkWell的亮光颜色ColorNo
buttonHighlightColor按钮InkWell的高光色ColorNo
buttonOverlayColor按钮InkWell的叠加颜色MaterialStateProperty<Color?>No
icon下拉按钮的后缀图标WidgetNo
iconOnClick打开下拉菜单时显示不同的图标WidgetNo
iconSize图标的大小doubleNo
iconEnabledColor如果按钮被激活,图标的颜色ColorNo
iconDisabledColor如果按钮被禁用,图标的颜色ColorNo
itemHeight菜单项的高度doubleNo
itemPadding菜单项的paddingEdgeInsetsGeometryNo
itemSplashColor项目的InkWell的亮色ColorNo
itemHighlightColor项目的InkWell的高亮颜色ColorNo
dropdownMaxHeight下拉菜单的最大高度doubleNo
dropdownWidth下拉菜单的宽度doubleNo
dropdownPadding下拉菜单的内部paddingEdgeInsetsGeometryNo
dropdownScrollPadding包括滚动条在内的下拉菜单的内部paddingEdgeInsetsGeometryNo
dropdownDecoration下拉菜单的装饰BoxDecorationNo
dropdownDirection下拉菜单相对于按钮的方向DropdownDirectionNo
dropdownElevation下拉菜单的高度intNo
selectedItemHighlightColor当前所选项目的高亮颜色ColorNo
scrollbarRadius滚动条边角的半径RadiusNo
scrollbarThickness滚动条的厚度doubleNo
scrollbarAlwaysShow始终显示滚动条,即使是在没有滚动的情况下boolNo
offset改变下拉菜单的位置OffsetNo
customButton使用自定义的小部件,如图标、图片等,而不是默认的按钮。WidgetNo
customItemsHeights为菜单项使用不同的预定义高度(对添加分隔符很有用)。ListNo
isExpanded使按钮的内部内容扩大(设置为真以避免长文本溢出)。boolNo
openWithLongPress在长按时打开下拉菜单,而不是轻触。boolNo
dropdownOverButton在按钮上方而不是下方打开下拉菜单boolNo
dropdownFullScreen在全屏模式下打开下拉菜单(在AppBar和TabBar上面)boolNo
focusColor使用传统界面(键盘和鼠标)输入焦点时的按钮颜色ColorNo
barrierDismissible你是否可以通过点击模态障碍物来取消这一途径boolNo
barrierColor模态屏障的颜色。如果这个颜色为空,屏障将是透明的ColorNo
barrierLabel用于可撤销障碍物的语义标签StringNo
searchController用于可搜索下拉菜单的控制器,如果为空,那么它将作为普通下拉菜单执行。TextEditingControllerNo
searchInnerWidget用于可搜索下拉菜单顶部的部件,用于可搜索下拉菜单的部件。WidgetNo
searchMatchFn用于可搜索下拉菜单的匹配函数,如果为空,将使用defaultFnSearchMatchFnNo
DropdownButtonHideUnderline(  
  child: DropdownButton2(  
    isExpanded: true,  
    hint: Row(  
      children: const [  
        Expanded(  
          child: Text(  
            '更多',  
            style: TextStyle(  
              fontSize: 14,  
              fontWeight: FontWeight.bold,  
              color: Colors.white,  
            ),            overflow: TextOverflow.ellipsis,  
          ),),],),    
          items: _items .map(  
          (e) => DropdownMenuItem<MoreOption>(  
              value: e,  
              child: Text(  
                e.label,  
                style: const TextStyle(  
                  fontSize: 14,  
                  fontWeight: FontWeight.bold,  
                  color: Colors.black45,  
                ),                
                overflow: TextOverflow.ellipsis,  
              )),).toList(),  
    // value: _selectedValue,  
    onChanged: (item) {  
      item?.onTap();  
    },    
    buttonHeight: 36,  
    buttonWidth: 80,  
    buttonPadding: const EdgeInsets.only(left: 12, right: 12),  
    buttonDecoration: BoxDecoration(  
      borderRadius: BorderRadius.circular(40),  
      // border: Border  
      color: kPrimaryColor,  
    ),    
    buttonElevation: 2,  
    iconDisabledColor: Colors.grey,  
    iconEnabledColor: Colors.white,  
    itemHeight: 40,  
    itemPadding:  
        const EdgeInsets.only(left: 14, right: 14),  
    dropdownMaxHeight: 400,  
    dropdownWidth: 200,  
    dropdownPadding: null,  
    dropdownDecoration: BoxDecoration(  
      borderRadius: BorderRadius.circular(14),  
      color: Colors.white,  
    ),    
    dropdownElevation: 8,  
    scrollbarRadius: const Radius.circular(40),  
    scrollbarThickness: 6,  
    scrollbarAlwaysShow: true,  
    offset: const Offset(-20, 0),  
  ),)

appflowy_popover

上述两个组件,可以基本实现下拉框的功能,但是不能手动触发popover,这里推荐一个开源项目封装的popover,以供参考:

AppFlowyopen in new window