我的界面搭建:
先来搭建一下我的界面,目前我的界面是一个空壳:
而最终要的效果是这样:
下面先来搭建界面:
菜单数据准备:
先定义元素文本及图标:
import 'package:flutter/material.dart';
class ProfilePage extends StatefulWidget {
@override
_ProfilePageState createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
List menuTitles = [
'我的消息',
'阅读记录',
'我的博客',
'我的问答',
'我的活动',
'我的团队',
'邀请好友',
];
List menuIcons = [
Icons.message,
Icons.print,
Icons.error,
Icons.phone,
Icons.send,
Icons.people,
Icons.person,
];
@override
Widget build(BuildContext context) {
return Center(
child: Text('我的'),
);
}
}
构建菜单项:
这里肯定是用ListView来构建了,这块之前学习过,直接上代码:
import 'package:flutter/material.dart';
class ProfilePage extends StatefulWidget {
@override
_ProfilePageState createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
List menuTitles = [
'我的消息',
'阅读记录',
'我的博客',
'我的问答',
'我的活动',
'我的团队',
'邀请好友',
];
List menuIcons = [
Icons.message,
Icons.print,
Icons.error,
Icons.phone,
Icons.send,
Icons.people,
Icons.person,
];
@override
Widget build(BuildContext context) {
return ListView.separated(
itemBuilder: (context, index) {
if (index == 0) {
return Container(
height: 200.0,
color: Colors.red,
);
}
index -= 1;
return ListTile(
leading: Icon(menuIcons[index]), //左图标
title: Text(menuTitles[index]), //中间标题
trailing: Icon(Icons.arrow_forward_ios),
);
},
separatorBuilder: (context, index) {
return Divider();
}, //分隔线
itemCount: menuTitles.length + 1);
}
}
上面由于将头像也做为列表的一项,所以在总列表项个数是+1,比较好理解,先看一下运行效果:
是不是感觉Flutter构建UI代码还是挺少的,像模像样的列表就出来了,接下来则来构建用户头像:
@override
Widget build(BuildContext context) {
return ListView.separated(
itemBuilder: (context, index) {
if (index == 0) {
//用户头像
return Center(
child: Column(
children: <Widget>[
Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: Colors.white,
width: 2.0,
),
image: DecorationImage(
image:
AssetImage('assets/images/ic_avatar_default.png'),
fit: BoxFit.cover,
)),
)
],
),
);
}
index -= 1;
return ListTile(
leading: Icon(menuIcons[index]), //左图标
title: Text(menuTitles[index]), //中间标题
trailing: Icon(Icons.arrow_forward_ios),
);
},
separatorBuilder: (context, index) {
return Divider();
}, //分隔线
itemCount: menuTitles.length + 1);
}
关于BoxDecoration的使用可以参考https://www.cnblogs.com/webor2006/p/12845831.html,其中用到了一个默认图像图:
上面是个纯白的图哦,其实是长这样:
记得要在yaml中声明哦:
运行瞅一下效果:
呃,样式不太对, 咱们先给它加一个背景颜色:
@override
Widget build(BuildContext context) {
return ListView.separated(
itemBuilder: (context, index) {
if (index == 0) {
//用户头像
return Container(
color: Color(AppColors.APP_THEME),
height: 150.0,
child: Center(
child: Column(
children: <Widget>[
Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: Colors.white,
width: 2.0,
),
image: DecorationImage(
image: AssetImage(
'assets/images/ic_avatar_default.png'),
fit: BoxFit.cover,
)),
)
],
),
),
);
}
index -= 1;
return ListTile(
leading: Icon(menuIcons[index]), //左图标
title: Text(menuTitles[index]), //中间标题
trailing: Icon(Icons.arrow_forward_ios),
);
},
separatorBuilder: (context, index) {
return Divider();
}, //分隔线
itemCount: menuTitles.length + 1);
}
运行:
头像木有居中,所以改一下:
再运行:
接下来则需要在它下面加一个用户名称的文本:
@override
Widget build(BuildContext context) {
return ListView.separated(
itemBuilder: (context, index) {
if (index == 0) {
//用户头像
return Container(
color: Color(AppColors.APP_THEME),
height: 150.0,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: Colors.white,
width: 2.0,
),
image: DecorationImage(
image: AssetImage(
'assets/images/ic_avatar_default.png'),
fit: BoxFit.cover,
)),
),
SizedBox(
//加间距
height: 10.0,
),
Text(
'点击头像登录',
style: TextStyle(color: Colors.white),
)
],
),
),
);
}
index -= 1;
return ListTile(
leading: Icon(menuIcons[index]), //左图标
title: Text(menuTitles[index]), //中间标题
trailing: Icon(Icons.arrow_forward_ios),
);
},
separatorBuilder: (context, index) {
return Divider();
}, //分隔线
itemCount: menuTitles.length + 1);
}
运行:
貌似界面有点不太和谐呀,看这:
所以将标题栏的阴影得去掉,加个属性配置就成了:
再运行看一下:
另外咱们给头像先增加一个点击事件,其它菜单列表暂且先放着不管,这次主要焦点是通过登录这个案例来学会Flutter的网络请求,这里则需要将头像用手势的widget包裹一下了:
@override
Widget build(BuildContext context) {
return ListView.separated(
itemBuilder: (context, index) {
if (index == 0) {
//用户头像
return Container(
color: Color(AppColors.APP_THEME),
height: 150.0,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
child: Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: Colors.white,
width: 2.0,
),
image: DecorationImage(
image: AssetImage(
'assets/images/ic_avatar_default.png'),
fit: BoxFit.cover,
)),
),
onTap: () {
//TODO:执行登录
},
),
SizedBox(
//加间距
height: 10.0,
),
Text(
'点击头像登录',
style: TextStyle(color: Colors.white),
)
],
),
),
);
}
index -= 1;
return ListTile(
leading: Icon(menuIcons[index]), //左图标
title: Text(menuTitles[index]), //中间标题
trailing: Icon(Icons.arrow_forward_ios),
);
},
separatorBuilder: (context, index) {
return Divider();
}, //分隔线
itemCount: menuTitles.length + 1);
}
先写个TODO吧,由于跳转到登录时需要使用到了开源中国的API,所以,接下来将焦点转移一下,先来对开源中国的API有一个理性上的认识。