一.效果图
二.页面分析
这里我们只用关注资讯页面就行,资讯页面大概可以分为两个部分:
1.顶部导航栏
顶部导航栏有3个固定的tab,选中的时候字体变大,并且改变颜色,如果直接使用系统的TabBar控件的话就不能改变字体大小了,所以这里自定义导航栏,可以自己来实现想要的效果。如果Tab是动态的话可以使用横向的ListView,这里由于只有固定的3个所以直接使用Row嵌套3个Text来实现这个导航栏。
2.页面body
页面主题可以直接使用ListView控件来实现,这里主要item布局样式:
1.推荐页面可以看出,分两种情况,一种是无图,一种是有图片的展示,这里最多展示3张图片,根据接口返回的图片集合来判断是否有图片,然后分别加载不同的控件。所以推荐页面item样式大概就是Colum Text Image Row Text。
2.城市页面和导购页面item样式是一致的,但是和推荐页面的样式还是有区别,推荐页面图片是在中间,但是这两个页面的图片是在右边,所以整体是在右布局。
三.码代码
1.构建导航栏
margin:设置距离顶部的间距为状态栏的高度。 height:设置导航栏高度。 tabText():Text公共属性
Container:是常用的容器控件之一,只包含一个子控件,用来定位和修饰子控件,比如形状和背景颜色等。
SizeBox: 比较常用的控件,只包含一个子控件,用来限制子控件的大小。
Expanded:包含一个子控件,默认不带其他参数的情况下,用来充满页面剩余位置,类似于android里面的weight,不过要注意的是使用Expanded的时候,父组件的尺寸应该是可计算的或者固定值,不能是无限制,不然程序没法知道,就会包错。
PageView通过 currentIndex来关联更新 顶部text和主题页面之间的切换,滑动切换页面的时候,同步更新顶部tab导航栏。
代码语言:javascript复制class TabBarInfoPageState extends State<TabBarInfoPage> {
int currentIndex = 0;
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Column(children: [
Container(
margin: EdgeInsets.only(top: ScreenUtil().statusBarHeight),
height: 80.h,
child: Row(
children: [
SizedBox(width: 20.w),
tabText("推荐", 0),
SizedBox(width: 50.w),
tabText("武汉", 1),
SizedBox(width: 50.w),
tabText("导购", 2)
],
)
),
Expanded(
child: PageView.builder(
onPageChanged: ((int index) => setState(() {
currentIndex = index;
})),
itemCount: 3,
itemBuilder: (context, index) {
return InfoListPage(index 1);
}))
]));
}
/// 导航栏文本样式定义
Text tabText(String text, int index) {
return Text(text,
style: TextStyle(
color: currentIndex == index ? Colors.black : Colors.grey,
fontSize: currentIndex == index ? 40.sp : 30.sp));
}
复制代码
2.构建资讯列表
资讯列表分为两种样式,一种是多张图片,并且图片在中间,另外一种是单张图片,并且图片在右边,
代码语言:javascript复制 /// 推荐tabUI样式
Widget recommendWidget(InfoMessageDataActivityData info) {
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(info.msgTitle.trim(),
textAlign: TextAlign.left, style: TextStyle(fontSize: 30.sp)),
SizedBox(height: 20.h),
Row(
children: images(info.msgTitleImgList),
mainAxisAlignment: MainAxisAlignment.spaceBetween,
),
SizedBox(
height: 20.h,
),
Row(children: [
Text(
info.sourceInfo,
style: TextStyle(color: Colors.grey),
),
Text("${info.clickNum}阅读", style: TextStyle(color: Colors.grey))
], mainAxisAlignment: MainAxisAlignment.spaceBetween),
SizedBox(height: 20.h),
Divider(
height: 1.h,
indent: 0,
color: Colors.grey,
)
]);
}
复制代码
代码语言:javascript复制Widget shoppingWidget(InfoMessageDataActivityData info) {
List<String> images = info.msgTitleImgList;
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
Expanded(
child: SizedBox(
height: 150.h,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(info.msgTitle,
textAlign: TextAlign.left,
style: TextStyle(fontSize: 30.sp)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
info.sourceInfo,
style: TextStyle(color: Colors.grey),
),
Text("${info.clickNum}阅读",
style: TextStyle(color: Colors.grey))
]),
]))),
images == null
? Container()
: Padding(
padding: EdgeInsets.only(left: 15.w),
child: ClipRRect(
child: Image.network(info.msgTitleImgList[0],
width: 220.w, height: 150.h, fit: BoxFit.cover),
borderRadius: BorderRadius.circular(6),
))
]),
SizedBox(height: 20.h),
Divider(
height: 1.h,
indent: 0,
color: Colors.grey,
)
]);
}