flutter 登錄界面和表單校驗json
先上Gif效果圖bash
可能在掘金是Gif不會動,你們請右擊,在新標籤打開,或者點擊下面的【點擊打開gif】async
點擊打開gifide
先畫UI,而後寫校驗,如今咱們UI畫好了,以前的佈局說過了,若是不會能夠看前面的文章。函數
登錄的時候,用戶要輸入手機號之類的,這時候咱們要反饋提示給用戶,這裏flutter自帶的Form表單就已經作到了佈局
首先使用 Form組件函數(準確說叫widget),而後寫一個key,由於咱們等下要操做它,而後寫child,裏面就是TextFormField組件。ui
TextFormField有 validator
校驗函數,接收一個入參就是value,而後return null的時候就是正常的,錯誤的時候return String就能夠了。this
看下完整代碼spa
你們, 看的時候點個贊,若是對你有幫助的話。 點贊對我也沒啥好處,不過但願感覺你們暖暖的愛意~~debug
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:cjyy/utils/http.dart';
import 'package:cjyy/utils/toast.dart';
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
class LoginPage extends StatefulWidget {
static String tag = 'login-page';
@override
_LoginPageState createState() => new _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
Jverify jverify = new Jverify();
List<JVCustomWidget>widgetList = [];
JVUIConfig uiConfig = JVUIConfig();
GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
String _phone = '';
String _pw = '';
// 密碼顯示、隱藏
bool _isObscure = true;
Color _eyeColor = Colors.grey;
final _phone_controller = TextEditingController();
@override
void initState() {
// SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle(statusBarColor: Colors.transparent,statusBarIconBrightness:Brightness.dark);
// SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
_phone_controller.addListener((){
// debugPrint('input:${_phone_controller.text}');
});
super.initState();
}
@override
void dispose() {
_phone_controller.dispose();
super.dispose();
}
void _onSubmit() async{
final form = _formKey.currentState;
if(form.validate()) {
form.save();
// showDialog(context: context, builder: (ctx)=> new AlertDialog(
// content: new Text('phone: $_phone , pw: $_pw '),
// ));
String response_content = await HTTP('get:phone_pw_login', {
"phone": _phone,
"pass": _pw
});
Map<String, Object> response_map = jsonDecode(response_content);
if(response_map['code'] != 200){
print('登陸異常');
Toast.show('登陸異常', context);
return;
}
Map<String, Object> data = response_map['data'];
final prefs = await SharedPreferences.getInstance();
final setTokenResult = await prefs.setString('user_token', data['token']);
await prefs.setInt('user_phone', data['phone']);
await prefs.setString('user_name', data['name']);
if(setTokenResult){
debugPrint('保存登陸token成功');
Navigator.of(context).pushReplacementNamed('/');
}else{
debugPrint('error, 保存登陸token失敗');
}
}
}
onRigister() async{
final result = await Navigator.pushNamed(context, '/rigister');
print(result);
_phone_controller.text = result;
}
@override
Widget build(BuildContext context) {
SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle(
statusBarColor: Colors.transparent,statusBarIconBrightness:Brightness.dark,
);
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
final logo = new Hero(
tag: 'hero',
child: new CircleAvatar(
backgroundColor: Colors.transparent,
radius: 48.0,
child: new ClipRRect(
child: new SizedBox(
width: 120,
height: 120,
child: new Image.asset('images/cjyy_320.jpg', fit: BoxFit.cover),
),
borderRadius: BorderRadius.all(Radius.circular(15))
),
),
);
final phone = new TextFormField(
keyboardType: TextInputType.number,
autofocus: false,
// initialValue: '',
controller: _phone_controller,
onSaved: (val)=> this._phone = val,
validator: (value){
if(value.length != 11){
return '手機號不存在哦~';
}else{
return null;
}
},
decoration: new InputDecoration(
hintText: '手機號',
contentPadding: new EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: new OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
)
)
);
final password = new TextFormField(
autofocus: false,
initialValue: '',
onSaved: (val)=> this._pw = val,
obscureText: _isObscure,
validator: (value){
if(value.length < 6 || value.length > 16){
return '密碼在6-16位數之間哦';
}else{
return null;
}
},
decoration: new InputDecoration(
hintText: '密碼',
contentPadding: new EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: new OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0)
),
suffixIcon: IconButton(
icon: Icon(
Icons.remove_red_eye,
color: _eyeColor,
),
onPressed: () {
setState(() {
_isObscure = !_isObscure;
_eyeColor = _isObscure
? Colors.grey
: Theme.of(context).iconTheme.color;
});
}),
),
);
final loginButton = new Padding(
padding: new EdgeInsets.symmetric(vertical: 16.0),
child: Container(
width: double.infinity,
height: 45,
margin: EdgeInsets.only(top: 50,left: 10,right: 10),
child: RaisedButton(
onPressed: () {
debugPrint('QAQ');
_onSubmit();
},
shape: StadiumBorder(side: BorderSide.none),
color: Color(0xff44c5fe),
child: Text(
'登陸',
style: TextStyle(color: Colors.white,fontSize: 15),
),
),
),
);
final forgetLabel = new FlatButton(
onPressed: (){
print('等死吧');
},
child: new Text('忘記密碼? ',style: new TextStyle(color: Colors.black54),),
);
final registerLabel = new FlatButton(
onPressed: onRigister,
child: new Text('註冊 ',style: new TextStyle(color: Colors.black54),),
);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.dark,
child: new Scaffold(
backgroundColor: Colors.white,
body: new Center(
child: new Center(
child: new ListView(
shrinkWrap: true,
padding: new EdgeInsets.only(left: 24.0,right: 24.0),
children: <Widget>[
new Form(
key: _formKey,
child: new Column(
children: <Widget>[
logo,
SizedBox(height: 48.0),
phone,
SizedBox(height: 8.0,),
password,
SizedBox(height: 24.0,),
loginButton,
// forgetLabel,
registerLabel,
],
),
)
],
),
),
),
)
);
}
}
複製代碼
--END--