Flutter 24: 图解自定义 Dialog 对话框

  1. 云栖社区>
  2. 博客>
  3. 正文

Flutter 24: 图解自定义 Dialog 对话框

阿策~ 2018-11-30 20:14:56 浏览3917

      Dialog 在我们的日常开发中是必不可少的,Flutter 也提供了 AlertDialog / SimpleDialog 供我们选择,但是对于开发还是不足够的,小菜尝试了一下自定义对话框,简单记录一下。

1. 继承 Dialog

      Dialog 只是一个基础的 Widget 不会直接使用,小菜想自定义 Dialog 必须先继承 Dialog。此时需要重写 Widget build(BuildContext context) 方法。

2. 绘制 Dialog 样式

      小菜尝试做一个性别选择框,包括标题,图片和按钮等。

import 'package:flutter/material.dart';

class GenderChooseDialog extends Dialog {
  GenderChooseDialog({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Padding(
        padding: const EdgeInsets.all(12.0),
        child: new Material(
            type: MaterialType.transparency,
            child: new Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  new Container(
                      decoration: ShapeDecoration(
                          color: Color(0xFFFFFFFF),
                          shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.all(
                            Radius.circular(8.0),
                          ))),
                      margin: const EdgeInsets.all(12.0),
                      child: new Column(children: <Widget>[
                        new Padding(
                            padding: const EdgeInsets.fromLTRB(
                                10.0, 40.0, 10.0, 28.0),
                            child: Center(
                                child: new Text('请选择性别',
                                    style: new TextStyle(
                                      fontSize: 20.0,
                                    )))),
                        new Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            mainAxisSize: MainAxisSize.max,
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: <Widget>[
                              _genderChooseItemWid(1),
                              _genderChooseItemWid(2)
                            ])
                      ]))
                ])));
  }

  Widget _genderChooseItemWid(var gender) {
    return GestureDetector(
        child: Column(children: <Widget>[
      Image.asset(
          gender == 1
              ? 'images/icon_type_boy.png'
              : 'images/icon_type_girl.png',
          width: 135.0,
          height: 135.0),
      Padding(
          padding: EdgeInsets.fromLTRB(0.0, 22.0, 0.0, 40.0),
          child: Text(gender == 1 ? '我是男生' : '我是女生',
              style: TextStyle(
                  color: Color(gender == 1 ? 0xff4285f4 : 0xffff4444),
                  fontSize: 15.0)))
    ]));
  }
}

3. 内容传参

      小菜尽量把对话框做到通用性强一些,小菜测试仅把标题当参数传递,一个参数与多个参数是类似的。

class GenderChooseDialog extends Dialog {
  
  var title;
  
  GenderChooseDialog({
    Key key,
    @required this.title,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) { }
}

4. 添加点击事件

      每个对话框要有自己的点击事件,小菜准备把点击不同图片或文字时添加不同的点击事件。需要自定义 Function 方法。

class GenderChooseDialog extends Dialog {
  var title;
  Function onBoyChooseEvent;
  Function onGirlChooseEvent;

  GenderChooseDialog({
    Key key,
    @required this.title,
    @required this.onBoyChooseEvent,
    @required this.onGirlChooseEvent,
  }) : super(key: key);
  
  Widget _genderChooseItemWid(var gender) {
    return GestureDetector(
        onTap: gender == 1 ? this.onBoyChooseEvent : this.onGirlChooseEvent,
        child: Column(children: <Widget>[
          Image.asset(
              gender == 1 ? 'images/icon_type_boy.png'
                  : 'images/icon_type_girl.png',
              width: 135.0, height: 135.0),
          Padding(
              padding: EdgeInsets.fromLTRB(0.0, 22.0, 0.0, 40.0),
              child: Text(gender == 1 ? '我是男生' : '我是女生',
                  style: TextStyle(
                      color: Color(gender == 1 ? 0xff4285f4 : 0xffff4444),
                      fontSize: 15.0)))
        ]));
  }
}

// 方法调用
void _onItemPressed() {
  showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return GenderChooseDialog(
            title: '小哥哥小姐姐请选择',
            onBoyChooseEvent: () {
              Navigator.pop(context);
            },
            onGirlChooseEvent: () {
              Navigator.pop(context);
            });
      });
}

5. 注意事项

  1. Dialog 也是 Widget 默认是占满全屏,所以小菜自己绘制部分对话框,为了协调,借助 type: MaterialType.transparency 设置了对话框外半透明效果;
  2. 无论是传参还是设置点击事件,都需要在初始化中添加,很像 Android 中对 RecycleView 设置内容和点击事件等;
GenderChooseDialog({
  Key key,
  @required this.title,
  @required this.onBoyChooseEvent,
  @required this.onGirlChooseEvent,
}) : super(key: key);
  1. showDialog 方法中,barrierDismissible: false 属性代表点击顶部状态栏(显示电量/时间的横条位置)时是否关闭对话框,如果想点击半透明位置时关闭对话框,可以再添加一个点击事件即可。

      小菜目前的学习还仅限于基本的使用,如果又不对的地方还希望多多指出。