美文网首页flutter
flutter 下拉筛选组件

flutter 下拉筛选组件

作者: 卢融霜 | 来源:发表于2021-10-19 15:30 被阅读0次

    效果图

    QQ录屏20211019151055202110191512221.gif

    网页版(第一次打开网址加载会很慢)
    网页版

    代码

    import 'dart:ui';
    
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';
    import 'package:flutter1/widget/drop_down_widget.dart';
    import 'package:flutter_screenutil/flutter_screenutil.dart';
    
    import 'base/base_routes_widget.dart';
    
    /// @description 作用:筛选组件演示
    /// @date: 2021/10/14
    /// @author:卢融霜
    class DropDownPage extends StatefulWidget {
      const DropDownPage({Key key}) : super(key: key);
    
      @override
      _DropDownPageState createState() => _DropDownPageState();
    }
    
    class _DropDownPageState extends State<DropDownPage> {
      List<String> titles = ["北京", "招标类型", "更多筛选"];
      List<Widget> listWidget = [];
      ScreenControl screenControl = ScreenControl();
      List<String> types = ["全部", "招标", "中标", "公示"];
    
      @override
      void initState() {
        listWidget = [
          Row(
            children: [
              Expanded(
                  flex: 1,
                  child: ListView.builder(itemBuilder: (context, index) {
                    return InkWell(
                      onTap: () {},
                      child: Container(
                        decoration: const BoxDecoration(
                            border: Border(
                                bottom: BorderSide(color: Color(0xffdddddd)))),
                        padding: EdgeInsets.all(10.r),
                        child: Text("北京", style: TextStyle(fontSize: 14.sp)),
                      ),
                    );
                  })),
              Expanded(
                  flex: 1,
                  child: ListView.builder(itemBuilder: (context, index) {
                    return InkWell(
                      onTap: () {
                        titles[0] = "省份";
                        screenControl.screenHide();
                      },
                      child: Container(
                        decoration: const BoxDecoration(
                            color: Color(0xffdddddd),
                            border: Border(
                                bottom: BorderSide(color: Color(0xffffffff)))),
                        padding: EdgeInsets.all(10.r),
                        child: Text("北京", style: TextStyle(fontSize: 14.sp)),
                      ),
                    );
                  }))
            ],
          ),
          ListView.builder(
              shrinkWrap: true,
              itemCount: types.length,
              itemBuilder: (context, index) {
                return Container(
                  width: double.infinity,
                  decoration: const BoxDecoration(
                      border: Border(bottom: BorderSide(color: Color(0xffdddddd)))),
                  padding: EdgeInsets.all(10.r),
                  child: InkWell(
                      onTap: () {
                        titles[1] = types[index];
                        screenControl.screenHide();
                      },
                      child: Text(
                        types[index],
                        style: TextStyle(fontSize: 14.sp),
                      )),
                );
              }),
          ListView(
            shrinkWrap: true,
            children: [
              Container(
                padding: EdgeInsets.only(
                    left: 15.r, top: 10.r, right: 15.r, bottom: 10.r),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text("检索内容",
                        style:
                            TextStyle(fontSize: 14.r, fontWeight: FontWeight.bold)),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        MaterialButton(
                          onPressed: () {},
                          color: Colors.blue,
                          textColor: Colors.white,
                          child: Text(
                            "全部",
                            style: TextStyle(fontSize: 14.r),
                          ),
                        ),
                        MaterialButton(
                          onPressed: () {},
                          color: Colors.blue,
                          textColor: Colors.white,
                          child: Text(
                            "标题",
                            style: TextStyle(fontSize: 14.r),
                          ),
                        ),
                        MaterialButton(
                          onPressed: () {},
                          color: Colors.blue,
                          textColor: Colors.white,
                          child: Text(
                            "内容",
                            style: TextStyle(fontSize: 14.r),
                          ),
                        )
                      ],
                    )
                  ],
                ),
              ),
              Container(
                padding: EdgeInsets.only(left: 15.r, right: 15.r, bottom: 10.r),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text("匹配方式",
                        style:
                            TextStyle(fontSize: 14.r, fontWeight: FontWeight.bold)),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        MaterialButton(
                          onPressed: () {},
                          color: Colors.blue,
                          textColor: Colors.white,
                          child: Text(
                            "全部",
                            style: TextStyle(fontSize: 14.r),
                          ),
                        ),
                        MaterialButton(
                          onPressed: () {},
                          color: Colors.blue,
                          textColor: Colors.white,
                          child: Text(
                            "模糊",
                            style: TextStyle(fontSize: 14.r),
                          ),
                        ),
                        MaterialButton(
                          onPressed: () {},
                          color: Colors.blue,
                          textColor: Colors.white,
                          child: Text(
                            "精准",
                            style: TextStyle(fontSize: 14.r),
                          ),
                        )
                      ],
                    )
                  ],
                ),
              )
            ],
          )
        ];
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return BaseRoutesWidget(
            title: '筛选组件',
            child: DropDownWidget(
              titles,
              listWidget,
              height: 40.r,
              bottomHeight: 400.r,
              screenControl: screenControl,
              child: Container(
                margin: EdgeInsets.only(top: 40.4.r),
                child: ListView.builder(itemBuilder: (context, index) {
                  return Container(
                    padding: EdgeInsets.all(15.r),
                    child: Text("item $index"),
                    decoration: BoxDecoration(
                        border: Border(
                            bottom: BorderSide(
                                color: const Color(0xffeeeeee), width: 0.4.r))),
                  );
                }),
              ),
            ));
      }
    }
    

    筛选组件

    import 'dart:ui';
    
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';
    import 'package:flutter1/widget/drop_down_head_widget.dart';
    import 'package:flutter_screenutil/flutter_screenutil.dart';
    
    /// @description 作用:多级筛选
    /// @date: 2021/10/14
    /// @author:卢融霜
    class DropDownWidget extends StatefulWidget {
      //标题集合
      List<String> titles;
    
      //展开视图集合
      List<Widget> listWidget;
    
      // 高度
      double height;
    
      //子集
      Widget child;
    
      //筛选文字大小
      double headFontSize;
    
      // 筛选图标icons
      IconData iconData;
    
      //筛选高度 限制
      // BoxConstraints constraints;
      double bottomHeight;
    
      ScreenControl screenControl;
    
      DropDownWidget(this.titles, this.listWidget,
          {this.child,
          this.height = 42,
          this.headFontSize,
          this.iconData,
          this.bottomHeight,
          this.screenControl,
          Key key})
          : super(key: key);
    
      @override
      _DropDownWidgetState createState() => _DropDownWidgetState();
    }
    
    AnimationController _controller;
    Animation<double> curve;
    //按钮旋转状态
    List<bool> rotateState = [];
    
    class _DropDownWidgetState extends State<DropDownWidget>
        with SingleTickerProviderStateMixin {
      int tabIndex = 0;
      final ScreenControl _screenControl = ScreenControl();
      bool showBottom = false;
    
      @override
      void initState() {
        super.initState();
        widget.bottomHeight ??= 400.r;
        //展开隐藏控制器,动画初始化
        _controller = AnimationController(
            vsync: this, duration: const Duration(milliseconds: 200));
        curve = CurvedAnimation(parent: _controller, curve: Curves.decelerate);
        curve = Tween(begin: 0.0, end: widget.bottomHeight).animate(curve)
          ..addListener(() {
            setState(() {
              if (curve.value > 0) {
                showBottom = true;
              } else {
                showBottom = false;
              }
            });
          });
        rotateState = [];
        widget.titles.toList().forEach((element) {
          rotateState.add(false);
        });
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Stack(
          children: [
            Container(
              alignment: Alignment.center,
              height: widget.height,
              decoration: BoxDecoration(
                  border: Border(
                      bottom: BorderSide(
                          color: const Color(0xffe4e7ed), width: 0.4.r))),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: getScreenTitle(),
              ),
            ),
            widget.child,
            getBottomScreen()
          ],
        );
      }
    
      List<Widget> getScreenTitle() {
        List<Widget> widgets = [];
        if (widget.titles.isNotEmpty) {
          for (int i = 0; i < widget.titles.length; i++) {
            widgets.add(Expanded(
                flex: 1,
                child: DropDownHeadWidget(
                  widget.titles[i],
                  getRoState(i),
                  () {
                    print("click${rotateState.length}");
                    setState(() {
                      tabIndex = i;
                      for (int j = 0; j < rotateState.length; j++) {
                        if (i == j) {
                          if (rotateState[j]) {
                            rotateState = rotateState.map((e) => false).toList();
                            _controller.reverse();
                          } else {
                            rotateState = rotateState.map((e) => false).toList();
                            rotateState[j] = !rotateState[j];
                            _controller.forward();
                          }
                        }
                      }
                    });
                  },
                  headFontSize: widget.headFontSize,
                  iconData: widget.iconData,
                )));
          }
        } else {
          widgets.add(Text(
            "数组为空",
            style: TextStyle(fontSize: 14.sp),
          ));
        }
        return widgets;
      }
    
      Widget getBottomScreen() {
        return SizedBox(
          height: showBottom ? double.infinity : 0.0,
          child: GestureDetector(
            onTap: () {
              _screenControl.screenHide();
            },
            child: getBottomIndex(),
          ),
        );
      }
    
      bool getRoState(int i) {
        if (rotateState.isEmpty || rotateState.length < i + 1) {
          return false;
        }
        return rotateState[i];
      }
    
      Widget getBottomIndex() {
        widget.bottomHeight ??= 400.r;
    
        return Container(
          margin: EdgeInsets.only(top: widget.height),
          alignment: Alignment.topCenter,
          color: Colors.black26,
          height: MediaQuery.of(context).size.height - widget.height,
          width: double.infinity,
          child: Container(
            width: double.infinity,
            constraints: BoxConstraints(maxHeight: curve.value),
            color: Colors.white,
            child: widget.listWidget[tabIndex],
          ),
        );
      }
    }
    
    class ScreenControl {
      //自动
      void autoDisplay() {
        if (_controller.isDismissed) {
          _controller.forward();
        } else {
          _controller.reverse();
          rotateState = rotateState.map((e) => false).toList();
        }
      }
    
      //显示
      void screenShow() {
        _controller.forward();
      }
    
      //隐藏
      void screenHide() {
        _controller.reverse();
        rotateState = rotateState.map((e) => false).toList();
      }
    }
    
    

    筛选头部组件

    import 'dart:ui';
    
    import 'package:flutter/animation.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_screenutil/flutter_screenutil.dart';
    
    /// @description 作用:多级筛选item
    /// @date: 2021/10/14
    /// @author:卢融霜
    class DropDownHeadWidget extends StatefulWidget {
      String title;
      bool isForward;
      Function onClick;
      double headFontSize;
      IconData iconData;
    
      DropDownHeadWidget(this.title, this.isForward, this.onClick,
          {this.headFontSize = 12.0, this.iconData = Icons.arrow_drop_down_outlined, key})
          : super(key: key);
    
      @override
      State<StatefulWidget> createState() {
        return _DropDownHeadWidgetState();
      }
    }
    
    class _DropDownHeadWidgetState extends State<DropDownHeadWidget>
        with SingleTickerProviderStateMixin {
      AnimationController controller;
      Animation shAnimation;
    
      @override
      void dispose() {
        controller.dispose();
        super.dispose();
      }
    
      @override
      void didUpdateWidget(covariant DropDownHeadWidget oldWidget) {
        if (widget.isForward) {
          controller.forward();
        } else {
          controller.reverse();
        }
        super.didUpdateWidget(oldWidget);
      }
    
      @override
      void initState() {
        controller = AnimationController(
            duration: const Duration(milliseconds: 200), vsync: this);
        shAnimation = Tween(begin: .0, end: .5).animate(controller)
          ..addStatusListener((status) {
            setState(() {
              if (status == AnimationStatus.completed) {
              } else {}
            });
          });
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        TextStyle headTextStyle;
        Icon iconData;
        if (shAnimation.isCompleted) {
          headTextStyle ??=
              TextStyle(fontSize: widget.headFontSize, color: Colors.blue);
          iconData = Icon(
    
            widget.iconData??Icons.arrow_drop_down_sharp,
            color: Colors.blue,
            size: 20.sp,
          );
          //
        } else {
          headTextStyle = TextStyle(
              fontSize: widget.headFontSize, color: const Color(0xff333333));
          iconData = Icon(
            widget.iconData??Icons.arrow_drop_down_sharp,
            size: 20.sp,
            color: const Color(0xff333333),
          );
        }
        return InkWell(
          onTap: () {
            widget.onClick();
          },
          child: Container(
              alignment: Alignment.center,
              width: double.infinity,
              height: double.infinity,
              padding: EdgeInsets.only(left: 5.r, right: 5.r),
              child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
                Text(widget.title, style: headTextStyle),
                RotationTransition(
                  turns: shAnimation,
                  child: iconData,
                )
              ])),
        );
      }
    }
    
    

    相关文章

      网友评论

        本文标题:flutter 下拉筛选组件

        本文链接:https://www.haomeiwen.com/subject/dveaoltx.html