美文网首页让前端飞Flutter中文社区闲话Flutter和Dart
Flutter 实战:撸半个知乎日报~ThemeListPage

Flutter 实战:撸半个知乎日报~ThemeListPage

作者: jzhu085 | 来源:发表于2018-06-23 22:50 被阅读316次

    fir_release_Android包下载地址

    GIF

    themelist.gif

    UI如图

    themelisgpage.png

    需求分析:

    • 整体滑动
    • 背景,标题,顶部导航栏联动,渐隐渐出动画
    • 装载数据

    UI拆解并实现:

    • CustomScrollView: 负责整体滑动

    var content = new CustomScrollView(
          //没有铺满也可以滑动
          physics: AlwaysScrollableScrollPhysics(),
          ........
          ........  
        )
    
    • SliverAppBar:背景,标题,顶部导航栏联动,渐隐渐出动画

    new SliverAppBar(
              expandedHeight: _appBarHeight,
              pinned: _appBarBehavior == AppBarBehavior.pinned,
              floating: _appBarBehavior == AppBarBehavior.floating ||
                  _appBarBehavior == AppBarBehavior.snapping,
              snap: _appBarBehavior == AppBarBehavior.snapping,
              flexibleSpace: new FlexibleSpaceBar(
                //标题
                title: Text('$_title'),
                //背景图
                background: new FadeInImage.memoryNetwork(
                    placeholder: kTransparentImage,
                    image: _barBg,
                    fit: BoxFit.fitHeight), 
              ),
            )
    
    
    • SliverList:

    拆解1:主编一栏
    Widget _buildEditor() {
       
       //横向控件的集合
       List<Widget> editors = [];
       
       //主编
       Widget lableWidget = new Padding(
         padding: const EdgeInsets.only(right: 12.0),
         child: new Text(
           '主编',
           style: new TextStyle(fontSize: 14.0),
         ),
       );
    
       editors.add(lableWidget);
       
       //循环加入主编的头像
       for (ThemeListEditorsModel model in _editorDatas) {
         Widget headView = new InkWell(
           onTap: () {
             RouteUtil.route2Web(context, model.name, model.url);
           },
           child: new Padding(
               padding: const EdgeInsets.only(
                   left: 6.0, right: 6.0, top: 12.0, bottom: 12.0),
               child: new CircleAvatar(
                 radius: 12.0,
                 backgroundImage: new NetworkImage(model.avatar),
               )),
         );
         editors.add(headView);
       }
    
       //组装
       return new Column(
         children: <Widget>[
           new Padding(
             padding: const EdgeInsets.only(left: 12.0, right: 12.0),
             child: new Row(
               children: editors,
             ),
           ),
           CommonDivider.buildDivider(),
         ],
       );
     }
    
    拆解2:基础item
    Widget _buildNormalItem(ThemeListStoriesModel item) {
       final List images = item.images;
       final String title = item.title;
       final int id = item.id;
       bool hasImage = (null != images && images.isNotEmpty);
    
       if (hasImage) {
         return new InkWell(
             onTap: () {
               RouteUtil.route2Detail(context, '$id');
             },
             child: new Padding(
                 padding: const EdgeInsets.only(left: 12.0, right: 12.0),
                 child: new SizedBox(
                   height: Constant.normalItemHeight,
                   child: new Column(
                     children: <Widget>[
                       new Row(
                         children: <Widget>[
                           new Expanded(
                             child: new Text(
                               title,
                               style: new TextStyle(
                                   fontSize: 16.0, fontWeight: FontWeight.w300),
                             ),
                           ),
                           new Padding(
                             padding: const EdgeInsets.all(8.0),
                             child: new SizedBox(
                               height: 80.0,
                               width: 80.0,
                               child: new Image.network(images[0]),
                             ),
                           )
                         ],
                       ),
                       new Expanded(
                         child: new Align(
                           alignment: Alignment.bottomCenter,
                           child: CommonDivider.buildDivider(),
                         ),
                       ),
                     ],
                   ),
                 )));
       } else {
         return new InkWell(
             onTap: () {
               RouteUtil.route2Detail(context, '$id');
             },
             child: new Padding(
                 padding: const EdgeInsets.only(left: 12.0, right: 12.0),
                 child: new SizedBox(
                   height: Constant.normalItemHeight,
                   child: new Column(
                     children: <Widget>[
                       new Row(
                         children: <Widget>[
                           new Expanded(
                             child: new SizedBox(
                               height: Constant.normalItemHeight,
                               child: new Align(
                                 alignment: Alignment.centerLeft,
                                 child: new Text(
                                   title,
                                   style: new TextStyle(
                                       fontSize: 16.0,
                                       fontWeight: FontWeight.w300),
                                 ),
                               ),
                             ),
                           ),
                         ],
                       ),
                       new Expanded(
                         child: new Align(
                           alignment: Alignment.bottomCenter,
                           child: CommonDivider.buildDivider(),
                         ),
                       ),
                     ],
                   ),
                 )));
       }
     }
    
    拆解3:根据类型显示item
     Widget _buildNewItem(ThemeListStoriesModel item) {
       Widget widget;
    
       switch (item.itemType) {
         case ThemeListStoriesModel.itemTypeEditor:
           widget = _buildEditor();
           break;
         case ThemeListStoriesModel.itemTypeNormal:
           widget = _buildNormalItem(item);
           break;
       }
       return widget;
     }
    
    拆解4:组装
    new SliverList(
             delegate: new SliverChildListDelegate(
                 new List<Widget>.generate(_normalDatas.length, (int i) {
               return _buildNewItem(_normalDatas[i]);
             })),
           ),
    
    
    拆解5:刷新
     var _refreshIndicator = new NotificationListener(
          onNotification: _onNotification,
          child: new RefreshIndicator(
            key: _refreshIndicatorKey,
            onRefresh: _refreshData,
            child: content,
          ),
        );
    
    拆解6:加载更多
      void _scrollListener() {
        //滑到最底部刷新
        if (_scrollController.position.pixels ==
            _scrollController.position.maxScrollExtent) {
          _loadData();
        }
      }
      
    

    知乎日报Flutter版代码已经上传到我的GITHUB ZhihuDailyPurifyByFlutter

    基础学习过程中的代码都放在GITHUB Flutter_Study

    每天学一点,学到Flutter发布正式版!

    相关文章

      网友评论

        本文标题:Flutter 实战:撸半个知乎日报~ThemeListPage

        本文链接:https://www.haomeiwen.com/subject/fsidyftx.html