美文网首页Flutter UIflutter
flutter 自定义单列下拉筛选组件

flutter 自定义单列下拉筛选组件

作者: 卢融霜 | 来源:发表于2021-08-16 17:58 被阅读0次

    运行效果:

    QQ录屏2021081617505520218161752432.gif

    筛选组件类

    import 'package:flutter/material.dart';
    import 'package:flutter_screenutil/flutter_screenutil.dart';
    
    /// @description 作用:列表筛选组件
    /// @date: 2021/8/16
    /// @author:卢融霜
    class ScreenWidget extends StatefulWidget {
      //筛选视图高度
      double topBarHeight;
      //显示标题
      Widget titleWidget;
      //筛选组件
      Widget screenListWidget;
      //子组件
      Widget child;
      //控制器,开关
      ScreenController controller;
      //打开监听
      Function screenOpen;
      //关闭监听
      Function screenClose;
    
      ScreenWidget(
          {Key key,
          this.controller,
          this.topBarHeight = 0,
          this.screenOpen,
          this.screenClose,
          @required this.titleWidget,
          @required this.screenListWidget,
          @required this.child})
          : super(key: key);
    
      @override
      _ScreenWidgetState createState() => _ScreenWidgetState();
    }
    
    AnimationController raController;
    Animation _raAnimation;
    Animation<double> _heAnimation;
    double viewHegin = 0;
    
    class _ScreenWidgetState extends State<ScreenWidget>
        with SingleTickerProviderStateMixin {
      @override
      void dispose() {
        raController.dispose();
        super.dispose();
      }
    
      @override
      void initState() {
        super.initState();
        if (widget.topBarHeight == null || widget.topBarHeight == 0) {
          widget.topBarHeight = 45.r;
        }
    
        raController = AnimationController(
            vsync: this, duration: const Duration(milliseconds: 200));
        _raAnimation = Tween(begin: .0, end: .5).animate(raController);
        _heAnimation = Tween(begin: .0, end: 0.1).animate(raController);
        Future.delayed(Duration.zero, () {
          _heAnimation =
              Tween(begin: .0, end: MediaQuery.of(context).size.height / 2.5)
                  .animate(raController)
                    ..addListener(() {
                      setState(() {
                        viewHegin = _heAnimation.value;
                      });
                      if (raController.isCompleted) {
                        if (widget.screenOpen != null) {
                          widget.screenOpen();
                        }
                      } else if (raController.isDismissed) {
                        if (widget.screenClose != null) {
                          widget.screenClose();
                        }
                      }
                    });
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Stack(
          children: [
            Positioned(
                child: Container(
              height: widget.topBarHeight,
              alignment: Alignment.center,
              color: Colors.white,
              child: InkWell(
                onTap: () {
                  if (raController.isCompleted) {
                    raController?.reverse();
                  } else {
                    raController?.forward();
                  }
                },
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    widget.titleWidget,
                    RotationTransition(
                      turns: _raAnimation,
                      child: Icon(
                        Icons.arrow_drop_down_sharp,
                        size: 30.r,
                      ),
                    )
                  ],
                ),
              ),
            )),
            Stack(
              children: [
                Align(
                    child: Container(
                  margin: EdgeInsets.only(top: widget.topBarHeight),
                  width: MediaQuery.of(context).size.width,
                  height: double.maxFinite,
                  child: Column(
                    children: [Expanded(child: widget.child)],
                  ),
                )),
                Align(
                    alignment: Alignment.topCenter,
                    child: Container(
                      height:
                          (viewHegin > 0) ? MediaQuery.of(context).size.height : 0,
                      decoration: BoxDecoration(
                          color: Colors.black26,
                          border: Border(
                              top: BorderSide(
                                  color: const Color.fromRGBO(230, 230, 230, 1),
                                  width: 0.4.r))),
                      margin: EdgeInsets.only(top: widget.topBarHeight),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          SizedBox(
                            height: viewHegin,
                            child: widget.screenListWidget,
                          )
                        ],
                      ),
                    ))
              ],
            )
          ],
        );
      }
    }
    
    class ScreenController {
      //打开
      void open() {
        raController?.forward();
      }
    
      //关闭
      void close() {
        raController?.reverse();
      }
    }
    

    使用组件

    import 'dart:ui';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:lnsl_credit_flutter/base/base_routes_widget.dart';
    import 'package:flutter_screenutil/flutter_screenutil.dart';
    import 'package:lnsl_credit_flutter/widget/screen_widget.dart';
    
    /// @description 作用:人员查询
    /// @date: 2021/8/16
    /// @author:卢融霜
    class PersonnelSearch extends StatefulWidget {
      const PersonnelSearch({Key key}) : super(key: key);
    
      @override
      _PersonnelSearchState createState() => _PersonnelSearchState();
    }
    
    class _PersonnelSearchState extends State<PersonnelSearch>{
      ScreenController controller = ScreenController();
      List<String> option = [
        "总监",
        "监理工程师",
        "监理员",
        "造价工程师",
        "质量检测员",
        "建造师",
        "安全工程师",
        "造价员",
        "五大员",
        "三类人员",
        "其他执业人员"
      ];
      String indexTitle = "总监";
      int selectIndex = 0;
      final ScrollController _scrollController = ScrollController();
    
      @override
      Widget build(BuildContext context) {
        return
          BaseRoutesWidget(
          isSearchBar: true,
          search: (String searchTitle) {},
          child:
          ScreenWidget(
              screenOpen: () {
                _scrollController.animateTo(selectIndex * 30.r,
                    duration: const Duration(microseconds: 1), curve: Curves.ease);
              },
              topBarHeight: 45.r,
              controller: controller,
              titleWidget: Text(
                indexTitle,
                style: TextStyle(
                    fontSize: 15.r, color: const Color.fromRGBO(51, 51, 51, 1)),
              ),
              screenListWidget: Container(
                color: Colors.white,
                child: ListView.builder(
                    controller: _scrollController,
                    itemCount: option.length,
                    itemBuilder: (BuildContext context, int index) {
                      return InkWell(
                        onTap: () {
                          setState(() {
                            indexTitle = option[index];
                            selectIndex = index;
                            controller.close();
                          });
                        },
                        child: Container(
                          decoration: BoxDecoration(
                              border: Border(
                                  bottom: BorderSide(
                                      color: const Color.fromRGBO(230, 230, 230, 1),
                                      width: 0.4.r))),
                          child: Text(
                            option[index],
                            style: TextStyle(
                                color: selectIndex == index
                                    ? const Color.fromRGBO(41, 121, 255, 1)
                                    : const Color.fromRGBO(51, 51, 51, 1),
                                fontSize: 14.r),
                          ),
                          padding: EdgeInsets.all(10.r),
                        ),
                      );
                    }),
              ),
              child: ListView.builder(
                  itemCount: 100,
                  itemBuilder: (BuildContext context, int index) {
                    return InkWell(
                      onTap: () {},
                      child: Container(
                        padding: EdgeInsets.all(10.r),
                        child: Text("1111111"),
                      ),
                    );
                  })),
        );
      }
    }
    

    涉及到的其他组件 BaseRoutesWidget

    import 'dart:ui';
    
    import 'package:flutter/material.dart';
    import 'package:flutter_screenutil/flutter_screenutil.dart';
    
    /// @description 作用:封装导航栏
    /// @date: 2021/7/14
    /// @author:卢融霜
    class BaseRoutesWidget extends StatefulWidget {
      //标题
      String title;
      double titleFontSize = 14.r;
      double toolBarHeight = 40.r;
      List<Widget> actions;
      Widget child;
      PreferredSizeWidget titleBottom;
      Color titleBgColor;
      bool showAppBar = true;
      bool isSearchBar = false;
      Function(String searchText) search;
      FloatingActionButton floatingActionButton;
    
      BaseRoutesWidget(
          {Key key,
          this.title,
          this.actions,
          this.child,
          this.titleBottom,
          this.titleBgColor,
          this.showAppBar = true,
          this.isSearchBar = false,
          this.search,
          this.floatingActionButton})
          : super(key: key);
    
      @override
      _BaseRoutesWidgetState createState() => _BaseRoutesWidgetState();
    }
    
    class _BaseRoutesWidgetState extends State<BaseRoutesWidget> {
      TextEditingController controller;
    
      @override
      void initState() {
        if (widget.isSearchBar) {
          controller = TextEditingController();
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          floatingActionButton: widget.floatingActionButton,
          resizeToAvoidBottomInset: false,
          appBar: widget.showAppBar
              ? (widget.isSearchBar
                  ? AppBar(
                      leadingWidth: 30.r,
                      toolbarHeight: widget.toolBarHeight,
                      centerTitle: true,
                      actions: widget.actions,
                      bottom: widget.titleBottom,
                      title: Row(
                        children: [
                          Expanded(
                              child: Container(
                            margin: EdgeInsets.only(right: 10.r),
                            decoration: BoxDecoration(
                                borderRadius:
                                    BorderRadius.all(Radius.circular(20.r)),
                                color: const Color.fromRGBO(242, 242, 242, 1)),
                            padding: EdgeInsets.only(
                                left: 10.r, right: 10.r, top: 4.r, bottom: 4.r),
                            child: TextField(
                              textInputAction: TextInputAction.search,
                              controller: controller,
                              style: TextStyle(fontSize: 13.r),
                              onEditingComplete: () {
                                widget.search(controller.text);
                              },
                              decoration: InputDecoration(
                                hintText: "请输入关键字",
                                hintStyle: TextStyle(fontSize: 13.r),
                                border: InputBorder.none,
                                isCollapsed: true,
                                icon: Icon(
                                  Icons.search_outlined,
                                  size: 18.r,
                                ),
                              ),
                            ),
                          )),
                          InkWell(
                            splashColor: Colors.transparent,
                            child: Text(
                              "搜索",
                              style: TextStyle(fontSize: 14.r),
                            ),
                            onTap: () {
                              widget.search(controller.text);
                            },
                          )
                        ],
                      ),
                    )
                  : AppBar(
                      toolbarHeight: widget.toolBarHeight,
                      centerTitle: true,
                      actions: widget.actions,
                      bottom: widget.titleBottom,
                      title: Text(widget.title,
                          style: TextStyle(fontSize: widget.titleFontSize)),
                    ))
              : null,
          body: widget.child,
        );
      }
    }
    

    相关文章

      网友评论

        本文标题:flutter 自定义单列下拉筛选组件

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