平时在写app项目的过程,总会遇到一些"不正经"的美工, 搞出一些不伦不类的图,但做为工程师的我们,都懒得和他们计较, 来的图,就做呗, 老子偏不信邪,只要是UI都是实现!! 哈哈~~
美工给的效果图如下 (这个和material风格的Dialog 还是有不少差别吧,所以咱们需要自定义一个自己的风格的Dialog)
话不多说,上最终效果图.
总体来说,实现起来不算太难,不过在写代码的过程中,有遇到一些小坑,和大家分享一下.
对封装控件的期望
- 键盘弹出可以正常(不会出现被遮挡的问题)
- 点击事情传递出来,并且点击ok按钮可以得到TextField的文字内容
虽说这个效果图,用系统的Dialog是满足不了的,需要自定义对话框.但自定义总得有一个切入口.
我们来先看一下系统的弹出框的api及效果
showAlertDialog(BuildContext context) {
//设置按钮
Widget cancelButton = FlatButton(
child: Text("Cancel"),
onPressed: () {},
);
Widget continueButton = FlatButton(
child: Text("Continue"),
onPressed: () {},
);
//设置对话框
AlertDialog alert = AlertDialog(
title: Text("AlertDialog"),
content: Text(
"Would you like to continue learning how to use Flutter alerts?"),
actions: [
cancelButton,
continueButton,
],
);
//显示对话框
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
效果如下
从系统api中,可以看出content这个参数是传Widget,于是产生这个思路------>还是用系统的showDialog()方法把它弹出来, 给它也是返回系统的AlertDialog,但这个AlertDialog,我们可以去改变他的样式,给它传递的content是我们需求的内容;这样就可以变成我们想要的样子
代码比较简单,如下
先新建一个类,继承自系统的 AlertDialog, 有一个参数contentWidget,需要外界传入.
import 'package:flutter/material.dart';
class RenameDialog extends AlertDialog {
RenameDialog({Widget contentWidget})
: super(
content: contentWidget,
contentPadding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
side: BorderSide(color: Colors.blue, width: 3)),
);
}
contentWidget 我们也封装一下,方便项目使用
新一个类RenameDialogContent,里面就是具体怎么布局,怎么把事件传递出来等
import 'package:flutter/material.dart';
double btnHeight = 60;
double borderWidth = 2;
class RenameDialogContent extends StatefulWidget {
String title;
String cancelBtnTitle;
String okBtnTitle;
VoidCallback cancelBtnTap;
VoidCallback okBtnTap;
TextEditingController vc;
RenameDialogContent(
{@required this.title,
this.cancelBtnTitle = "Cancel",
this.okBtnTitle = "Ok",
this.cancelBtnTap,
this.okBtnTap,
this.vc});
@override
_RenameDialogContentState createState() =>
_RenameDialogContentState();
}
class _RenameDialogContentState extends State<RenameDialogContent> {
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: 20),
height: 200,
width: 10000,
alignment: Alignment.bottomCenter,
child: Column(
children: [
Container(
alignment: Alignment.center,
child: Text(
widget.title,
style: TextStyle(color: Colors.grey),
)),
Spacer(),
Padding(
padding: EdgeInsets.fromLTRB(30, 0, 30, 0),
child: TextField(
style: TextStyle(color: Colors.black87),
controller: widget.vc,
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
)),
),
),
Container(
// color: Colors.red,
height: btnHeight,
margin: EdgeInsets.fromLTRB(0, 30, 0, 0),
child: Column(
children: [
Container(
// 按钮上面的横线
width: double.infinity,
color: Colors.blue,
height: borderWidth,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
FlatButton(
onPressed: () {
widget.vc.text = "";
widget.cancelBtnTap();
Navigator.of(context).pop();
},
child: Text(
widget.cancelBtnTitle,
style: TextStyle(fontSize: 22, color: Colors.blue),
),
),
Container(
// 按钮中间的竖线
width: borderWidth,
color: Colors.blue,
height: btnHeight - borderWidth - borderWidth,
),
FlatButton(
onPressed: () {
widget.okBtnTap();
Navigator.of(context).pop();
widget.vc.text = "";
},
child: Text(
widget.okBtnTitle,
style: TextStyle(fontSize: 22, color: Colors.blue),
)),
],
),
],
),
)
],
));
}
}
最后使用的时候,就比较简单了
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return RenameDialog(
contentWidget: RenameDialogContent(
title: "请输入新的家庭名称",
okBtnTap: () {
print(
"输入框中的文字为:${_vc.text}",
);
},
vc: _vc,
cancelBtnTap: () {},
),
);
});
有一个坑点就是关于textField的属性设置,
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
)),
如果不设置的话,当键盘弹起的时候,看不到TextField相关的下划线或者边框之类的,这个也不知道是不是系统api的bug,这个不知道小伙伴们会不会遇到.
不设置的效果图如下
结尾
这里就当是提供一种思路吧,小伙伴如果有更好的实现思路或方法,请多指教,欢迎在评论区留言!今天的分享先写到这里吧,感觉有点帮助的话,请点赞,加关注喽~~