美文网首页Flutter 入坑记Flutter
flutter 类似iOS底部弹出框实现

flutter 类似iOS底部弹出框实现

作者: 雪纳瑞的哈士奇 | 来源:发表于2019-06-11 16:33 被阅读0次

    废话不多说 实现思路就是弹出框自定义

    调用方法

    showDialog(
                barrierDismissible: true,//是否点击空白区域关闭对话框,默认为true,可以关闭
                context: context,
                builder: (BuildContext context) {
                  var list = List();
                  list.add('相册');
                  list.add('相机');
                  list.add('保存图片');
                  return CommonBottomSheet(
                    list: list,
                    onItemClickListener: (index) async {
                      Navigator.pop(context);
                    },
                  );
                });
    

    实现方法

    import 'dart:ui';
    import 'package:flutter/material.dart';
    
    /// 底部弹出框
    class CommonBottomSheet extends StatefulWidget {
      CommonBottomSheet({Key key, this.list, this.onItemClickListener})
          : assert(list != null),
            super(key: key);
      final list;
      final OnItemClickListener onItemClickListener;
      @override
      _CommonBottomSheetState createState() => _CommonBottomSheetState();
    }
    typedef OnItemClickListener = void Function(int index);
    
    class _CommonBottomSheetState extends State<CommonBottomSheet> {
      OnItemClickListener onItemClickListener;
      var itemCount;
      double itemHeight = 44;
      var borderColor = Colors.white;
      double circular = 10;
      @override
      void initState() {
        super.initState();
        onItemClickListener = widget.onItemClickListener;
      }
      @override
      Widget build(BuildContext context) {
        Orientation orientation = MediaQuery.of(context).orientation;
        Size screenSize = MediaQuery.of(context).size;
    
        var deviceWidth = orientation == Orientation.portrait
            ? screenSize.width
            : screenSize.height;
        print('devide width');
        print(deviceWidth);
    
        /// *2-1是为了加分割线,最后还有一个cancel,所以加1
        itemCount = (widget.list.length * 2 - 1) + 1;
        var height = ((widget.list.length+1) * 48).toDouble();
        var cancelContainer = Container(
            height: itemHeight,
            margin: EdgeInsets.only(left: 10, right: 10),
            decoration: BoxDecoration(
              color: Colors.white, // 底色
              borderRadius: BorderRadius.circular(circular),
            ),
            child: Center(
              child: GestureDetector(
                onTap: () {
                  Navigator.pop(context);
                },
                child: Text("取消",
                  style: TextStyle(
                      fontFamily: 'Robot',
                      fontWeight: FontWeight.normal,
                      decoration: TextDecoration.none,
                      color: Color(0xff333333),
                      fontSize: 18),
                ),
              ),
            ));
        var listview = ListView.builder(
            itemCount: itemCount,
            itemBuilder: (BuildContext context, int index) {
              if (index == itemCount - 1) {
                return new Container(
                  child: cancelContainer,
                  margin: const EdgeInsets.only(top: 10),
                );
              }
              return getItemContainer(context, index);
            });
    
        var totalContainer = Container(
          child: listview,
          height: height,
          width: deviceWidth * 0.98,
        );
    
        var stack = Stack(
          alignment: Alignment.center,
          children: <Widget>[
            Positioned(
              bottom: 0,
              child: totalContainer,
            ),
          ],
        );
        return stack;
      }
    
    
    
      Widget getItemContainer(BuildContext context, int index) {
        if (widget.list == null) {
          return Container();
        }
        if (index.isOdd) {
          return Container(
            margin: EdgeInsets.symmetric(horizontal: 10),
            child: Divider(
              height: 0.5,
              color: borderColor,
            ),
          );
        }
    
        var borderRadius;
        var margin;
        var border;
        var borderAll = Border.all(color: borderColor, width: 0.5);
        var borderSide = BorderSide(color: borderColor, width: 0.5);
        var isFirst = false;
        var isLast = false;
    
        /// 只有一个元素
        if (widget.list.length == 1) {
          borderRadius = BorderRadius.circular(circular);
          margin = EdgeInsets.only(bottom: 10, left: 10, right: 10);
          border = borderAll;
        } else if (widget.list.length > 1) {
          /// 第一个元素
          if (index == 0) {
            isFirst = true;
            borderRadius = BorderRadius.only(topLeft: Radius.circular(circular), topRight: Radius.circular(circular));
            margin = EdgeInsets.only(left: 10, right: 10,);
            border = Border(top: borderSide, left: borderSide, right: borderSide);
          } else if (index == itemCount - 2) {
            isLast = true;
            /// 最后一个元素
            borderRadius = BorderRadius.only(bottomLeft: Radius.circular(circular), bottomRight: Radius.circular(circular));
            margin = EdgeInsets.only( left: 10, right: 10);
            border = Border(bottom: borderSide, left: borderSide, right: borderSide);
          } else {
            /// 其他位置元素
            margin = EdgeInsets.only(left: 10, right: 10);
            border = Border(left: borderSide, right: borderSide);
          }
        }
        var isFirstOrLast = isFirst || isLast;
        int listIndex = index ~/ 2;
        var text = widget.list[listIndex];
        var contentText = Text(
          text,
          style: TextStyle(
              fontWeight: FontWeight.normal,
              decoration: TextDecoration.none,
              color: Color(0xFF333333),
              fontSize: 18),
        );
    
        var center;
        if (!isFirstOrLast) {
          center = Center(
            child: contentText,
          );
        }
        var itemContainer = Container(
            height: itemHeight,
            margin: margin,
            decoration: BoxDecoration(
              color: Colors.white, // 底色
              borderRadius: borderRadius,
              border: border,
            ),
            child: center);
        var onTap2 = () {
          if (onItemClickListener != null) {
            onItemClickListener(index);
          }
        };
        var stack = Stack(
          alignment: Alignment.center,
          children: <Widget>[itemContainer, contentText],
        );
        var getsture = GestureDetector(
          onTap: onTap2,
          child: isFirstOrLast ? stack : itemContainer,
        );
        return getsture;
      }
    }
    

    效果图

    image.png

    根据https://www.jianshu.com/p/49e0d4f30edb来写 但是这老哥写的UI有些不适合我的要求

    相关文章

      网友评论

        本文标题:flutter 类似iOS底部弹出框实现

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