开局废话:由于公司app后期需要做混合开发,又担心h5的性能问题。于是迫不得已,只能两端齐搞,验证一些性能优化的问题。打开了一年前flutter正式发布时,蹭热度创建的现已布满藤蔓的仓库,微微颤抖的双手,开始敲击键盘。
先说下普通的自定义弹窗吧,鉴于弹窗一般只起一些提示,跟选择功能,所以没必要去单独注册路由,继承showDialog父类就可以了,这个类的功能也就是往路由栈中push一条记录而已。
阻止事件冒泡
一般想让普通组件拥有点击事件可以用继承了Button类的组件包裹,也可以用GestureDetector进行包裹,但是这里面的事件响应跟js是类似的,子组件相同的事件会冒泡给父组件,所以弹窗的时候回用到。
GestureDetector(
onTap: () {
router.back(context); //退出弹出框
},
child: GestureDetector(
onTap: () {
return false; // 阻止事件冒泡
}
)
)
常用弹窗封装:
图片预览
图片预览用到的插件库为image_picker,详细请点进去看文档吧。
showDialog<Null>(
context: options.context, //BuildContext对象
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
router.back(context); //退出弹出框
},
child: PhotoView(
imageProvider: NetworkImage(reslut.params[0]),
));
});
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
有什么有疑问的,欢迎评论区交流。
后续分享,敬请期待。