Flutter实现自定义下拉选择框的示例详解

在一些列表页面中,我们经常会有上方筛选项的的需求,点击出现一个下拉菜单,多选、单选、列表选等,而在Flutter中,并没有现成的这样的组件,找第三方的扩展有时候又会受到一定限制,所以最好我们可以自己做一个,这样即使扩展我们也会得心应手。

先看效果图:

关键点:弹出、收回动画、状态改变、选项联动

思路: 我们可以看到一个完整的下拉框有头部和具体的下拉选项两部分组成,头部又和下拉组进行了联动, 把头部当做1个数组,下方选项作为1个数组,两个数组数量一致之间形成一个完整的下拉选择框可以更好的控制联动效果。

首先我们看弹出和收回,我们可以把他看作一个组件的高度由0逐渐扩大再逐渐缩小至0,只要我们对这个组件的高度用动画来进行控制就可以实现,下方有一个黑色透明度渐变,这里我们根据上方弹窗的动画来改变下方黑色阴影的变化即可。

关键代码:

/// 下拉组件
@override
Widget build(BuildContext context) {
  return Column(
    children: [
      _MenuBuilder(
        animation: animation,
        // 这里显示我们需要的具体下拉框选项内容
        child: widget.children[widget.menuController.index],
      ),
      isShowShadow // 是否显示下方黑色阴影 只有下拉弹出才显示 这个地方我们就可以根据UI设计来进行高度自定义
          ? Expanded(
              child: InkWell(
              child: AnimatedBuilder(
                  animation: animation,
                  builder: (context, child) {
                  // 这里是下拉框下方阴影 点击阴影隐藏下拉框
                    return Container(
                      width: double.infinity,
                      height: MediaQuery.of(context).size.height,
                      color: Colors.black
                          .withOpacity(animation.value / (widget.height * 3)),
                    );
                  }),
              onTap: () {
                widget.menuController.hide();
              },
            ))
          : const SizedBox(),
    ],
  );
}

class _MenuBuilder extends StatelessWidget {
  final Animation<double> animation;
  final Widget child;

  const _MenuBuilder({required this.animation, required this.child});

// 这里我们主要用动画来控制下拉内容组件的高度
  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        child: child,
        animation: animation,
        builder: (context, child) {
          return Container(
            color: Colors.white,
            height: animation.value,
            child: child,
          );
        });
  }

接下来我们看头部设计,头部设计稍微复杂一些,主要还是状态的改变,选项之间的联动,这里我们新建一个状态控制器:主要来对头部的一些状态进行控制,比如点击头部按钮之后的文字or颜色的改变,选择完毕颜色的保存,重置颜色的恢复等一些状态,下方控制器主要就是来控制头部的一些状态。

/// 菜单控制器
class MenuController extends ChangeNotifier {
  // 当前组件是否显示 默认不显示 针对整个菜单数组
  bool isShow = false;

  // 显示当前组件title的文本 共用
  String title = "";

  // 显示哪个下拉框
  int index = 0;

  // 选择下拉框的的title 这个字段只有在真正选择的时候才会改变
  int titleIndex = 0;

  /// 更改Title
  changeTitle(int titleIndex, String? title) {
    this.titleIndex = titleIndex;
    this.title = title ?? "";
    hide();
  }

  // 显示下拉 index 为下拉哪一个菜单的index
  show(int index) {
    this.index = index;
    if (!isShow) {
      isShow = true;
    }
    notifyListeners();
  }

  // 隐藏 取消
  hide() {
    isShow = false;
    notifyListeners();
  }
}

有了控制器我们还需要对头部数据进行处理,首先我们的头部在没有选择选项的时候会有一个默认的数组,这个是永远不会改变的,所以这个数组一旦设置了就不能改变了,之后我们新建一个动态数组也就是当前显示的数组,这个数组的默认值就是我们未选择选项的默认值,这里我们需要监听头部状态的改变来对显示数组进行处理。

关键代码:重点 主要针对头部状态改变的处理,这块代码搞清楚了,基本就OK了。

@override
void initState() {
  super.initState();
  // changeTitles就是我们的显示数组
  changeTitles.addAll(widget.titles);
  for (var i = 0; i < changeTitles.length; i++) {
  //_chindren 是我们的头部组件数组
    _children.add(searchFilter(changeTitles[i], i));
  }
  widget.menuController.addListener(() {

    // 下拉 true 隐藏 false
    var isShow = widget.menuController.isShow;

    // 改变头部状态
    setState(() {
      if (widget.menuController.title != "") {
      // 说明当前选择了选项 赋值我选择的选项
        changeTitles[widget.menuController.titleIndex] =
            widget.menuController.title;
      } else {
      // 为空 说明当前的选项我清空了 赋值初始头部数组的数据
        changeTitles[widget.menuController.titleIndex] =
            widget.titles[widget.menuController.titleIndex];
      }
      // currentIndex 当前选择的index 默认-1 用来对比更新头部文字和颜色
      // 如果下拉 更新当前选项inedx 如果隐藏说明没有选择任何一个下拉框 置为-1
      if (isShow && currentIndex < widget.titles.length) {
        currentIndex = widget.menuController.index;
      } else {
        currentIndex = -1;
      }
      // 每次下拉收回我们只需改变头部数据即可 changeTitles 永远都是显示的数组 直接全部更新到组件即可
      _children.clear();
      for (var i = 0; i < changeTitles.length; i++) {
        _children.add(searchFilter(changeTitles[i], i));
      }
    });
  });
}

// 这里就是一个简单的Row数组 按照百分比排列 也可以自定义不同宽度
@override
Widget build(BuildContext context) {
  return SizedBox(
    height: widget.headHeight ?? 45,
    child: Row(children: _children),
  );
}

主要对头部文本内容以及颜色进行更新,如果当前选项=头部中的选项||或者 选项赋值的名字不等于初始值我们就认为选中了此菜单,从而改变颜色。到这里基本逻辑就梳理清楚了,下拉框样式这个可以自己根据自己的业务进行自定义。

Widget searchFilter(String name, int index) {
TextStyle(color: currentIndex == index || widget.titles[index] != name
                      ? widget.clickColor
                      : widget.defaultColor),
}

附源码地址

总结

思路就是整个页面的下拉组件视为一体,这样做的目的也是为了在切换不同选项的时候可以省略收回又打开的繁琐动画,可以有一种整体的体验,那在做这个下拉框主要用到了动画以及状态管理相关的技能,可以说在Flutter编程思想里,状态式编程是跟原生的应用式编程的最大区别,只有真正的掌握了这两个技能,才能更好的理解下拉框的实现的过程。

到此这篇关于Flutter实现自定义下拉选择框的示例详解的文章就介绍到这了,更多相关Flutter下拉选择框内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android 列表选择框 Spinner详解及实例

    Android 列表选择框 Spinner详解及实例 Spinner 是 Android 的列表选择框,不过 spinner 并不需要显示下拉列表,而是相当于弹出一个菜单供用户选择. Spinner 属性: ● android:spinnerMode:列表显示的模式,有两个选择,为弹出列表(dialog)以及下拉列表(dropdown),如果不特别设置,为下拉列表. ● android:entries:使用<string-array.../>资源配置数据源. ● android:prompt:

  • Android Spinner列表选择框的应用

    Android  Spinner列表选择框的应用 Spinner 是 Android 的列表选择框,不过 spinner 并不需要显示下拉列表,而是相当于弹出一个菜单供用户选择. Spinner 属性: ● android:spinnerMode:列表显示的模式,有两个选择,为弹出列表(dialog)以及下拉列表(dropdown),如果不特别设置,为下拉列表. ● android:entries:使用<string-array.../>资源配置数据源. ● android:prompt:对当

  • Android编程实现变化的双重选择框功能示例

    本文实例讲述了Android编程实现变化的双重选择框功能.分享给大家供大家参考,具体如下: 原理:定义四个RadioGroup,通过第一个RadioGroup的选择来控制其余几个radiogroup的显隐 布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&quo

  • Android列表选择框Spinner使用方法详解

    安卓提供的列表选择框(Spinner)相当于web端用户注册时的选择下拉框,比如注册候选择省份城市等.如下图便是一个列表选择框 下拉列表的列表选择项能够通过xml文件的android:entries属性指定,或是在java代码中导入,属性android:prompt是列表项的标题. 一 列表项数据 实际运用当中,很多下拉列表项的数据实际是可知的,可以放在xml资源文件中.这时,开发者可以通过xml属性进行指定数据. 除了资源文件之外,开发者还能够使用适配器适配数据源.(适配器:如果您的电脑不能接

  • Android BSearchEdit 搜索结果选择框的实例代码

    EditText搜索结果下拉框.自动or回调模式.可diy.使用超简便 (EditText search results drop-down box, auto or callback mode, diy, easy to use) Github地址 YangsBryant/BSearchEdit (Github排版比较好,建议进入这里查看详情,如果觉得好,点个star吧!) 引入module allprojects { repositories { google() jcenter() mav

  • Flutter实现自定义下拉选择框的示例详解

    在一些列表页面中,我们经常会有上方筛选项的的需求,点击出现一个下拉菜单,多选.单选.列表选等,而在Flutter中,并没有现成的这样的组件,找第三方的扩展有时候又会受到一定限制,所以最好我们可以自己做一个,这样即使扩展我们也会得心应手. 先看效果图: 关键点:弹出.收回动画.状态改变.选项联动 思路: 我们可以看到一个完整的下拉框有头部和具体的下拉选项两部分组成,头部又和下拉组进行了联动, 把头部当做1个数组,下方选项作为1个数组,两个数组数量一致之间形成一个完整的下拉选择框可以更好的控制联动效

  • 基于jQuery下拉选择框插件支持单选多选功能代码

    由于最近项目的需求,需要做一个下拉选择框的插件,支持单选显示表单数据,多选显示表格数据,该插件主要运用了jQuery与jqgrid以及easyui. 下面给大家展示下效果图,如果大家感觉还不错,请参考实现代码: 多选:呈现列表 具体代码如下所示: /** *下拉框插件-chooseList *调用插件的方式以及格式: * 1.首先你需要创建一个div面板,给div定义ID * 2.在你所需要的地方调用插件: * 参数说明: * $("#divID").chooseList({ * qu

  • Vue下拉选择框Select组件使用详解(二)

    本文实例为大家分享了Vue下拉选择框Select组件的使用方法,供大家参考,具体内容如下 效果图如下: 下拉组件宽度可自定义设置以下属性: ①下拉组件宽度width属性,默认宽度290 ②placeholder属性 ③是否禁用下拉的disabled属性 已预设下拉列表最多8条,超过时滚动显示,具体可自定义调整,如果下拉选项过长省略号显示,鼠标悬浮显示全称,由于业务需求,设置mode属性,区别默认name和value  与  dictKey和dictVal ①创建组件Select.vue <tem

  • Vue下拉选择框Select组件使用详解(一)

    本文实例为大家分享了Vue下拉选择框Select组件的使用方法,供大家参考,具体内容如下 效果图如下: 展开图如下: ①创建组件Select.vue:预设两种主题色,亦可视情况进行自定义修改样式: <template>   <div class="m-select-wrap">     <input       :class="['u-select-input f16', color === 'blue' ? '' : 'white-color'

  • 多级联动下拉选择框,动态获取下一级

    多级联动下拉选择框,动态获取下一级,每一级数据为XML,可支持无限级(浏览器端需要Microsoft.XMLDOM支持) 项目需要,一个材料类别表,三级,总共有7000多条记录,如果一次获取会很慢的,所以就是用了动态读取,每次就读一级,且服务器端使用了缓存,效率还不错. HTML代码如下: <select name="MaterialClass1" ChildSelectName="MaterialClass2"></select><s

  • js下拉选择框与输入框联动实现添加选中值到输入框的方法

    本文实例讲述了js下拉选择框与输入框联动实现添加选中值到输入框的方法.分享给大家供大家参考.具体如下: 这里演示js下拉选择框与输入框联动,直接添加选中值到输入框中的效果.这种效果相信不少朋友见到过吧,省去用户输入的麻烦,这里使用JS直接将值赋予输入框,了解原理之后,可灵活运用,扩展出更多的特效来. 运行截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-select-value-to-input-codes/ 具体代码如下: <html> <

  • JS实现的5级联动Select下拉选择框实例

    本文实例讲述了JS实现的5级联动Select下拉选择框.分享给大家供大家参考.具体如下: 这是一个基于JS的5级联动Select下拉选择框,这里演示的仅是一个示例,没有做汉化,当初从老外网站扒下时花了很多时间,当然我们平时用时候可能不需要这么多级,意在介绍一种编写方法和思路,希望大家喜欢. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-select-5-option-codes/ 具体代码如下: <title>一个基于JS的5级联动Se

  • JS简单设置下拉选择框默认值的方法

    本文实例讲述了JS简单设置下拉选择框默认值的方法.分享给大家供大家参考,具体如下: //根据下拉对象默认选中后台对应的记录 function setSelectOption(objSelect, targetValue){ if(objSelect){ var options = objSelect.options; if(options){ var len = options.length; for(var i=0;i<len;i++){ if(options[i].value == targ

  • python+selenium select下拉选择框定位处理方法

    一.前言 总结一下python+selenium select下拉选择框定位处理的两种方式,以备后续使用时查询: 二.直接定位(XPath) 使用Firebug找到需要定位到的元素,直接右键复制XPath,使用find_element_by_xpath定位: driver = webdriver.Firefox() driver.get("https://www.baidu.com/") driver.find_element_by_xpath().click() 三.间接定位(Sel

  • Layui动态生成select下拉选择框不显示的解决方法

    给代码添加如下部分: layui.use('form', function(){ //此段代码必不可少 var form = layui.form; form.render(); }); 实现效果: HTML代码: <div class="layui-form-item"> <label class="layui-form-label">执行周期</label> <div class="layui-input-in

随机推荐