Flutter UIflutter

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

2021-08-16  本文已影响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,
    );
  }
}
上一篇下一篇

猜你喜欢

热点阅读