Flutter仿ios底部弹出选择视图

先放一张效果图
截屏2020-05-29 上午11.30.23.png

1、使用示例

var labelList = ['str1', 'str2', 'str3'];
showDialog(
      barrierDismissible: true,
      context: context,
      builder: (BuildContext context) {
        return CommonBottomSheet(
          list: labelList,
          onItemClickListener: (index) async {
            String label = labelList[index];
            String value = valueList[index];
            print('选择:$value  $label');
            var tfController = _tfControllerList[entity.itemId];
            tfController.text = label;
            // 修改实体里面的数据
            _editPhontEntityWithItemIdAddText(itemId, value);
            Navigator.pop(context);
          },
        );
      }
    );

2、视图源码

import 'dart:ui';
import 'package:flutter/material.dart';

// 仿ios底部弹出选择视图 ActionSheet  参考地址 https://www.jianshu.com/p/905232502f33

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 {
  OnItemClickListener onItemClickListener;
  var itemCount;
  double itemHeight = 50;
  var borderColor = Colors.white;
  double circular = 10;
  var textColor = Color(0xff007aff);

  @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是为了加分割线
    itemCount = (widget.list.length * 2 - 1);
    var height = ((widget.list.length+1) * (itemHeight+1) + 10).toDouble();
    var cancelContainer =
    SafeArea(bottom: true,child:
      GestureDetector(
        onTap: () {
          Navigator.pop(context);
        },
        child: Container(
          height: itemHeight,
          margin: EdgeInsets.only(left: 10, right: 10),
          decoration: BoxDecoration(
            color: Colors.white, // 底色
            borderRadius: BorderRadius.circular(circular),
          ),
          alignment: Alignment.center,
          child: Text("取消",
            style: TextStyle(
              fontFamily: 'Robot',
              fontWeight: FontWeight.normal,
              decoration: TextDecoration.none,
              color: textColor,
              fontSize: 18
            ),
          )
        ),
      )
    );
    var listview = ListView.builder(
        itemCount: itemCount,
        shrinkWrap: true,
        
        itemBuilder: (BuildContext context, int index) {
          return getItemContainer(context, index);
        });

    var totalContainer = Container(
      height: height + 10,
      width: deviceWidth * 0.98,
      // color: Colors.red,
      child: Column(
        children: [
          new Expanded(
            child: listview
          ),
          new Container(
            child: cancelContainer,
            margin: const EdgeInsets.only(top: 10, bottom: 10),
          )
        ],
      ),      
    );

    var stack = Stack(
      alignment: Alignment.bottomCenter,
      children: [
        Positioned(
          // bottom: 0,
          child: totalContainer,
        ),
      ],
    );
    return stack;
  }



  Widget getItemContainer(BuildContext context, int index) {
    if (widget.list == null) {
      return Container();
    }
    if (index.isOdd) {
      return Container(
        child: new Container(
          height: 1,
          margin: EdgeInsets.only(left: 10, right: 10),
          color: Color(0xffeeeeee),
        ),
      );
    }

    var borderRadius;
    var margin;
    var isFirst = false;
    var isLast = false;

    /// 只有一个元素
    if (widget.list.length == 1) {
      borderRadius = BorderRadius.circular(circular);
      margin = EdgeInsets.only(bottom: 10, left: 10, right: 10);
    } 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,);
      } else if (index == itemCount - 1) {
        isLast = true;
        /// 最后一个元素
        borderRadius = BorderRadius.only(bottomLeft: Radius.circular(circular), bottomRight: Radius.circular(circular));
        margin = EdgeInsets.only( left: 10, right: 10);
      } else {
        /// 其他位置元素
        margin = EdgeInsets.only(left: 10, right: 10);
      }
    }
    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: textColor,
          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(listIndex);
      }
    };
    var stack = Stack(
      alignment: Alignment.center,
      children: [itemContainer, contentText],
    );
    var getsture = GestureDetector(
      onTap: onTap2,
      child: isFirstOrLast ? stack : itemContainer,
    );
    return getsture;
  }
}

本文参考地址

你可能感兴趣的:(Flutter仿ios底部弹出选择视图)