flutter 類似iOS底部彈出框?qū)崿F(xiàn)

廢話不多說 實現(xiàn)思路就是彈出框自定義

調(diào)用方法

showDialog(
            barrierDismissible: true,//是否點擊空白區(qū)域關(guān)閉對話框,默認(rèn)為true叛甫,可以關(guān)閉
            context: context,
            builder: (BuildContext context) {
              var list = List();
              list.add('相冊');
              list.add('相機(jī)');
              list.add('保存圖片');
              return CommonBottomSheet(
                list: list,
                onItemClickListener: (index) async {
                  Navigator.pop(context);
                },
              );
            });

實現(xiàn)方法

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

根據(jù)http://www.reibang.com/p/49e0d4f30edb來寫 但是這老哥寫的UI有些不適合我的要求

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末审姓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子旨椒,更是在濱河造成了極大的恐慌晓褪,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件综慎,死亡現(xiàn)場離奇詭異涣仿,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)示惊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門好港,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人米罚,你說我怎么就攤上這事钧汹。” “怎么了录择?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵拔莱,是天一觀的道長碗降。 經(jīng)常有香客問我,道長塘秦,這世上最難降的妖魔是什么讼渊? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮尊剔,結(jié)果婚禮上爪幻,老公的妹妹穿的比我還像新娘。我一直安慰自己须误,他們只是感情好挨稿,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著霹期,像睡著了一般叶组。 火紅的嫁衣襯著肌膚如雪拯田。 梳的紋絲不亂的頭發(fā)上历造,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機(jī)與錄音船庇,去河邊找鬼吭产。 笑死,一個胖子當(dāng)著我的面吹牛鸭轮,可吹牛的內(nèi)容都是我干的臣淤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼窃爷,長吁一口氣:“原來是場噩夢啊……” “哼邑蒋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起按厘,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤医吊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后逮京,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卿堂,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年懒棉,在試婚紗的時候發(fā)現(xiàn)自己被綠了草描。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡策严,死狀恐怖穗慕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情妻导,我是刑警寧澤揍诽,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布诀蓉,位于F島的核電站,受9級特大地震影響暑脆,放射性物質(zhì)發(fā)生泄漏渠啤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一添吗、第九天 我趴在偏房一處隱蔽的房頂上張望沥曹。 院中可真熱鬧,春花似錦碟联、人聲如沸妓美。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽壶栋。三九已至,卻和暖如春普监,著一層夾襖步出監(jiān)牢的瞬間贵试,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工凯正, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留毙玻,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓廊散,卻偏偏與公主長得像桑滩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子允睹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355