preface

In the last chapter, I realized the classification of moke JSON data display home page. Today, I wrote an article list component to render the article from digging gold. Due to the short time, there are still some problems in style adjustment, and there will be time for reconstruction later

The main steps are as follows

  • Build small cards for individual articles
  • Article list component
  • Home page display

Small card components for individual articles

Here I mainly show the page data, but the style construction is still a little rough

The following uses Flex and Expanded to implement the Flex layout THAT I’m familiar with

Flex

The Flex component can arrange child components horizontally or vertically. If you know the main axis, using Row or Column is convenient. Because Row and Column inherit from Flex and have basically the same parameters, you can use Row or Column almost anywhere Flex can be used. Flex is powerful on its own, but it can also work with Expanded components for flexible layouts. Let’s discuss Flex and elastic layout related properties only.

Expanded

You can scale up the space occupied by Row, Column, and Flex child components.

import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_application/config/theme.dart'; class ArticleSingle extends StatelessWidget { final ArticleModel articleModel; ArticleSingle(this.articleModel); @override Widget build(BuildContext context) { List<Widget> getTagList() { List<Widget> tagList = []; articleModel.tags.forEach((element) { tagList.add(RawChip( label: Text(element), labelStyle: TextStyle(fontSize: 10.0), the padding: EdgeInsets. All (0),)); }); return tagList; } return Container( padding: EdgeInsets.fromLTRB(0, 12, 0, 12), alignment: Alignment.centerLeft, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ new Text( articleModel.title, style: TextStyle(fontWeight: fontweight.w600, fontSize: 16.0), Flex(direction: Axis. Horizontal, children: [ Expanded( flex: 2, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [New Text(articlemodel.author, style: TextStyle(fontWeight: fontweight.w300, fontSize: 12.0)), SizedBox(width: GetTagList ()],), new Text(articleModel.content, style: TextStyle(fontSize: 14.0,), maxLines: 2, overflow: 1), getTagList(),), new Text(articlemodel.content, style: TextStyle(fontSize: 14.0,), maxLines: 2, overflow: 2 TextOverflow ellipsis,), / / the number of the Row (crossAxisAlignment: crossAxisAlignment. Start, mainAxisAlignment: MainAxisAlignment.start, children: [ Icon(CupertinoIcons.eye,size: 14,color: secondColor,), SizedBox(width: 5), Text(articleModel.viewCount.toString()), SizedBox(width: 10), Icon(Icons.thumb_up,size: 14,color: secondColor,), SizedBox(width: 5), Text(articleModel.diggCount.toString()), SizedBox(width: 10), Icon(Icons.comment,size: 14,color: secondColor,), SizedBox(width: 5), Text(articleModel.commentCount.toString()) ], ) ], )), Expanded( flex: 1, child: Column( children: [ Image.network( articleModel.imgUrl, width: 80, height: 80, ), ], )) ], ) ], ), ); } } class ArticleModel { final String title; // Final String author; // Author final String content; // Final String imgUrl; // Final int viewCount; Final int diggCount; Final int commentCount; // Final int commentCount; Final List<String> tags; // Final double ctime; ArticleModel( {this.title = '', this.author = '', this.content = '', this.imgUrl = '', this.viewCount = 0, this.diggCount = 0, this.commentCount = 0, this.tags = const [], this.ctime = 0}); }Copy the code

Article list component

ListView

ListView implements scrollable components with the following main parameters:

  • itemExtent: If this parameter is not set tonull, will forcechildrenThe “length” of isitemExtentThe value of the; The “length” here refers to the length of the child component in the scrolling direction, that is, if the scrolling direction is vertical, thenitemExtentRepresents the height of the child component; If the rolling direction is horizontal, thenitemExtentRepresents the width of the child component. inListView, specifyitemExtentIt is more efficient than letting the child components determine their own length because of the specificationitemExtentAfter that, the scrolling system can know the length of the list in advance without having to recalculate it each time a child component is built, especially if the scrolling position changes frequently (scrolling systems need to calculate the list height frequently).
  • shrinkWrap: This property indicates whether it is set based on the total length of the child componentsListViewThe default value isfalse. By default,ListViewWill take up as much space as possible in the scrolling direction. whenListViewIn a container with no boundary (rolling direction),shrinkWrapMust betrue.
  • addAutomaticKeepAlives: This property indicates whether the list item (child component) is wrapped inAutomaticKeepAliveThe component; Typically, in a lazy-loaded list, if the list items are wrapped inAutomaticKeepAliveWhen the list item slides out of the viewport, it is not GC, it is usedKeepAliveNotificationTo preserve its state. If the list item maintains it itselfKeepAliveState, then this parameter must be set tofalse.
  • addRepaintBoundaries: This property indicates whether the list item (child component) is wrapped inRepaintBoundaryComponent. Wraps a list item around a scrollable component as it scrollsRepaintBoundaryList item redraw can be avoided, but not added when the overhead of list item redraw is very small (such as a color block, or a short text)RepaintBoundaryIt’s more efficient. andaddAutomaticKeepAliveSame if the list item itself maintains itKeepAliveState, then this parameter must be set tofalse.

The code is as follows:

import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'article_single.dart'; Class ArticleList extends StatefulWidget {final List<ArticleModel> ArticleList; ArticleList({this.articleList = const []}); _ArticleState createState() => _ArticleState(); } class _ArticleState extends State<ArticleList> { ScrollController _controller = new ScrollController(); //ListView Controller List<Widget> buildArticle() {List<Widget> articles = []; widget.articleList.forEach((element) { articles.add(new ArticleSingle(element)); }); return articles; } @override Widget build(BuildContext context) { return new Container( child: widget.articleList.length == 0 ? new Center( child: Text('No Data'), ) : ListView( controller: _controller, children: buildArticle(), ) ); }}Copy the code

Home page

In this case, the main thing is to repackage the REQUIRED JSON data and render the page

The following code

import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_application/config/theme.dart'; import 'package:flutter_application/pages/common/search/common_search.dart'; import 'package:flutter_application/pages/components/article_list.dart'; import 'package:flutter_application/pages/components/article_single.dart'; class IndexPage extends StatefulWidget { _IndexState createState() => _IndexState(); } class _IndexState extends State<IndexPage> with TickerProviderStateMixin { late TabController _tabController; var _tabList = []; var _articleList = []; List<ArticleModel> _articleModels = []; @override void initState() { // TODO: implement initState super.initState(); } @override Widget build(BuildContext context) { // List<ArticleModel> _articleModels = []; / / classification rootBundle. LoadString (" assets/json/categories. Json "), then ((value) = > {. _tabList = json decode (value)}); _tabController = TabController( length: _tabList.length, vsync: this); // Categories have a length of 8. My side moke the json data directly _tabController. AddListener (() {switch (_tabController. Index) {/ / TODO access tabBarView}}); rootBundle .loadString("assets/json/articles.json") .then((value) => {_articleList = json.decode(value)}); _articleModels = []; _articleList.forEach((element) { var articleInfo = element['article_info']; List<String> tags = []; var curTags = []; curTags = element['tags']; curTags.forEach((e) { tags.add(e['tag_name']); }); var articleModel = new ArticleModel( title: articleInfo['title'], author: element['author_user_info']['user_name'], content: articleInfo['brief_content'], imgUrl: articleInfo['cover_image'], viewCount: articleInfo['view_count'], diggCount: articleInfo['digg_count'], commentCount: articleInfo['comment_count'], ctime: double.parse(articleInfo['ctime']), tags: tags); _articleModels.add(articleModel); }); Return new Container(// color: color (0xffF5F6f7), // Background color padding: EdgeInsets. FromLTRB (12, 6, 12, 0), child: New Column(children: [CommonSearch(hint: 'search ', icon: icon (CupertinoIcons. Search), onTap: () => {// TODO access search},), Expanded(Child: controller: TabBar(Controller: _tabController, isScrollable: LabelColor: primaryColor, unselectedLabelColor: firstColor, labelStyle: TextStyle(fontSize: 12.0), tabs: _tabList .map((e) => Tab( text: e['category_name'], )) .toList()), body: new TabBarView( controller: _tabController, children: _tabList.map((e) { return Container( alignment: Alignment.center, child: ArticleList( articleList: _articleModels, )); }).toList(), ), )), ], ), ); }}Copy the code

The renderings are as follows