小菜前两天花了很久才搭建了一个最简单的【登录】页面,但依然还有很多需要优化的地方,小菜又花了很久的时间尝试做了一点点的优化,仅针对优化的部分简单整理一下。
优化一:解决 OverFlowed 遮挡文本框问题
-
小菜刚开始在编辑内容块 content 时,以为涉及的 widget 元素不多,所占不会超过屏幕,所以根 widget 使用的是 body: new Container(),但是在点击文本框 TextField 时,弹出的键盘会挡住部分 widget,并提示 Bottom OverFlowed By 85 pixels,如图:
-
小菜查了一下官网,调整方式很简单,将根 widget 调整为 body: new ListView(),Flutter 中的 ListView 不仅代表列表 (ListView/RecycleView),还可以代表一个可滑动布局 (ScrollView),如图:
优化二:文本框 TextField 中尾部添加【清空数据】图标
方式一:使用层布局 Stack,在输入文本框 TextField 上一层添加一个【清空数据】图标;
new Padding(
padding: new EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 15.0),
child: new Stack(
alignment: new Alignment(1.0, 1.0),
//statck
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Padding(
padding:
new EdgeInsets.fromLTRB(0.0, 0.0, 5.0, 0.0),
child: new Image.asset(
'images/icon_username.png',
width: 40.0,
height: 40.0,
fit: BoxFit.fill,
),
),
new Expanded(
child: new TextField(
controller: _phonecontroller,
keyboardType: TextInputType.phone,
decoration: new InputDecoration(
hintText: '请输入用户名',
),
),
),
]),
new IconButton(
icon: new Icon(Icons.clear, color: Colors.black45),
onPressed: () {
_phonecontroller.clear();
},
),
],
),
),
方式二:使用文本框 TextField 自带的属性【后缀图标 suffixIcon】,文本框 TextField 提供了很多便利的属性,例如:【前缀图标 prefixIcon】【文本框前图标 icon】;
new Expanded(
child: new TextField(
controller: _pwdcontroller,
decoration: new InputDecoration(
hintText: '请输入密码',
suffixIcon: new IconButton(
icon: new Icon(Icons.clear,
color: Colors.black45),
onPressed: () {
_pwdcontroller.clear();
},
),
),
obscureText: true,
),
),
Tips: 小菜更倾向于方法二,方法一采用的是层布局,如果超过图标所在位置,若不做特别处理,之后输入的内容会被图标挡住,而且相较于方法二使用了更多的 widget。小菜为了测试,在【输入用户名】模块采用了方法一,【输入密码】模块采用了方法二。
优化三:调整键盘弹出样式
设置文本框 TextField 中 keyboardType: TextInputType.phone, Flutter 提供了多种弹出键盘的方式:text/datetime/phone/url/number/multiline/emailAddress...
键盘样式.png phone优化四:根据输入文本框添加【温馨提示】对话框
Flutter 提供了创建和显示弹出对话框的功能,如:showDialog/showMenu/showModalBottomSheet 等,小菜采用的是对话框方式,可设置标题/内容/按钮等各属性。
Tips: 对话框中 barrierDismissible: false, 属性,若为false,点击对话框周围,对话框不会关闭;若为true,点击对话框周围,对话框自动关闭。
相关注意
Flutter 提供了很多便利的小图标,使用起来非常方便,小菜但就一个小【×】找到了好几个类似的图,希望可以多多尝试,体验一下。如图:
主要源码
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: '轻签到',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: '极速登录'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _phoneState, _pwdState = false;
String _checkStr;
TextEditingController _phonecontroller = new TextEditingController();
TextEditingController _pwdcontroller = new TextEditingController();
void _checkPhone() {
if (_phonecontroller.text.isNotEmpty &&
_phonecontroller.text.trim().length == 11) {
_phoneState = true;
} else {
_phoneState = false;
}
}
void _checkPwd() {
if (_pwdcontroller.text.isNotEmpty &&
_pwdcontroller.text.trim().length >= 6 &&
_pwdcontroller.text.trim().length <= 10) {
_pwdState = true;
} else {
_pwdState = false;
}
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: '轻签到',
home: new Scaffold(
appBar: new AppBar(
title: new Text('极速登录'),
),
body: new ListView(
children: <Widget>[
new Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Padding(
padding: new EdgeInsets.all(30.0),
child: new Image.asset(
'images/ic_launcher.png',
scale: 1.2,
)),
new Padding(
padding: new EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 15.0),
child: new Stack(
alignment: new Alignment(1.0, 1.0),
//statck
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Padding(
padding:
new EdgeInsets.fromLTRB(0.0, 0.0, 5.0, 0.0),
child: new Image.asset(
'images/icon_username.png',
width: 40.0,
height: 40.0,
fit: BoxFit.fill,
),
),
new Expanded(
child: new TextField(
controller: _phonecontroller,
keyboardType: TextInputType.phone,
decoration: new InputDecoration(
hintText: '请输入用户名',
),
),
),
]),
new IconButton(
icon: new Icon(Icons.clear, color: Colors.black45),
onPressed: () {
_phonecontroller.clear();
},
),
],
),
),
new Padding(
padding: new EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 40.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Padding(
padding: new EdgeInsets.fromLTRB(0.0, 0.0, 5.0, 0.0),
child: new Image.asset(
'images/icon_password.png',
width: 40.0,
height: 40.0,
fit: BoxFit.fill,
),
),
new Expanded(
child: new TextField(
controller: _pwdcontroller,
decoration: new InputDecoration(
hintText: '请输入密码',
suffixIcon: new IconButton(
icon: new Icon(Icons.clear,
color: Colors.black45),
onPressed: () {
_pwdcontroller.clear();
},
),
),
obscureText: true,
),
),
]),
),
new Container(
width: 340.0,
child: new Card(
color: Colors.blue,
elevation: 16.0,
child: new FlatButton(
child: new Padding(
padding: new EdgeInsets.all(10.0),
child: new Text(
'极速登录',
style: new TextStyle(
color: Colors.white, fontSize: 16.0),
),
),
onPressed: () {
_checkPhone();
_checkPwd();
if (_phoneState && _pwdState) {
_checkStr = '页面跳转下期见咯!';
} else {
if (!_phoneState) {
_checkStr = '请输入11位手机号!';
} else if (!_pwdState) {
_checkStr = '请输入6-10位密码!';
}
}
print(_checkStr);
showDialog<Null>(
context: context,
barrierDismissible: false,
child: new AlertDialog(
title: new Text(
'温馨提示',
style: new TextStyle(
color: Colors.black54,
fontSize: 18.0,
),
),
content: new Text(_checkStr),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: new Text('确定')),
],
),
);
},
),
),
),
],
),
],
),
),
);
}
}
小菜也是刚接触 Flutter,还有很多不清楚和不理解的地方,如果又不对的地方还希望多多指出。以下是小菜公众号,欢迎闲来吐槽~
网友评论