B 站视频
https://www.bilibili.com/vide…
本节目标
- 了解 supernova 代码生成器作用
- 导入 xd 设计稿
- 如何高效使用生成代码
正文
代码生成器
- supernova
- imgcook
有潜力加入代码生成功能
- lanhuapp
- mockplus
supernova 代码生成器
https://supernova.io/
导入 xd 设计稿,生成代码
商业设计稿不好直接分享, 可以加微信联系 ducafecat
编写用户中心界面代码
组织代码结构
class _AccountPageState extends State<AccountPage> {
// 个人页面 头部
Widget _buildUserHeader() {}
// 列表项
Widget _buildCell() {}
@override
Widget build(BuildContext context) {final appState = Provider.of<AppState>(context);
return SingleChildScrollView(
child: Column(
children: <Widget>[_buildUserHeader(),
_buildCell(),],
),
);
}
}
直接使用生成的代码
- 个人页面 头部
Widget _buildUserHeader() {
return Container(
height: 333,
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
left: 0,
right: 0,
child: Container(
height: 333,
decoration: BoxDecoration(color: AppColors.primaryBackground,),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 2,
decoration: BoxDecoration(color: AppColors.primaryElement,),
child: Container(),),
],
),
),
),
Positioned(
left: 20,
top: 40,
right: 20,
bottom: 21,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 198,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Align(
alignment: Alignment.topCenter,
child: Container(
width: 108,
height: 108,
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
top: 0,
child: Container(
width: 108,
height: 108,
decoration: BoxDecoration(
color: AppColors.primaryBackground,
boxShadow: [Shadows.primaryShadow,],
borderRadius: Radii.k54pxRadius,
),
child: Container(),),
),
Positioned(
top: 10,
child: Image.asset(
"assets/images/image.png",
fit: BoxFit.none,
),
),
],
),
),
),
Spacer(),
Container(margin: EdgeInsets.only(bottom: 9),
child: Text(
"Cameron Rogers",
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.primaryText,
fontFamily: "Montserrat",
fontWeight: FontWeight.w400,
fontSize: 24,
),
),
),
Text(
"@boltrogers",
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.primaryText,
fontFamily: "Avenir",
fontWeight: FontWeight.w400,
fontSize: 16,
),
),
],
),
),
Spacer(),
Container(
height: 44,
child: FlatButton(onPressed: () => this.onButtonPressed(context),
color: Color.fromARGB(255, 41, 103, 255),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(6)),
),
textColor: Color.fromARGB(255, 255, 255, 255),
padding: EdgeInsets.all(0),
child: Text(
"Get Premium - \$9.99",
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.secondaryText,
fontFamily: "Montserrat",
fontWeight: FontWeight.w400,
fontSize: 18,
),
),
),
),
],
),
),
],
),
);
}
- 列表项
Widget _buildCell() {
return Container(
height: 60,
child: Stack(
alignment: Alignment.centerLeft,
children: [
Positioned(
left: 0,
right: 0,
child: Container(
height: 60,
decoration: BoxDecoration(color: AppColors.secondaryElement,),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 1,
decoration: BoxDecoration(color: AppColors.primaryElement,),
child: Container(),),
],
),
),
),
Positioned(
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(margin: EdgeInsets.only(right: 11),
child: Text(
"12",
textAlign: TextAlign.right,
style: TextStyle(
color: AppColors.primaryText,
fontFamily: "Avenir",
fontWeight: FontWeight.w400,
fontSize: 18,
),
),
),
Container(
width: 24,
height: 24,
margin: EdgeInsets.only(right: 20),
child: Image.asset(
"assets/images/icon.png",
fit: BoxFit.none,
),
),
],
),
),
Positioned(
left: 0,
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
left: 0,
right: 19,
child: Container(),),
Positioned(
left: 20,
right: 0,
child: Text(
"Favorite channels",
textAlign: TextAlign.left,
style: TextStyle(
color: AppColors.primaryText,
fontFamily: "Montserrat",
fontWeight: FontWeight.w400,
fontSize: 18,
),
),
),
],
),
),
],
),
);
}
抽取代码 lib/common/widgets/app.dart
/// 10 像素 Divider
Widget divider10Px({Color bgColor = AppColors.secondaryElement}) {
return Container(height: duSetWidth(10),
decoration: BoxDecoration(color: bgColor,),
);
}
修改代码 _buildUserHeader
// 个人页面 头部
Widget _buildUserHeader() {
return Container(height: duSetWidth(333),
child: Stack(
alignment: Alignment.center,
children: [
// 背景
Positioned(
left: 0,
right: 0,
child: Container(height: duSetWidth(333),
decoration: BoxDecoration(color: AppColors.primaryBackground,),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(height: duSetWidth(2),
decoration: BoxDecoration(color: AppColors.tabCellSeparator,),
child: Container(),),
],
),
),
),
Positioned(
left: 20,
top: 40,
right: 20,
bottom: 21,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// 头像
Container(height: duSetWidth(198),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Align(
alignment: Alignment.topCenter,
child: Container(width: duSetWidth(108),
height: duSetWidth(108),
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
top: 0,
child: Container(width: duSetWidth(108),
height: duSetWidth(108),
decoration: BoxDecoration(
color: AppColors.primaryBackground,
boxShadow: [Shadows.primaryShadow,],
borderRadius: BorderRadius.all(Radius.circular(duSetWidth(108) / 2)),
),
child: Container(),),
),
Positioned(
top: 10,
child: Image.asset(
"assets/images/account_header.png",
height: duSetWidth(88),
width: duSetWidth(88),
fit: BoxFit.fill,
),
),
],
),
),
),
// 文字
Spacer(),
Container(margin: EdgeInsets.only(bottom: 9),
child: Text(
Global.profile.displayName,
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.primaryText,
fontFamily: "Montserrat",
fontWeight: FontWeight.w400,
fontSize: 24,
),
),
),
Text(
"@boltrogers",
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.primaryText,
fontFamily: "Avenir",
fontWeight: FontWeight.w400,
fontSize: 16,
),
),
],
),
),
// 按钮
Spacer(),
Container(
height: 44,
child: FlatButton(onPressed: () => {},
color: Color.fromARGB(255, 41, 103, 255),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(6)),
),
textColor: Color.fromARGB(255, 255, 255, 255),
padding: EdgeInsets.all(0),
child: Text(
"Get Premium - \$9.99",
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.primaryElementText,
fontFamily: "Montserrat",
fontWeight: FontWeight.w400,
fontSize: 18,
),
),
),
),
],
),
),
],
),
);
}
修改代码 _buildCell
// 列表项
Widget _buildCell({
String title,
String subTitle,
int number,
bool hasArrow = false,
VoidCallback onTap,
}) {
return GestureDetector(
onTap: onTap,
child: Container(height: duSetWidth(60),
color: Colors.white,
child: Stack(
alignment: Alignment.centerLeft,
children: [
// 背景
Positioned(
left: 0,
right: 0,
child: Container(height: duSetWidth(60),
decoration: BoxDecoration(color: AppColors.primaryBackground,),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(height: duSetWidth(1),
decoration: BoxDecoration(color: AppColors.tabCellSeparator,),
child: Container(),),
],
),
),
),
// 右侧
Positioned(
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
// 数字
number == null
? Container()
: Container(margin: EdgeInsets.only(right: 11),
child: Text(number.toString(),
textAlign: TextAlign.right,
style: TextStyle(
color: AppColors.primaryText,
fontFamily: "Avenir",
fontWeight: FontWeight.w400,
fontSize: duSetFontSize(18),
),
),
),
// 箭头
hasArrow == false
? Container()
: Container(width: duSetWidth(24),
height: duSetWidth(24),
margin: EdgeInsets.only(right: 20),
child: Icon(
Icons.arrow_forward_ios,
color: AppColors.primaryText,
),
),
],
),
),
// 标题
title == null
? Container()
: Positioned(
left: 20,
child: Text(
title,
textAlign: TextAlign.left,
style: TextStyle(
color: AppColors.primaryText,
fontFamily: "Montserrat",
fontWeight: FontWeight.w400,
fontSize: duSetFontSize(18),
),
),
),
// 子标题
subTitle == null
? Container()
: Positioned(
right: 20,
child: Text(
subTitle,
textAlign: TextAlign.left,
style: TextStyle(
color: AppColors.primaryText,
fontFamily: "Montserrat",
fontWeight: FontWeight.w400,
fontSize: duSetFontSize(18),
),
),
),
],
),
),
);
}
修改代码 build
@override
Widget build(BuildContext context) {final appState = Provider.of<AppState>(context);
return SingleChildScrollView(
child: Column(
children: <Widget>[_buildUserHeader(),
divider10Px(),
_buildCell(
title: "Email",
subTitle: "boltrogers@gmail.com",
),
divider10Px(),
_buildCell(
title: "Favorite channels",
number: 12,
hasArrow: true,
),
_buildCell(
title: "Bookmarks",
number: 294,
hasArrow: true,
),
_buildCell(
title: "Popular categories",
number: 7,
hasArrow: true,
),
divider10Px(),
_buildCell(
title: "Newsletter",
hasArrow: true,
),
_buildCell(
title: "Settings",
hasArrow: true,
),
divider10Px(),
_buildCell(
title: "Switch Gray Filter",
hasArrow: true,
onTap: () => appState.switchGrayFilter(),
),
_buildCell(
title: "Log out",
hasArrow: true,
onTap: () => goLoginPage(context),
),
divider10Px(),],
),
);
}
技巧
- vscode 固定代码
总结
资源
设计稿蓝湖预览
https://lanhuapp.com/url/lYuz1
密码: gSKl
蓝湖现在收费了,所以查看标记还请自己上传 xd 设计稿
商业设计稿文件不好直接分享, 可以加微信联系 ducafecat
代码
https://github.com/ducafecat/…