首页List UI编写
Nealyang opened this issue · 0 comments
介绍
这一章节中,我们将完成首页List部分的编写
cell 结构分析
cell的整体是一个Column结构,每一行中,再是一个横向排列的。底部的点赞和评论按钮结构比较统一,可以考虑单独抽出来作为一个新的widget
作者和标题之间的点(.)无法通过文字直接模拟,所以这里我们把点也同样抽出来作为一个widget
cell 相关widget编写
个人编写习惯:先从小写到大,在大(iindexListCell)中引入你要写的小(inTextDot)以方便看样式,然后编写玩小的后再放到大的中使用.
- lib/widgets/inTextDot.dart
import 'package:flutter/material.dart';
class InTextDot extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 3.0,
height: 3.0,
margin: const EdgeInsets.symmetric(horizontal: 6.0),
decoration: BoxDecoration(
color: Color(0xFFB2BAC2),
borderRadius: BorderRadius.all(Radius.circular(3.0))),
);
}
}
文字中的点,比较容易,我们直接写一个container,用于做点,然后边距也作为这个widget该有的属性。注意看这里我们样式中对于Container自身的装饰属性所谓decoration,同样我们之前说的vscode功能,鼠标悬停在Widget上,可以看到他的属性,以及这个属性的值类型
- lib/widgets/goodAndCommentCell.dart
这里点赞和评论的cell很简单,其实仔细分析可以看到,点赞和评论也是同一个组件才对,不应该写两遍。这里我就不优化,之所以是截图,希望大家可以自己动手,发挥自己的聪明才智,编写这一个UI,或者说,优化我上面的代码~
- lib/widgets/indexListCell.dart
首先我们定义一些基础变量
final IndexCell cellInfo;
IndexListCell({Key key, this.cellInfo}) : super(key: key);
TextStyle titleTextStyle = TextStyle(
color: Color(0xFFB2BAC2),
fontWeight: FontWeight.w300,
fontSize: 13.0,
);
由于第一行中,热门、专栏、推荐等是不一定存在的,所以这里我们需要写一个方法去判断是否存在这个字段
List<Widget> _buildFirstRow() {
List<Widget> _listRow = new List();
if (cellInfo.hot) {
_listRow.add(Text(
'热',
style: TextStyle(
color: Color(0xFFF53040),
fontWeight: FontWeight.w600,
),
));
_listRow.add(InTextDot());
}
if (cellInfo.isCollection == 'post') {
_listRow.add(Text(
'专栏',
style: TextStyle(
color: Color(0xFFBC30DA),
fontWeight: FontWeight.w600,
),
));
_listRow.add(InTextDot());
}
_listRow.add(Text(cellInfo.username, style: titleTextStyle));
_listRow.add(InTextDot());
_listRow.add(Text(cellInfo.createdTime, style: titleTextStyle));
_listRow.add(InTextDot());
_listRow.add(Expanded(
//防止文本超长
child: Text(
cellInfo.tag,
style: titleTextStyle,
overflow: TextOverflow.ellipsis,
),
));
return _listRow;
}
而cell的布局如上我们分析的那样,Column中一行一行的搞下去
所以此处build方法如下:
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: 20.0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: _buildFirstRow(),
),
),
Container(
margin: const EdgeInsets.symmetric(vertical: 9.0),
child: Text(
cellInfo.title,
style: TextStyle(
color: Color(0xFF393C3F),
fontSize: 14.0,
fontWeight: FontWeight.w600,
),
overflow: TextOverflow.ellipsis,
),
),
GoodAndCommentCell(cellInfo.collectionCount, cellInfo.commentCount),
SizedBox(
height: 15.0,
),
Divider(
height: 2.0,
),
],
),
);
}
对于一些样式的调整和边距的调整,大家可以根据自己的审美哈~实际开发中,这些也根据设计师给我们的样式来做相应开发。
头部header
分析线上页面,我们可以看到在列表的cell上部,还有个头部,在我们登陆状态和非登录状态是不同的,所以这里,我们肯定是需要给他一个Widget组件来实现的
- lib/widgets/indexListHeader.dart
import 'package:flutter/material.dart';
class IndexListHeader extends StatelessWidget {
final bool hasLogin;
IndexListHeader(this.hasLogin);
@override
Widget build(BuildContext context) {
if (hasLogin) {
} else {}
return Container(
padding: const EdgeInsets.all(10.0),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'热门文章',
style: TextStyle(
color: Color(0xFF434343),
fontSize: 16.0,
fontWeight: FontWeight.bold
),
),
FlatButton(
child: Text('查看更多', style: TextStyle(color: Color(0xFF757575))),
onPressed: () {
print('查看更多');
},
)
],
),
Divider(),
],
),
);
}
}
这里我们还未涉及到登陆,所以暂时先留一个口子(构造函数)在这,后面做到了登陆部分再回来修改UI。
之前我们说到在使用一些widget的时候,有些属性是必须的,不然编译器会报错,like this
当然,我们可以按住command键,点击widget,到源码中去查看一些相关属性的编写和类型
ListView.builder
毫无疑问,这里我们使用ListView 布局,因为考虑性能且不确定长度,这里我们不会给ListView传入children而是直接只用它的构造函数 builder,而且这样的长列表对于非可视区域部分的cell还会做相应的资源回收。
- lib/pages/indexPage.dart
_renderList(context , index){
if(index == 0){
return IndexListHeader(false);
}
return IndexListCell(cellInfo: _listData[index-1]);
}
@override
Widget build(BuildContext context) {
print(_listData.length);
if (_listData.length == 0) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: _listData.length+1,//添加一个header
itemBuilder: (context,index)=> _renderList(context,index),
);
}
}
注意上面我们给ListView传递的长度是length+1,因为我们要塞列表的头部~
同样,我们也处理了数据未请求到的时候loading的展示
至此,我们的app已经有点样子出来了有么有
总结
如上,我们基本首页已经有了雏形,至此,你应该学会
- ListView的使用
- 组件的拆分、细化和组合
- VsCode的一些使用技巧