目标:
1.怎么构建抽屉菜单效果?
2.抽屉菜单怎么定制?
一、抽屉菜单
侧滑抽屉菜单效果
1.1 抽屉菜单入口
Flutter 的脚手架Scaffold,默认提供了抽屉菜单效果入口。
主页面采用一个简单的页面,侧滑菜单首先使用一个Image,先看看侧滑效果。
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:myflutter/drawer/widget/main_drawer.dart';void main() => runApp(DrawerApp());/*** 构建抽屉菜单APP** @author zhouronghua* @time 2024/6/20 上午9:47*/
class DrawerApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text("抽屉菜单"),),drawer: Drawer(/// 自定义抽屉菜单Widgetchild: MainDrawer(),),body: new MainPage(),),);}
}/*** 主页面** @author zhouronghua* @time 2024/6/20 上午10:02*/
class MainPage extends StatelessWidget {@overrideWidget build(BuildContext context) {// 主页面简单一个容器return Container(child: Text("我是主页面"),);}
}
显示效果:
1.2 定制抽屉菜单
抽屉菜单显示用户未登录状态,允许用户点击,点击跳转登录页。
添加用户头像Header,和收藏菜单项
import 'package:flutter/material.dart';class MainDrawer extends StatefulWidget {@override_MainDrawerState createState() {return _MainDrawerState();}
}class _MainDrawerState extends State<MainDrawer> {/// 用户名:标记用户是否登录late String _userName;@overrideWidget build(BuildContext context) {// 顶部用户信息Widget userHeader = DrawerHeader(decoration: BoxDecoration(color: Colors.orangeAccent,),child: InkWell(/// 纵向视图child: Column(/// 设置内边距children: [Padding(padding: EdgeInsets.only(bottom: 20.0),// 采用一个圆形图像child: CircleAvatar(backgroundImage: AssetImage('assets/images/logo.png'),/// 设置图片半径radius: 40.0,),),Text("请先登录", style: TextStyle(fontSize: 20.0)),],),));return ListView(// 列表项子项children: [/// 用户头userHeader,/// 收藏InkWell(onTap: () => {},child: ListTile(leading: Icon(Icons.favorite),title: Text('收藏列表', style: TextStyle(fontSize: 16.0)),),),],);}
}
assets的图像可能加载不出来。
怎么解决呢?
1.2.1 解决assets图片加载不出来
添加assets图片,需要注册一下图片。
1)注册图片资源
在项目pubspec.yaml 中,将需要使用的图片进行注册
2)引用图片
路径就是 assets/图片路径。
// 采用一个圆形图像child: CircleAvatar(backgroundImage: AssetImage('assets/images/logo.png'),/// 设置图片半径radius: 40.0,),
热重载项目,可以看到图片已经加载出来了。
1.3 抽屉菜单点击事件监听
InkWell 对应的点击事件:onTap
点击用户头像,如果没有登录,则导航跳转登录页面。
// 顶部用户信息Widget userHeader = DrawerHeader(decoration: BoxDecoration(color: Colors.orangeAccent,),child: InkWell(/// 点击事件onTap: () {/// 点击跳转登录页面if (_userName == null) {/// 用户未登录跳转登录页面Navigator.push(context, MaterialPageRoute(builder: (context) {return LoginPage();}));debugPrint("open login page");}},/// 纵向视图child: Column(/// 设置内边距children: [Padding(padding: EdgeInsets.only(bottom: 20.0),// 采用一个圆形图像child: CircleAvatar(backgroundImage: AssetImage('assets/images/logo.png'),/// 设置图片半径radius: 40.0,),// child: ClipRRect(// borderRadius: BorderRadius.circular(40.0),// child: Image.network(// 'http://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280',// fit: BoxFit.cover,// ),// ),),Text("请先登录", style: TextStyle(fontSize: 20.0)),],),));
二、用户登录页面
用户登录页,输入用户名+密码。
2.1 Form表单
Flutter提供了表单组件,可以定制表单内容。
登录需要输入用户名,输入密码,以及登录按钮,因此可以采用一个列表结构展示。
import 'package:flutter/material.dart';class LoginPage extends StatefulWidget {@overrideLoginPageState createState() {return LoginPageState();}
}class LoginPageState extends State<LoginPage> {final _formKey = GlobalKey<FormState>();FocusNode _pwdNode = new FocusNode();late String? _username = null, _password = null;bool _isObscure = true;late Color? _pwdIconColor = null;@overridevoid dispose() {_pwdNode.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("登录"),),body: Form(key: _formKey,child: ListView(padding: EdgeInsets.symmetric(horizontal: 22.0),children: <Widget>[_buildUserName(),_buildPwd(),_buildLogin(),_buildRegister(),],)));}Widget _buildRegister() {return Padding(padding: EdgeInsets.only(top: 10.0),child: Row(///孩子居中对齐mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Text('没有账号?'),GestureDetector(child: Text('点击注册',style: TextStyle(color: Colors.green),),onTap: () async {///进入注册// Navigator.push(context, MaterialPageRoute(builder: (_) {// return RegisterPage();// }));},),],),);}Widget _buildLogin() {return Container(height: 45.0,margin: EdgeInsets.only(top: 18.0, left: 8.0, right: 8.0),child: RaisedButton(child: Text('登录',style: TextStyle(fontSize: 18.0, color: Colors.white),),color: Theme.of(context).primaryColor,onPressed: _doLogin,),);}Widget _buildPwd() {return TextFormField(focusNode: _pwdNode,///是否隐藏obscureText: _isObscure,validator: (String? value) {if (value?.trim().isEmpty == true) {return '请输入密码';}_password = value;},textInputAction: TextInputAction.done,onEditingComplete: _doLogin,decoration: InputDecoration(labelText: '密码',///输入框尾部图标suffixIcon: IconButton(icon: Icon(Icons.remove_red_eye,color: _pwdIconColor,),onPressed: () {setState(() {_isObscure = !_isObscure;///密码隐藏 图标颜色控制_pwdIconColor = (_isObscure? Colors.grey: Theme.of(context).iconTheme.color)!;});})),);}Widget _buildUserName() {return TextFormField(autofocus: true,decoration: InputDecoration(labelText: '用户名',),initialValue: _username,/// 从注册返回username///设置键盘回车为下一步textInputAction: TextInputAction.next,onEditingComplete: () {///点击下一步FocusScope.of(context).requestFocus(_pwdNode);},validator: (String? value) {if (value?.trim().isEmpty == true) {return '请输入用户名';}_username = value;},);}void _doLogin() async {_pwdNode.unfocus();///输入的内容通过验证if (_formKey.currentState?.validate() == true) {//TODO 执行登录方法// var result = await Api.login(_username, _password);// if (result['errorCode'] == -1) {// Toast.show(result['errorMsg'], context,// duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);// } else {// AppManager.eventBus.fire(LoginEvent(_username));// Navigator.pop(context);// }}}
}
2.2 输入框
用户名是一个输入框,采用 TextFormField 控件。
Widget _buildUserName() {return TextFormField(autofocus: true,decoration: InputDecoration(labelText: '用户名',),initialValue: _username,/// 从注册返回username/// 设置键盘回车为下一步textInputAction: TextInputAction.next,onEditingComplete: () {/// 软键盘点击下一步FocusScope.of(context).requestFocus(_pwdNode);},validator: (String? value) {if (value?.trim().isEmpty == true) {return '请输入用户名';}_username = value;},);}
2.2.1 属性说明
- autofocus:是否自动获得焦点
- decoration:控件修饰。创建用于的边框、标签、图标和样式的束
装饰“材质设计”文本字段。 - initialValue:输入框初始值
- textInputAction:设置键盘回车为下一步
- onEditingComplete:编辑完成时的回调。软件盘点击下一步进入密码输入框获得焦点
- validator:表单字段有效性校验。如果的内容为空的话,提示“请输入用户名”。点击“登录”的时候,校验输入的用户名内容。这个相当于输入内容的校验逻辑。return 返回的就是错误提示内容。