Lists are the most common form of application. The ListView component is provided in the Flutter to implement lists. This article will use the ListView to implement an illustrated list.

Interface layout analysis

The list of implementations for this article is shown in the figure above. Once we get the interface design draft, the first thing we do in UI development is think about the interface elements and layout. In the case of the above interface, the actual interface elements include lists and list elements. The list element is the key. The list element includes an image on the left, a title on the right of the image, and the number of views (with a front icon). The layout of the list elements is shown in the following figure.Vertically, the layout height of the list elements is determined by the image. The height of the icon and the number of views is fixed, and the remaining space is taken up by the title. Considering the beauty of the interface, the maximum number of lines of the title is 2, and the part beyond the use of… Alternative. Horizontally, the image width is fixed to maintain a fixed aspect ratio. After the width of the image is fixed, the remaining space (except for the spacing) is the space of the title. Based on the above description, a general layout can be obtained:

  • The entire list element is wrapped in a Container to set the margins around it.
  • In landscape, use the Row component for landscape layout.
  • The Column component is used in the vertical layout of the right area.
  • The browse count icon and text on the right also need to be horizontally laid out using Row.
  • In order to keep the spacing between the left picture and the right area, use Container to wrap the right side uniformly, so as to control the spacing.

Introduction of ListView

The ListView is used to generate lists, usually using the Builder static method to build a list with key parameters:

  • ItemCount: The number of list elements.
  • ItemBuilder: A list element builder that returns the corresponding list element component by specifying the subscript of the element.

If you want to use a list of separated components, you can also build the list using the listView. seperate method, which has an additional seperateBuilder parameter that returns the separated components corresponding to the list elements.

Therefore, the key to lists is the implementation of the list element component.

coded

Again, we implemented the list in Dynamic.dart, based on the previous project. Dart is used to build list elements, and dynamic_mock_data. dart is used to simulate background interface data. Dynamic_mock_data is simple and returns paging data with a static list method, as shown below:

class DynamicMockData {
  static List<Map<String.Object>> list(int page, int size) {
    return List<Map<String.Object>>.generate(size, (index) {
      return {
        'title': 'title${index + (page - 1) * size + 1}: This is a list title, maximum two lines, multiple parts will be cut '.'imageUrl':
            'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3331308357, & FM = 26 & gp = 0. 177638268 JPG'.'viewCount': 180}; }); }}Copy the code

Page and size are used to simulate the paging situation to facilitate the subsequent implementation of the pull up and pull down refresh. Note the use of the generate method of List to build an array. This method is used to build an array of a specified size. You can build an array element with index subscript through the callback function with index input.

The implementation code for dynamic_item.dart is as follows:

import 'package:flutter/material.dart';

class DynamicItem extends StatelessWidget {
  final String title;
  final String imageUrl;
  final int viewCount;
  static const double ITEM_HEIGHT = 100;
  static const double TITLE_HEIGHT = 80;
  static const double MARGIN_SIZE = 10;
  const DynamicItem(this.title, this.imageUrl, this.viewCount, {Key key})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.all(MARGIN_SIZE),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          _imageWrapper(this.imageUrl),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                _titleWrapper(context, this.title),
                _viewCountWrapper(this.viewCount.toString()),
              ],
            ),
          )
        ],
      ),
    );
  }

  Widget _titleWrapper(BuildContext context, String text) {
    return Container(
      height: TITLE_HEIGHT,
      margin: EdgeInsets.fromLTRB(MARGIN_SIZE, 0.0.0),
      child: Text(
        this.title,
        maxLines: 2,
        overflow: TextOverflow.ellipsis,
        style: Theme.of(context).textTheme.headline6,
      ),
    );
  }

  Widget _viewCountWrapper(String text) {
    return Container(
      margin: EdgeInsets.fromLTRB(MARGIN_SIZE, 0.0.0),
      height: ITEM_HEIGHT - TITLE_HEIGHT,
      child: Row(children: [
        Icon(
          Icons.remove_red_eye_outlined,
          size: 14.0,
          color: Colors.grey,
        ),
        SizedBox(width: 5),
        Text(
          this.viewCount.toString(),
          style: TextStyle(color: Colors.grey, fontSize: 14.0),),),); } Widget _imageWrapper(String imageUrl) {
    return SizedBox(
      width: 150, height: ITEM_HEIGHT, child: Image.network(imageUrl), ); }}Copy the code

First, we define the title, imageUrl, and viewCount member properties of the final type. The constraint of using final is that other classes can directly access it, but cannot modify it. These properties can also be defined as private members if they themselves are not externally accessible.

The second is to use constructors to initialize member attributes directly. This is Dart’s shorthand for automatically initializing a member without the body of the function, as long as the parameters are passed in the same order. This is usually used for final-modified member attributes.

The entire interface is built in the Build method. Note that Expanded is used to wrap the right area. Expanded is a component that automatically occupies the remaining space in the horizontal layout. If you do not have this package, the content on the right side will be too wide to display and alarm will be raised.

Images, titles, and views are all captured by a separate build component method, both to reduce the UI nesting level and to remove the separate build method to improve reuse if the same components are available later. The key Settings are explained below:

  • CrossAxisAlignment: crossAxisAlignment. Start: This element for marking Row alignment components aligns from the start position in column direction (that is, vertical right alignment and image top alignment).
  • Margin of Container: This parameter is used to set the left, right, and top margins of the Container. If the four directions are the same, use the EdgeInsets. All method. If not, use EdgeInsets. FromLTRB to set the spacing in each of the four directions separately.
  • A SizedBox component is used in the browse numbers component, which has nothing to do with it except to put some space between the icon and the browse numbers and improve the look.

Components used

In addition to the ListView, this section covers the following components:

  • Text: A Text component, equivalent to label. In addition to text content, you can use style to set text styles. The maxLines constraint is used for the title, and the overflow constraint is used for the post-overflow processing.
  • Image: Image component, which uses Image.net Work to load images from the network. This Image.net Work is very rudimentary and will be replaced later with the cached_image_network plug-in.
  • Icon: Icon component. There are many font Icons built into the Flutter, which can be used for most scenarios. Icons can be found using the Icon name defined by the Icons class.
  • Row: Row layout component. Children are arranged in the same Row from left to right.
  • Column: The children components are arranged in the same Column from top to bottom.

The above components are basic for this example, and more Settings can be found by viewing the source code in the IDE or by reading the official documentation.

Conclusion: This article describes building lists using listViews, focusing on how the list elements are laid out, the specific layout components, and the implementation methods. The key work of the interface implementation is actually the split of the layout child elements. The rest can be implemented in a variety of ways, depending on your preference. However, care needs to be taken to avoid too much nesting resulting in less readable code and to improve the reusability of UI components.