继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

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

老菜和尚
关注TA
已关注
手记 185
粉丝 165
获赞 165

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

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

webp

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

@overrideWidget 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 不限制宽高,效果为新打开一个页面,点击空白区不会消失,如图:

webp

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

webp

  1. Modal 式工作表:是一个半透明的页面,默认占据屏幕一半 ScaffoldState.showModalBottomSheet

@overrideWidget 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 不限制宽高,效果为打开一个半透明页面,默认占据屏幕一半,点击空白区工作表消失,如图:

webp

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

webp

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

webp

核心源码

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

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), ) ), )
        ],
      ),
    );
  }
}



作者:阿策神奇


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP