内容简介:(授权转载)微信码个蛋授权转载作者:这是我之前我预告要发的系列文章,昨天因为排版删了,没有原作者同意请勿二次转载。
(授权转载)微信码个蛋授权转载
作者:这是我之前我预告要发的系列文章,昨天因为排版删了,没有原作者同意请勿二次转载。
前面提到基础部件的时候,忘了提输入内容处理部件,这里补上,然后顺带撸个实际的界面吧
TextField
const TextField({ Key key, this.controller, // 定义一个 `TextEditingController` 实例,用来获取输入框内容等操作 this.focusNode, // 定义一个 `FocusNode` 实例,判断当前输入框是否获取到焦点等操作 this.decoration = const InputDecoration(), // 输入框样式,包括提醒字样,hint 等等 TextInputType keyboardType, // 输入文本类型,例如 数字,email 等等 this.textInputAction, // 键盘确认按钮的事件类型 this.textCapitalization = TextCapitalization.none, this.style, // 文字样式 this.textAlign = TextAlign.start, // 对齐方式 this.textDirection, // 文字方向 this.autofocus = false, // 是否自动获取焦点 this.obscureText = false, // 文字是否隐藏,多用于密码 this.autocorrect = true, this.maxLines = 1, // this.maxLength, // 最大长度 this.maxLengthEnforced = true, // 设置最大长度后,输入内容超出后是否强制不给输入 this.onChanged, // 输入内容发生变化时候的回调 this.onEditingComplete, // 输入完毕的回调 this.onSubmitted, // 提交内容的回调 this.inputFormatters, // this.enabled, // 是否可输入,false 不可输入 this.cursorWidth = 2.0, // 游标宽度 this.cursorRadius, // 游标半径 this.cursorColor, // 游标颜色 this.keyboardAppearance, // 该属性只在 iOS 设备有效 this.scrollPadding = const EdgeInsets.all(20.0), this.enableInteractiveSelection, this.onTap, // 点击事件 })
那么,简单的来个输入框示例吧,然后通过 Text
展示结果
class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState(); }class _HomePageState extends State<HomePage> { // 可以传入初始值 TextEditingController _editController = TextEditingController(); FocusNode _editNode = FocusNode(); // 保存按钮点击后的输入内容值 String _content = ''; // 监听输入内容变化的内容值 String _spyContent = ''; @override void initState() { super.initState(); // 当输入框获取到焦点或者失去焦点的时候回调用 _editNode.addListener(() { print('edit has focus? => ${_editNode.hasFocus}'); }); } @override void dispose() { // 记得销毁,防止内存溢出 _editController.dispose(); _editNode.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Input Content'), ), body: Container( padding: const EdgeInsets.symmetric(horizontal: 12.0), child: Column( children: <Widget>[ TextField( controller: _editController, focusNode: _editNode, decoration: InputDecoration( icon: Icon(Icons.phone_iphone, color: Theme.of(context).primaryColor), labelText: '请输入手机号', helperText: '手机号', hintText: '手机号...在这儿输入呢'), keyboardType: TextInputType.number, // 输入类型为数字类型 textInputAction: TextInputAction.done, style: TextStyle(color: Colors.redAccent, fontSize: 18.0), textDirection: TextDirection.ltr, maxLength: 11, // 最大长度为 11 maxLengthEnforced: true, // 超过长度的不显示 onChanged: (v) { // 输入的内容发生改变会调用 setState(() => _spyContent = v); }, onSubmitted: (s) { // 点击确定按钮时候会调用 setState(() => _spyContent = _editController.value.text); }, ), Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: RaisedButton( onPressed: () { // 获取输入的内容 setState(() => _content = _editController.value.text); // 清理输入内容 _editController.clear(); setState(() => _spyContent = ''); }, child: Text('获取输入内容'))), // 展示输入的内容,点击按钮会显示 Text(_content.isNotEmpty ? '获取到输入内容: $_content' : '还未获取到任何内容...'), Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), // 监听输入内容的变化,会跟随输入的内容进行改变 child: Text('我是文字内容监听:$_spyContent'), ) ], )), ); } }
这边需要提下的是 setState
方法,该方法只有 StatefulWidget
才有,当需要修改某个值的内容的时候,通过该方法进行修改,最后的效果图如下,当输入框文字发生变化的时候,监听的 Text
内容会随之改变,获取内容的 Text
当点击按钮了才发生变化
textField 展示1.png
textField 展示2.png
该部分代码查看 text_field_main.dart
文件
那么如果有个需求,在点击按钮的时候需要对输入的内容的合理性进行检测,当然可以通过 TextEditingController
的结果进行检测,但是还有个更加方便的方法,可以直接使用部件 TextFormField
来实现,不过需要我们在外层加一个 Form
部件,接下来,就要准备通过 TextFormField
来撸一个登录界面,但是这之前,前面有个坑需要先解决下
导入自定义的图标
在这之前,涉及到 Icon
部件,都是使用的系统自带的图标,那么如何导入第三方自定义图标呢,马上为你揭晓答案,首先我们需要打开「阿里妈妈」也就是 iconfont ,不知道的小伙伴通过链接打开,然后需要注册个账户,也可以直接通过 Github
等三方登录,然后就可以搜索我们需要的图标了,接下来需要撸一个登录,那我们就找一个 用户 和 密码 的图标吧,选择喜欢的图标,然后鼠标放到图标会出现三个按钮,直接点击 购物车 那个按钮,然后就可以通过顶部的 购物车 按钮查看添加的图标,点击下载代码,把资源文件下载到本地。
iconfont.png
解压后,需要用到的文件有两个,别的可以忽略
-
demo_index.html
这边用来查看图标的unicode
-
iconfont.ttf
这边就是图标资源文件了
回到项目,创建一个文件夹 fonts
,和 images
同级,将 iconfont.ttf
文件放到该文件夹下,然后打开 pubspec.ymal
文件,注册下导入的资源,可以自己命名 iconfont.ttf
文件名,便于自己发现就行,例如我命名为 third_part_icon.ttf
,在注册图片下面继续添加
fonts: - family: ThirdPartIcons fonts: - asset: fonts/third_part_icon.ttf
注册完了记得点击 Package get
,否则会找不到资源。接着新建个 third_icons.dart
文件
import 'package:flutter/material.dart';class ThirdIcons { // codePoint 值通过打开 `demo_index.html` 获取 // 会在相应 icon 下带有相应的 code,把 `&#` 替换成 `0`,然后去掉最后的 `;` 即可 // 例如 对应我们需要的图标就是 0xe672 static const IconData username = ThirdIconData(0xe672); static const IconData password = ThirdIconData(0xe62f); }class ThirdIconData extends IconData { // fontFamily 就是我们在 `pubspec.yaml` 中注册的 family 值 const ThirdIconData(int codePoint) : super(codePoint, fontFamily: 'ThirdPartIcons'); }
接下来就可以通过该类导入需要的第三方图标了。
导入第三方插件
其实 Flutter
中缺少很多功能,需要通过导入第三方插件来实现功能,插件就是 Flutter
和原生交互的桥梁,也就是说,要写 Flutter
的插件,需要写 Android
和 iOS
两端代码才可,否则只有在其中一个端能够实现功能。好在有很多现成的插件已经开源,可以通过 FlutterPackage 搜索到,例如等会我们会需要用到 FlutterToast
这个插件,用来做提醒用,在 FlutterPackage
中搜索到插件后,打开项目中的 pubspec.ymal
文件,在 dependencies
类目下将 fluttertoast
插件引入,如图:
插件导入展示.png
然后点击 Package get
让其导入即可,别的插件也是这样导入。做好准备工作,我们就可以撸一个登录界面了~
撸一个登录界面
在开撸之前,我们先看下最终的效果图吧,虽然是比较常用的界面(因为图都是自己搞的,比较丑请不要介意)
登录展示.png
注册展示.png
因为两个界面比较相似,所以这边只贴外层的代码和登录的代码,具体的代码,可以查看源码,已经推到 Github
void main() { runApp(LoginApp()); if (Platform.isAndroid) { var style = SystemUiOverlayStyle(statusBarColor: Colors.transparent); SystemChrome.setSystemUIOverlayStyle(style); } }/// 外层界面,包裹登录界面和注册界面,使用的都是前面讲过的,忘记可以查看之前的章节class LoginApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Login Demo', debugShowCheckedModeBanner: false, theme: ThemeData(primarySwatch: Colors.lightBlue), home: LoginHomePage(), ); } }class LoginHomePage extends StatefulWidget { @override _LoginHomePageState createState() => _LoginHomePageState(); }class _LoginHomePageState extends State<LoginHomePage> with SingleTickerProviderStateMixin { TabController _tabController; List<String> _pageIndicators = ['登录', '注册']; List<Widget> _pages = []; int _position = 0; @override void initState() { super.initState(); _tabController = TabController(length: _pageIndicators.length, vsync: this); // 将登录界面和注册界面添加到列表,用于放到 IndexStack 的 children 属性 _pages..add(LoginPage())..add(RegisterPage()); _tabController.addListener(() { // 当 tab 切换的时候,联动 IndexStack 的 child 页面也进行修改,通过 setState 来修改值 if (_tabController.indexIsChanging) setState(() => _position = _tabController.index); }); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { // 先忽略... return Theme( data: ThemeData(primarySwatch: Colors.pink, iconTheme: IconThemeData(color: Colors.pink)), child: Scaffold( body: Container( padding: const EdgeInsets.all(20.0), alignment: Alignment.center, decoration: BoxDecoration(image: DecorationImage(image: AssetImage('images/login_bg.png'), fit: BoxFit.cover)), // 先忽略...下面会讲,主要是解决软键盘弹出的时候,界面内容会溢出的问题 child: SingleChildScrollView( child: SafeArea( child: Column(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ // 顶部页面切换指示器,代码可以参考 `app_bar_main.dart` 文件 TabBar( indicatorSize: TabBarIndicatorSize.label, controller: _tabController, indicatorWeight: 4.0, indicatorColor: Colors.white, // 返回 tab 列表 tabs: _pageIndicators .map((v) => Text(v, style: TextStyle(color: Colors.white, fontSize: 24.0))) .toList()), Padding( padding: const EdgeInsets.only(top: 30.0), child: SizedBox( // 切换界面列表 child: IndexedStack(children: _pages, index: _position), // 指定高度 height: MediaQuery.of(context).size.height / 2)) ])), ), ), )); } }
/// 登录界面class LoginPage extends StatefulWidget { @override _LoginPageState createState() => _LoginPageState(); }class _LoginPageState extends State<LoginPage> { // 用于后面判断表单内容是否有效 GlobalKey<FormState> _formKey = GlobalKey(); // 用于获取输入框的内容 TextEditingController _usernameController = TextEditingController(); TextEditingController _passwordController = TextEditingController(); @override void initState() { super.initState(); } @override void dispose() { // 防止内存溢出,记得销毁..销毁..销毁 _usernameController.dispose(); _passwordController.dispose(); super.dispose(); } _login() { // 取消焦点 FocusScope.of(context).requestFocus(FocusNode()); // 判断表单是否有效 if (_formKey.currentState.validate()) { // 获取输入框内容 var username = _usernameController.value.text; var password = _passwordController.value.text; // 判断登录条件 if (username == 'kuky' && password == '123456') // 引入的三方插件方法,`Flutter` 没有自带的 `Taost` Fluttertoast.showToast(msg: '登录成功'); else Fluttertoast.showToast(msg: '登录失败'); } } @override Widget build(BuildContext context) { return Form( // 将 key 设置给表单,用于判断表单是否有效 key: _formKey, child: Column( children: <Widget>[ Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), // 表单输入框,参数同 TextField 基本类似 child: TextFormField( controller: _usernameController, style: TextStyle(color: Colors.white, fontSize: 16.0), decoration: InputDecoration( icon: Icon(ThirdIcons.username, size: 24.0, color: Colors.white), labelText: '请输入用户名', labelStyle: TextStyle(color: Colors.white), helperStyle: TextStyle(color: Colors.white)), // 有效条件(为空不通过,返回提示语,通过返回 null) validator: (value) => value.trim().isEmpty ? '用户名不能为空' : null, ), ), Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), child: TextFormField( obscureText: true, controller: _passwordController, style: TextStyle(color: Colors.white, fontSize: 16.0), decoration: InputDecoration( icon: Icon(ThirdIcons.password, size: 24.0, color: Colors.white), labelText: '请输入密码', labelStyle: TextStyle(color: Colors.white), helperStyle: TextStyle(color: Colors.white)), validator: (value) => value.trim().length < 6 ? '密码长度不能小于6位' : null, ), ), Padding( padding: const EdgeInsets.only(top: 20.0), child: SizedBox( // 主要用于使 RaisedButton 和上层容器同宽 width: MediaQuery.of(context).size.width, child: RaisedButton( color: Colors.pink, shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))), onPressed: _login, child: Text( '登录', style: TextStyle(color: Colors.white, fontSize: 20.0), )), ), ) ], )); } }
撸完界面后,可以试下登录效果,如果输入框的内容,和 TextFormField
的 validator
的条件不符合,则会显示错误文字的提示
登录错误展示.png
如果按照条件用户名为 kuky
密码为 123456
(条件可以根据自己进行修改)则会显示登录成功的逻辑
登录成功展示.png
以上代码查看 login_home_page.dart
文件
注册界面的逻辑和登录界面的逻辑几乎一样,算是第一次实战了,望小伙伴能够好好的写一遍
最后代码的地址还是要的:
-
文章中涉及的代码: demos
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Dreamweaver CS3 Bible
Joseph W. Lowery / Wiley / May 21, 2007 / $49.99
Book Description Learn to create dynamic, data-driven Web sites using the exciting enhancements in the Dreamweaver CS3 version. You get a thorough understanding of the basics and then progress to l......一起来看看 《Dreamweaver CS3 Bible》 这本书的介绍吧!