flutter|Flutter 浅析之 登录页

技术无止境,只怕不学习啊,Flutter 我们开始吧
先上图来看一下要实现的效果:
flutter|Flutter 浅析之 登录页
文章图片

页面结构
1.标题
2.手机号输入框
3.验证码输入框
4.获取验证码
5.60s倒计时
6.登录按钮
7.跳转到主页
下面直接上代码说明

/// (`InkWell`)可用时使用的字体样式。 final TextStyle _availableStyle = TextStyle( fontSize: 16.0, color: const Color(0xFF00CACE), ); /// (`InkWell`)不可用时使用的样式。 final TextStyle _unavailableStyle = TextStyle( fontSize: 16.0, color: const Color(0xFFCCCCCC), ); class LogInPage extends StatefulWidget { /// 倒计时的秒数,默认60秒。 final int countdown; const LogInPage({Key key, this.countdown: 60}) : super(key: key); @override State> createState() { // TODO: implement createState return LogInPageState(); } } //class LogInPageState extends State {String _verifyStr = '获取验证码'; /// 倒计时的计时器。 Timer _timer; /// 当前倒计时的秒数。 int _seconds; /// 按钮文案 String _buttonName = "登录"; /// 标题 String title = "测试"; /// 当前(`InkWell`)的字体样式。 TextStyle inkWellStyle = _availableStyle; TextEditingController _userController = new TextEditingController(); // 手机号 TextEditingController _passWordController = new TextEditingController(); // 验证码@override void initState() { super.initState(); _seconds = widget.countdown; }@override Widget build(BuildContext context) { // TODO: implement build return new Scaffold( body: new ListView( children: [ new Container( color: Colors.white, // 背景色 padding: EdgeInsets.only(top: 78, left: 8, right: 17), child: new Column( crossAxisAlignment: CrossAxisAlignment.center, // 对齐方式 children: [ _setTitle(title), // 设置标题 _setAccount(),//账号 _setCode(),//验证码 _raisedButton()//按钮 ], // 子集数组 ), ), ], // listview 子集列表 ), // 列表 ); //控制整个布局添加标题 策划顶部底部按钮等 }/// 标题 Widget _setTitle(String title) { return new Text( title, style: TextStyle( fontSize: 35, // 字体大小 color: Colors.black // 字体颜色 ), ); }/// 手机号输入框 Widget _setAccount() { return new Container( margin: EdgeInsets.only(top: 15), child: _createTextField(context, "请输入手机号码", 1, false, _userController), ); } ///// 验证码输入框 Widget _setCode() { return new Stack( children: [ _createTextField(context, "短信验证码", 2, true, _passWordController), new Container( height: 54.0, child: new Align( alignment: FractionalOffset.centerRight, // 右侧对齐 child: GestureDetector( // 手势交互 onTap: (){ setState(() { String user = _userController.text.toString(); if (user.isEmpty|!RegularMatch.isChinaPhoneLegal(user)) { Fluttertoast.showToast( msg: "请输入正确的电话号码!", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.TOP, fontSize: 12, timeInSecForIos: 1); return; } _startTimer(); // 倒计时 }); }, child: new Visibility( child: new Text( _verifyStr, style: TextStyle( color: Colors.blue, fontSize: 16, ), )), ), ), // 设置 布局的高宽适应 ), ], // 子集列表 ); // 叠加布局 } ///// 登录按钮 Widget _raisedButton() { return new Container( width: double.infinity, height: 45, margin: EdgeInsets.only(left: 19, top: 35), child: new RaisedButton( onPressed: () { // 点击事件 String user = _userController.text; String pw = _passWordController.text; //RegExp exp = RegExp( //r'^((13[0-9])|(14[0-9])|(15[0-9])|(16[0-9])|(17[0-9])|(18[0-9])|(19[0-9]))\d{8}$'); // 手机号校验 if (null == user || user.length < 11 || !RegularMatch.isChinaPhoneLegal(user)) { Fluttertoast.showToast( msg: "请输入正确的电话号码!", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.TOP); return; } // 验证码校验 if (null == pw || pw.length < 4) { Fluttertoast.showToast( msg: "请输入正确的验证码!", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.TOP); return; } // 路由页面跳转 Navigator.pushNamed( context, '/Home'); //使用的是“命名导航路由”,具体去哪个界面,看main.dart 对应routeName('/Home')的界面 }, color: Color(0xff017EFF), // 按钮颜色 shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(5)), ), // 弧度 child: new Text( _buttonName, style: TextStyle( color: Colors.white, fontSize: 17, ), ), ), ); } ///// 输入框 Widget _createTextField(BuildContext context, String hintText, int type, autovalidate, TextEditingController _controller) { return new Theme( data: new ThemeData(primaryColor: Colors.red, hintColor: Color(0xffa8afc3)), child: new ConstrainedBox( constraints: BoxConstraints( minHeight: 54, // 设置高度 ), child: new Padding( padding: EdgeInsets.only(top: 19, left: 15), child: new TextFormField( obscureText: false, // 是否是密码 controller: _controller, // 设置输入框 keyboardType: TextInputType.number, // 唤起键盘输入方式 inputFormatters: [ LengthLimitingTextInputFormatter(1 == type ? 11 : 4) ], // 输入长度 autovalidate: autovalidate, // 自我验证 validator: (value) { return value.length < 4 && value.length > 0 ? "验证码长度不够4位" : null; }, // 输入的长度 decoration: new InputDecoration( contentPadding: EdgeInsets.all(10.0), hintText: hintText, // 提示文案 hintStyle: TextStyle( color: Color(0xffa8afc3), // 字体颜色 ), // 提示文案的样式设置 focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.blue)), // 边框颜色 border: UnderlineInputBorder(), // 设置装饰形状 ), ), ), ), ); } ///// 启动倒计时的计时器。 void _startTimer() {if(_timer!=null){ if(_timer.isActive){ return; } } _timer = Timer.periodic(Duration(seconds: 1), (timer) { if (_seconds == 0) { _cancelTimer(); _seconds = widget.countdown; inkWellStyle = _availableStyle; setState(() {}); return; } _seconds--; _verifyStr = '${_seconds}s'; setState(() {}); if (_seconds == 0) { _verifyStr = '重新发送'; } }); } // /// 取消倒计时的计时器。 void _cancelTimer() { // 计时器(`Timer`)组件的取消(`cancel`)方法,取消计时器。 _timer?.cancel(); }} //

手机号校验
class RegularMatch{static const String PHONE_REG = r'^((13[0-9])|(14[0-9])|(15[0-9])|(16[0-9])|(17[0-9])|(18[0-9])|(19[0-9]))\d{8}$'; ///校验用户手机号码 static bool isChinaPhoneLegal(String str) { return new RegExp(PHONE_REG).hasMatch(str); } }

flutter|Flutter 浅析之 登录页
文章图片

主页面
void main() { runApp(MyApp()); }class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), routes: { '/': (BuildContext context) => new LogInPage(), '/Home': (BuildContext context) => new MyHomePage(title: '主页',), }, //home: LogInPage(), ); } }

MyHomePage中什么界面就自己写吧
flutter|Flutter 浅析之 登录页
文章图片

【flutter|Flutter 浅析之 登录页】源码下载

    推荐阅读