Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

首页List UI编写 #22

Open
Nealyang opened this issue Mar 19, 2019 · 0 comments
Open

首页List UI编写 #22

Nealyang opened this issue Mar 19, 2019 · 0 comments
Labels

Comments

@Nealyang
Copy link
Owner

介绍

这一章节中,我们将完成首页List部分的编写

该章节后,咱们的list界面应该长这个样子
img

cell 结构分析

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上,可以看到他的属性,以及这个属性的值类型

de

  • lib/widgets/goodAndCommentCell.dart
    code
    这里点赞和评论的cell很简单,其实仔细分析可以看到,点赞和评论也是同一个组件才对,不应该写两遍。这里我就不优化,之所以是截图,希望大家可以自己动手,发挥自己的聪明才智,编写这一个UI,或者说,优化我上面的代码~

goodAndCommentCell 代码链接

  • 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

worning

当然,我们可以按住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的一些使用技巧
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant