- 3.6、实现圆角图片
- 方式一:ClipRRect
ClipRRect用于实现圆角效果,可以设置圆角的大小。
实现代码如下,非常简单:
Center( child: ClipRRect( borderRadius: BorderRadius.circular(10), child: Image.network( "https://tva1.sinaimg.cn/large/006y8mN6gy1g7aa03bmfpj3069069mx8.jpg", width: 200, height: 200, ), ), );
- 方式二:Container+BoxDecoration
class HomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: Container( width: 200, height: 200, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), image: DecorationImage( image: NetworkImage("https://tva1.sinaimg.cn/large/006y8mN6gy1g7aa03bmfpj3069069mx8.jpg"), ) ), ), ); } }
四、TextField
- 4.1、TextField的介绍TextField用于接收用户的文本输入,它提供了非常多的属性,我们来看一下源码:但是我们没必要一个个去学习,很多时候用到某个功能时去查看是否包含某个属性即可
const TextField({ Key key, this.controller, this.focusNode, this.decoration = const InputDecoration(), TextInputType keyboardType, this.textInputAction, this.textCapitalization = TextCapitalization.none, this.style, this.strutStyle, this.textAlign = TextAlign.start, this.textAlignVertical, this.textDirection, this.readOnly = false, ToolbarOptions toolbarOptions, this.showCursor, this.autofocus = false, this.obscureText = false, this.autocorrect = true, this.maxLines = 1, this.minLines, this.expands = false, this.maxLength, this.maxLengthEnforced = true, this.onChanged, this.onEditingComplete, this.onSubmitted, this.inputFormatters, this.enabled, this.cursorWidth = 2.0, this.cursorRadius, this.cursorColor, this.keyboardAppearance, this.scrollPadding = const EdgeInsets.all(20.0), this.dragStartBehavior = DragStartBehavior.start, this.enableInteractiveSelection = true, this.onTap, this.buildCounter, this.scrollController, this.scrollPhysics, })
- 几个比较常见的属性:一些属性比较简单:keyboardType键盘的类型,style设置样式,textAlign文本对齐方式,maxLength最大显示行数等等;
- decoration:用于设置输入框相关的样式
- icon:设置左边显示的图标
- labelText:在输入框上面显示一个提示的文本
- hintText:显示提示的占位文字
- border:输入框的边框,默认底部有一个边框,可以通过InputBorder.none删除掉
- filled:是否填充输入框,默认为false
- fillColor:输入框填充的颜色
- controller:TextEditingController()
- onChanged:监听输入框内容的改变,传入一个回调函数
- onSubmitted:点击键盘中右下角的down时,会回调的一个函数
- 4.2、TextField 的样式以及监听
TextField( decoration: InputDecoration( labelText: "username", icon: Icon(Icons.favorite), hintText: "请输入用户名", // OutlineInputBorder() // InputBorder.none border: OutlineInputBorder() ), onChanged: (value) { print("输入的内容:$value"); }, onSubmitted: (value) { print("提交的值:$value"); }, // 输入不可见 obscureText: true, )
- 4.3、TextField的controller
我们可以给TextField添加一个控制器(Controller),可以使用它设置文本的初始值,也可以使用它来监听文本的改变;
事实上,如果我们没有为TextField提供一个Controller,那么会Flutter会默认创建一个TextEditingController的,这个结论可以通过阅读源码得到:
@override void initState() { super.initState(); // ...其他代码 if (widget.controller == null) _controller = TextEditingController(); }
- 我们也可以自己来创建一个Controller控制一些内容:
class _TextFieldDemoState extends State<TextFieldDemo> { final textEditingController = TextEditingController(); @override void initState() { super.initState(); // 1.设置默认值 textEditingController.text = "Hello World"; // 2.监听文本框 textEditingController.addListener(() { print("textEditingController:${textEditingController.text}"); }); } // ...省略build方法 }
五. Form表单的使用
在我们开发注册、登录页面时,通常会有多个表单需要同时获取内容或者进行一些验证,如果对每一个TextField都分别进行验证,是一件比较麻烦的事情。
做过前端的开发知道,我们可以将多个input标签放在一个form里面,Flutter也借鉴了这样的思想:我们可以通过Form对输入框进行分组,统一进行一些操作。
- 5.1、Form 表单的基本使用
Form表单也是一个Widget,可以在里面放入我们的输入框。
但是Form表单中输入框必须是FormField类型的
我们查看刚刚学过的TextField是继承自StatefulWidget,并不是一个FormField类型;
我们可以使用TextFormField,它的使用类似于TextField,并且是继承自FormField的;
我们通过Form的包裹,来实现一个注册的页面:
class JKHomeContent extends StatefulWidget { @override _JKHomeContentState createState() => _JKHomeContentState(); } class _JKHomeContentState extends State<JKHomeContent> { @override Widget build(BuildContext context) { return Form( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextFormField( decoration: InputDecoration( icon: Icon(Icons.people), labelText: '用户名或者手机号' ), ), TextFormField( obscureText: true, decoration: InputDecoration( icon: Icon(Icons.lock), labelText: "密码" ), ), SizedBox( height: 20, ), Container( // double.infinit width: 200, height: 44, child: RaisedButton( color: Colors.green, child: Text("注 册", style: TextStyle(fontSize: 20, color: Colors.white),), onPressed: () { print('点击了 注册'); }, ), ) ], ) ); } }
- 5.2、保存和获取表单数据有了表单后,我们需要在点击注册时,可以同时获取和保存表单中的数据,怎么可以做到呢?
- 1、需要监听注册按钮的点击,在之前我们已经监听的onPressed传入的回调中来做即可。(当然,如果嵌套太多,我们待会儿可以将它抽取到一个单独的方法中)
- 2、监听到按钮点击时,同时获取用户名和密码的表单信息。
- 如何同时获取
用户名
和密码
的表单信息?
- 如果我们调用
Form的State对象
的save方法,就会调用Form中放入的TextFormField的onSave回调:
TextFormField( decoration: InputDecoration( icon: Icon(Icons.people), labelText: "用户名或手机号" ), onSaved: (value) { print("用户名:$value"); }, ),
- 但是,我们有没有办法可以在点击按钮时,拿到
Form对象
来调用它的save方法呢?
知识点:在Flutter如何可以获取一个通过一个引用获取一个StatefulWidget的State对象:通过绑定一个GlobalKey即可
。
class JKHomeContent extends StatefulWidget { @override _JKHomeContentState createState() => _JKHomeContentState(); } class _JKHomeContentState extends State<JKHomeContent> { final registerFormKey = GlobalKey<FormState>(); String username, password; void registerForm() { registerFormKey.currentState.save(); print("username:$username password:$password"); } @override Widget build(BuildContext context) { return Form( key: registerFormKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextFormField( decoration: InputDecoration( icon: Icon(Icons.people), labelText: '用户名或者手机号' ), onSaved: (value) { username = value; }, ), TextFormField( obscureText: true, decoration: InputDecoration( icon: Icon(Icons.lock), labelText: "密码" ), onSaved: (value) { password = value; }, ), SizedBox( height: 20, ), Container( // double.infinit width: 200, height: 44, child: RaisedButton( color: Colors.green, child: Text("注 册", style: TextStyle(fontSize: 20, color: Colors.white),), onPressed: () { print('点击了 注册'); registerForm(); }, ), ) ], ) ); } }
- 5.3、验证填写的表单数据在表单中,我们可以添加
验证器
,如果不符合某些特定的规则,那么给用户一定的提示信息比如我们需要账号和密码有这样的规则:账号和密码都不能为空。按照如下步骤就可以完成整个验证过程:
- 1、为TextFormField添加validator的回调函数;
validator: (value) { return value.length < 6 ? "密码长度不够6位" : null; },
- 2、调用Form的State对象的validate方法,就会回调validator传入的函数;
也可以为TextFormField添加一个属性:autovalidate
不需要调用validate方法,会自动验证是否符合要求;
void registerForm() { // 读取当前 From 的状态 var registerFrom = registerFormKey.currentState; // 验证From表单 if (registerFrom.validate()) { // 符合要求进行存储 registerFrom.save(); print("username:$username password:$password"); } }