Flutter 19: 图解【分享页面】底部对话框

      小菜在学习 Flutter 过程中需要处理一个类似 AndroidPopupWindow 效果的分享弹框页。看似很简单的页面,里面却有很多值得尝试的地方。

      小菜测试时主要用 GridViewBottomSheet 来实现的,当然也可以不用 GridView,小菜简单介绍一下这两组 Widget

GridView

      GridView 我们都很熟悉了,是日常中最常用到的控件之一,小菜前段时间学习了一下 ListView 的基本用法,GridView 的用法基本相同,小菜不再多说,只提醒一个属性,用来设置 GridView item 基本属性。

const SliverGridDelegateWithFixedCrossAxisCount({
   @required this.crossAxisCount, // 每行 item 个数
   this.mainAxisSpacing = 0.0,    // 列间距,即 item 左右间距
   this.crossAxisSpacing = 0.0,   // 行间距,即 item 上下间距
   this.childAspectRatio = 1.0,   // item 宽高比,默认1:1
})
Tips:注意设置 item 个数与列间距的配合,如果太大可能会造成页面展示不全等异常情况。

BottomSheet

      BottomSheet 小菜理解为是从底部向上弹的工作表,主要分为两种:

  1. Persistent 式工作表:类似于一个全新的页面,完全展示 ScaffoldState.showBottomSheet
@override
Widget build(BuildContext context) {
return new Scaffold(
    appBar: new AppBar(
      title: new Text("分享页面"),
    ),
    body: new Center(
      child: new Builder(builder: (BuildContext context) {
        return new FlatButton(
            onPressed: () {
              showBottomSheet(
                  context: context,
                  builder: (BuildContext context) {
                    return _showNomalWid(context);
                  });
            },
            child: new Text("我要分享"),
            color: Colors.blue);
      }),
    ));
}

Widget _showNomalWid(BuildContext context) {
    return new Container(
//      height: 320.0,
//      color: Colors.greenAccent,
      child: new GridView.builder(
        gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 4, mainAxisSpacing: 5.0, childAspectRatio: 1.0),
        itemBuilder: (BuildContext context, int index) {
          return new Column(
            children: <Widget>[
              new Padding(
                padding: EdgeInsets.fromLTRB(0.0, 6.0, 0.0, 6.0),
                child: new Image.asset(
                  'images/${urlItems[index]}', width: 50.0, height: 50.0, fit: BoxFit.fill,
                ),
              ),
              new Text(nameItems[index])
            ],
          );
        },
        itemCount: nameItems.length,
      ),
    );
}

1.1 若用 showBottomSheet 方式开启工作表,同时内容 Widget 不限制宽高,效果为新打开一个页面,点击空白区不会消失,如图:

1.2 若此时设置内容 Widget 宽高,会发现依旧是重新打开一个页面,高度从底向上占据所设置高度,且点击空白区不会消失,如图:

  1. Modal 式工作表:是一个半透明的页面,默认占据屏幕一半 ScaffoldState.showModalBottomSheet
@override
Widget build(BuildContext context) {
return new Scaffold(
    appBar: new AppBar(
      title: new Text("分享页面"),
    ),
    body: new Center(
      child: new Builder(builder: (BuildContext context) {
        return new FlatButton(
            onPressed: () {
              showModalBottomSheet(
                  context: context,
                  builder: (BuildContext context) {
                    return _showNomalWid(context);
                  });
            },
            child: new Text("我要分享"),
            color: Colors.blue);
      }),
    ));
}

2.1 若用 showModalBottomSheet 方式开启工作表,同时内容 Widget 不限制宽高,效果为打开一个半透明页面,默认占据屏幕一半,点击空白区工作表消失,如图:

2.2 若此时设置内容 Widget 宽高,会发现依旧是打开一个半透明页面,高度从底向上占据所设置高度,且点击空白区会消失,如图:

2.3 若此时设置内容 Widget 数据量很多,效果如何呢,这就是小菜选择用 GridView 的原因,在现有宽高内进行可滑动操作即可,如图:

核心源码

      小菜稍稍修饰了一下页面效果,主要源码如下:

import 'package:flutter/material.dart';

class SharePopup extends StatelessWidget {
  List<String> nameItems = <String>[
    '微信', '朋友圈', 'QQ', 'QQ空间', '微博', 'FaceBook', '邮件', '链接'
  ];
  List<String> urlItems = <String>[
    'icon_wechat.png', 'icon_wechat_moments.png', 'icon_qq.png', 'icon_qzone.png',
    'icon_sina.png', 'icon_facebook.png', 'icon_email.png', 'icon_copylink.png'
  ];

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("分享页面"),
        ),
        body: new Center(
          child: new Builder(builder: (BuildContext context) {
            return new FlatButton(
                onPressed: () {
                  showModalBottomSheet(
                      context: context,
                      builder: (BuildContext context) {
                        return _shareWidget(context);
                      });
                },
                child: new Text("我要分享"),
                color: Colors.blue);
          }),
        ));
  }

  Widget _shareWidget(BuildContext context) {
    return new Container(
      height: 250.0,
      child: new Column(
        children: <Widget>[
          new Padding(
            padding: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
            child: new Container(
              height: 190.0,
              child: new GridView.builder(
                gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 4,
                    mainAxisSpacing: 5.0,
                    childAspectRatio: 1.0),
                itemBuilder: (BuildContext context, int index) {
                  return new Column(
                    children: <Widget>[
                      new Padding(
                        padding: EdgeInsets.fromLTRB(0.0, 6.0, 0.0, 6.0),
                        child: new Image.asset( 'images/${urlItems[index]}', width: 50.0, height: 50.0, fit: BoxFit.fill, ) ),
                      new Text(nameItems[index])
                    ],
                  );
                },
                itemCount: nameItems.length,
              ),
            ),
          ),
          new Container( height: 0.5, color: Colors.blueGrey, ),
          new Center( child: new Padding(
              padding: EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
              child: new Text( '取  消', style: new TextStyle(fontSize: 18.0, color: Colors.blueGrey), ) ), )
        ],
      ),
    );
  }
}

      小菜刚接触 Flutter 时间不长,还有很多不清楚和不理解的地方,如果有不对的地方还希望多多指教。

来源:阿策小和尚

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,351评论 0 17
  • 本文主要介绍了Flutter布局相关的内容,对相关知识点进行了梳理,并从实际例子触发,进一步讲解该如何去进行布局。...
    Q吹个大气球Q阅读 9,712评论 6 51
  • 本文对Flutter的29种布局控件进行了总结分类,讲解一些布局上的优化策略,以及面对具体的布局时,如何去选择控件...
    Q吹个大气球Q阅读 10,517评论 15 153
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,421评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,680评论 2 59