B站視訊
1 本節目標
- 程式碼規範
- 業務程式碼組織
- 首頁程式碼編寫
2 程式碼規範
2.1 官方程式碼規範
2.3 chrome 外掛 <彩雲小譯 - 網頁翻譯外掛>
chrome.google.com/webstore/de…
2.4 阿里專案規範
3 業務介面程式碼組織
3.1 redux、fish-redux
- redux 架構
- fish-redux 架構
進一步的細分,進行規範
github.com/alibaba/fis… medium.com/@dave790602…
- fish-redux 程式碼
3.2 bloc
- 架構
- 程式碼組織
3.3 簡單就是美
3.4 如何平衡
- 是否團隊開發
- 是否簡單業務(20 頁面)
- 是否重互動(視訊社交、聊天 A)
4 新聞首頁實現
4.1 介面組成分析
- 分類導航、推薦新聞、頻道導航
- 新聞列表、廣告 ad、郵件訂閱
4.2 程式碼框架
...
class _MainPageState extends State<MainPage> {
@override
void initState() {
super.initState();
_loadAllData();
}
// 讀取所有資料
_loadAllData() async {
}
// 分類選單
Widget _buildCategories() {
return Container();
}
// 推薦閱讀
Widget _buildRecommend() {
return Container();
}
// 頻道
Widget _buildChannels() {
return Container();
}
// 新聞列表
Widget _buildNewsList() {
return Container();
}
// ad 廣告條
// 郵件訂閱
Widget _buildEmailSubscribe() {
return newsletterWidget();
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: <Widget>[
_buildCategories(),
Divider(height: 1),
_buildRecommend(),
Divider(height: 1),
_buildChannels(),
Divider(height: 1),
_buildNewsList(),
Divider(height: 1),
_buildEmailSubscribe(),
],
),
);
}
}
複製程式碼
4.3 實現業務
- 建立 widget 單獨檔案
- 分類導航
lib/pages/main/categories_widget.dart
Widget newsCategoriesWidget({
List<CategoryResponseEntity> categories,
String selCategoryCode,
Function(CategoryResponseEntity) onTap,
}) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: categories.map<Widget>((item) {
return Container(
alignment: Alignment.center,
height: duSetHeight(52),
padding: EdgeInsets.symmetric(horizontal: 8),
child: GestureDetector(
child: Text(
item.title,
style: TextStyle(
color: selCategoryCode == item.code
? AppColors.secondaryElementText
: AppColors.primaryText,
fontSize: duSetFontSize(18),
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
),
),
onTap: () => onTap(item),
),
);
}).toList(),
),
);
}
複製程式碼
- 頻道導航
lib/pages/main/channels_widget.dart
Widget newsChannelsWidget({
List<ChannelResponseEntity> channels,
Function(ChannelResponseEntity) onTap,
}) {
return Container(
height: duSetHeight(137),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: channels.map<Widget>((item) {
return Container(
width: duSetWidth(70),
height: duSetHeight(97),
margin: EdgeInsets.symmetric(horizontal: duSetWidth(10)),
child: InkWell(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// 圖示
Container(
height: duSetWidth(64),
margin: EdgeInsets.symmetric(horizontal: duSetWidth(3)),
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
left: 0,
top: 0,
right: 0,
child: Container(
height: duSetWidth(64),
decoration: BoxDecoration(
color: AppColors.primaryBackground,
boxShadow: [
Shadows.primaryShadow,
],
borderRadius:
BorderRadius.all(Radius.circular(32)),
),
child: Container(),
),
),
Positioned(
left: duSetWidth(10),
top: duSetWidth(10),
right: duSetWidth(10),
child: Image.asset(
"assets/images/channel-${item.code}.png",
fit: BoxFit.none,
),
),
],
),
),
// 標題
Text(
item.title,
textAlign: TextAlign.center,
overflow: TextOverflow.clip,
maxLines: 1,
style: TextStyle(
color: AppColors.thirdElementText,
fontFamily: "Avenir",
fontWeight: FontWeight.w400,
fontSize: duSetFontSize(14),
height: 1,
),
),
],
),
onTap: () => onTap(item),
),
);
}).toList(),
),
),
);
}
複製程式碼
- 新聞行 Item
lib/pages/main/news_item_widget.dart
Widget newsItem(NewsItem item) {
return Container(
height: duSetHeight(161),
padding: EdgeInsets.all(duSetWidth(20)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// 圖
imageCached(
item.thumbnail,
width: duSetWidth(121),
height: duSetWidth(121),
),
// 右側
SizedBox(
width: duSetWidth(194),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// 作者
Container(
margin: EdgeInsets.all(0),
child: Text(
item.author,
style: TextStyle(
fontFamily: 'Avenir',
fontWeight: FontWeight.normal,
color: AppColors.thirdElementText,
fontSize: duSetFontSize(14),
height: 1,
),
),
),
// 標題
Container(
margin: EdgeInsets.only(top: duSetHeight(10)),
child: Text(
item.title,
style: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
color: AppColors.primaryText,
fontSize: duSetFontSize(16),
height: 1,
),
overflow: TextOverflow.clip,
maxLines: 3,
),
),
// Spacer
Spacer(),
// 一行 3 列
Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
// 分類
ConstrainedBox(
constraints: BoxConstraints(
maxWidth: duSetWidth(60),
),
child: Text(
item.category,
style: TextStyle(
fontFamily: 'Avenir',
fontWeight: FontWeight.normal,
color: AppColors.secondaryElementText,
fontSize: duSetFontSize(14),
height: 1,
),
overflow: TextOverflow.clip,
maxLines: 1,
),
),
// 新增時間
Container(
width: duSetWidth(15),
),
ConstrainedBox(
constraints: BoxConstraints(
maxWidth: duSetWidth(100),
),
child: Text(
'• ${duTimeLineFormat(item.addtime)}',
style: TextStyle(
fontFamily: 'Avenir',
fontWeight: FontWeight.normal,
color: AppColors.thirdElementText,
fontSize: duSetFontSize(14),
height: 1,
),
overflow: TextOverflow.clip,
maxLines: 1,
),
),
// 更多
Spacer(),
InkWell(
child: Icon(
Icons.more_horiz,
color: AppColors.primaryText,
size: 24,
),
onTap: () {},
),
],
),
),
],
),
),
],
),
);
}
複製程式碼
- 郵件訂閱
lib/pages/main/newsletter_widget.dart
Widget newsletterWidget() {
return Container(
margin: EdgeInsets.all(duSetWidth(20)),
child: Column(
children: <Widget>[
// newsletter
Row(
children: <Widget>[
Text(
'Newsletter',
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: duSetFontSize(18),
fontWeight: FontWeight.w600,
color: AppColors.thirdElement,
),
),
Spacer(),
IconButton(
icon: Icon(
Icons.close,
color: AppColors.thirdElementText,
size: duSetFontSize(17),
),
onPressed: () {},
),
],
),
// email
inputEmailEdit(
marginTop: 19,
keyboardType: TextInputType.emailAddress,
hintText: "Email",
isPassword: false,
controller: null,
),
// btn subcrible
Padding(
padding: EdgeInsets.only(top: 15),
child: btnFlatButtonWidget(
onPressed: () {},
width: duSetWidth(335),
height: duSetHeight(44),
fontWeight: FontWeight.w600,
title: "Subscribe",
),
),
// disc
Container(
margin: EdgeInsets.only(top: duSetHeight(29)),
width: duSetWidth(261),
child: Text.rich(TextSpan(children: <TextSpan>[
TextSpan(
text: 'By clicking on Subscribe button you agree to accept',
style: new TextStyle(
color: AppColors.thirdElementText,
fontFamily: "Avenir",
fontWeight: FontWeight.w400,
fontSize: duSetFontSize(14),
),
),
TextSpan(
text: ' Privacy Policy',
style: new TextStyle(
color: AppColors.secondaryElementText,
fontFamily: "Avenir",
fontWeight: FontWeight.w400,
fontSize: duSetFontSize(14),
),
recognizer: TapGestureRecognizer()
..onTap = () {
toastInfo(msg: 'Privacy Policy');
},
),
])),
),
],
),
);
}
複製程式碼
- 推薦閱讀
lib/pages/main/recommend_widget.dart
Widget recommendWidget(NewsRecommendResponseEntity newsRecommend) {
return Container(
margin: EdgeInsets.all(duSetWidth(20)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// 圖
imageCached(
newsRecommend.thumbnail,
width: duSetWidth(335),
height: duSetHeight(290),
),
// 作者
Container(
margin: EdgeInsets.only(top: duSetHeight(14)),
child: Text(
newsRecommend.author,
style: TextStyle(
fontFamily: 'Avenir',
fontWeight: FontWeight.normal,
color: AppColors.thirdElementText,
fontSize: duSetFontSize(14),
),
),
),
// 標題
Container(
margin: EdgeInsets.only(top: duSetHeight(10)),
child: Text(
newsRecommend.title,
style: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
color: AppColors.primaryText,
fontSize: duSetFontSize(24),
height: 1,
),
),
),
// 一行 3 列
Container(
margin: EdgeInsets.only(top: duSetHeight(10)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
// 分類
ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 120,
),
child: Text(
newsRecommend.category,
style: TextStyle(
fontFamily: 'Avenir',
fontWeight: FontWeight.normal,
color: AppColors.secondaryElementText,
fontSize: duSetFontSize(14),
height: 1,
),
overflow: TextOverflow.clip,
maxLines: 1,
),
),
// 新增時間
Container(
width: duSetWidth(15),
),
ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 120,
),
child: Text(
'• ${duTimeLineFormat(newsRecommend.addtime)}',
style: TextStyle(
fontFamily: 'Avenir',
fontWeight: FontWeight.normal,
color: AppColors.thirdElementText,
fontSize: duSetFontSize(14),
height: 1,
),
overflow: TextOverflow.clip,
maxLines: 1,
),
),
// 更多
Spacer(),
InkWell(
child: Icon(
Icons.more_horiz,
color: AppColors.primaryText,
size: 24,
),
onTap: () {},
),
],
),
),
],
),
);
}
複製程式碼
藍湖設計稿
lanhuapp.com/url/lYuz1 密碼: gSKl
藍湖現在收費了,所以檢視標記還請自己上傳 xd 設計稿 商業設計稿檔案不好直接分享, 可以加微信聯絡 ducafecat