flutter -各类自定义弹窗(图片预览,输入框,键盘)以及如何阻止事件冒泡

       开局废话:由于公司app后期需要做混合开发,又担心h5的性能问题。于是迫不得已,只能两端齐搞,验证一些性能优化的问题。打开了一年前flutter正式发布时,蹭热度创建的现已布满藤蔓的仓库,微微颤抖的双手,开始敲击键盘。
       先说下普通的自定义弹窗吧,鉴于弹窗一般只起一些提示,跟选择功能,所以没必要去单独注册路由,继承showDialog父类就可以了,这个类的功能也就是往路由栈中push一条记录而已。

阻止事件冒泡
一般想让普通组件拥有点击事件可以用继承了Button类的组件包裹,也可以用GestureDetector进行包裹,但是这里面的事件响应跟js是类似的,子组件相同的事件会冒泡给父组件,所以弹窗的时候回用到。

GestureDetector(
    onTap: () {
        router.back(context); //退出弹出框
    },
    child: GestureDetector(
        onTap: () {
            return false; // 阻止事件冒泡
        }
    )
)

常用弹窗封装:
图片预览
图片预览用到的插件库为image_picker,详细请点进去看文档吧。

  1. 单图片:
showDialog<Null>(
      context: options.context, //BuildContext对象
      builder: (BuildContext context) {
        return GestureDetector(
            onTap: () {
                  router.back(context); //退出弹出框
            },
            child: PhotoView(
              imageProvider: NetworkImage(reslut.params[0]),
            ));
 });
  1. 多图片:
class ImageView extends StatelessWidget {
 final List<String> imgList; // 图片列表
 final int currentIndex;  // 当前预览图片索引
 ImageView(this.imgList, this.currentIndex) : assert(imgList != null);

 @override
 Widget build(BuildContext context) {
   return Container(
       child: PhotoViewGallery.builder(
     scrollPhysics: const BouncingScrollPhysics(),
     builder: (BuildContext context, int index) {
       return PhotoViewGalleryPageOptions(
         imageProvider: NetworkImage(imgList[index]),
         initialScale: PhotoViewComputedScale.contained,
       );
     },
     itemCount: imgList.length,
     pageController: PageController(initialPage: currentIndex),
   ));
 }
}

自定义键盘弹窗
刚开始再网上找了很久,大部分的不是很全,也存在一些问题,于是自己就手撸一个吧(ps: 由于用于给h5交互时调用,没有表单提交逻辑)。同样也是直接使用的showDialog。

showDialog<Null>(
          context: options.context, //BuildContext对象
          builder: (BuildContext context) {
            return GestureDetector(
              onTap: () {
                router.back(context); //退出弹出框
              },
              child: CommentDialog(
                callback: (value) {
                  // 释放promise
                  final dynamic r = {'code': 0, 'data': '$value'};
                  // 跟h5 js的交互逻辑
                  options.controller.evaluateJavascript(
                      "__app_native_callback__['${reslut.resolveName}']&&__app_native_callback__['${reslut.resolveName}'](${json.encode(r)})");
                  router.back(context);
                },
              ),
            );
          });

keyboard-popup.dart

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

// ignore: must_be_immutable
class CommentDialog extends Dialog {
  String text;
  String currentValue = '';
  dynamic callback;

  CommentDialog({Key key, this.text, this.callback}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Material(
      //创建透明层
      type: MaterialType.transparency, //透明类型
      child: GestureDetector(
          onTap: () {
            return false;
          },
          child: Stack(children: <Widget>[
            Positioned(
                left: 0,
                right: 0,
                bottom: MediaQuery.of(context).viewInsets.bottom > 0
                    ? MediaQuery.of(context).viewInsets.bottom
                    : 0,
                child: Container(
                    width: MediaQuery.of(context).size.width,
                    padding: EdgeInsets.all(16.0),
                    decoration: BoxDecoration(color: Colors.white),
                    child: Column(
                      children: <Widget>[
                        TextFormField(
                          decoration: InputDecoration(
                              hintText: "说点什么", border: InputBorder.none),
                          autofocus: true,
                          cursorColor: Color(0xFF00dcFF),
                          onChanged: (v) {
                            this.currentValue = v;
                          },
                        ),
                        Row(
                          children: <Widget>[
                            Container(
                                height: 30.0,
                                width: 32.0,
                                child: FlatButton.icon(
                                    onPressed: () {},
                                    padding: EdgeInsets.all(0.0),
                                    focusColor: Colors.white,
                                    hoverColor: Colors.white,
                                    highlightColor: Colors.white,
                                    splashColor: Colors.white,
                                    icon: Icon(
                                      Icons.image,
                                      color: Colors.grey,
                                    ),
                                    label: Text(''))),
                            Expanded(child: Text('')),
                            Container(
                                height: 30.0,
                                width: 40.0,
                                child: FlatButton(
                                  padding: EdgeInsets.all(0.0),
                                  focusColor: Colors.white,
                                  hoverColor: Colors.white,
                                  highlightColor: Colors.white,
                                  splashColor: Colors.white,
                                  child: Text(
                                    '发布',
                                    style: TextStyle(color: Color(0xFF00dcFF)),
                                  ),
                                  onPressed: () {
                                    if (currentValue == '') return;
                                    callback(currentValue);
                                  },
                                ))
                          ],
                        )
                      ],
                    )))
          ])),
    );
  }
}

项目介绍:主要包括帖子列表页,登录页,以及webview实现的帖子详情页,用于验证一些h5混合开发的问题,该有的功能也都有,但是不是很完善,有些一年前的代码已不再重构,所以参考的同学看看核心代码就好了,哈哈。h5项目用的vue + ssr技术,目前实践效果还可以,可以把flutter-cfsw这个项目拉下来,打包一个release包看下效果,只能说h5天下第一。
项目地址:https://github.com/Vitaminaq/flutter-cfsw
有什么有疑问的,欢迎评论区交流。
后续分享,敬请期待。

猜你喜欢

转载自blog.csdn.net/theoneEmperor/article/details/107612841