Flutter 構建完整應用手冊-列表

基礎列表

顯示數據列表是移動應用程序的基本模式。 Flutter包含ListView部件,使列表變得垂手可得!html

建立一個ListView

使用標準的ListView構造函數很是適合僅包含少許項目的列表。 咱們還將使用內置的ListTile部件來爲咱們的項目提供一個可視結構。java

new ListView(
  children: <Widget>[
    new ListTile(
      leading: new Icon(Icons.map),
      title: new Text('Map'),
    ),
    new ListTile(
      leading: new Icon(Icons.photo_album),
      title: new Text('Album'),
    ),
    new ListTile(
      leading: new Icon(Icons.phone),
      title: new Text('Phone'),
    ),
  ],
);

完整例子

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'Basic List';
    
    return new MaterialApp(
      title: title,
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
        ),
        body: new ListView(
          children: <Widget>[
            new ListTile(
              leading: new Icon(Icons.map),
              title: new Text('Map'),
            ),
            new ListTile(
              leading: new Icon(Icons.photo_album),
              title: new Text('Album'),
            ),
            new ListTile(
              leading: new Icon(Icons.phone),
              title: new Text('Phone'),
            ),
          ],
        ),
      ),
    );
  }
}

建立一個水平列表

有時,您可能想要建立一個水平滾動而不是垂直滾動的列表。 ListView部件支持開箱即用的水平列表。數據庫

咱們將使用標準的ListView構造函數,經過橫向scrollDirection,這將覆蓋默認的垂直方向。app

new ListView(
  // This next line does the trick.
  scrollDirection: Axis.horizontal,
  children: <Widget>[
    new Container(
      width: 160.0,
      color: Colors.red,
    ),
    new Container(
      width: 160.0,
      color: Colors.blue,
    ),
    new Container(
      width: 160.0,
      color: Colors.green,
    ),
    new Container(
      width: 160.0,
      color: Colors.yellow,
    ),
    new Container(
      width: 160.0,
      color: Colors.orange,
    ),
  ],
)

完整例子

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'Horizontal List';

    return new MaterialApp(
      title: title,
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
        ),
        body: new Container(
          margin: new EdgeInsets.symmetric(vertical: 20.0),
          height: 200.0,
          child: new ListView(
            scrollDirection: Axis.horizontal,
            children: <Widget>[
              new Container(
                width: 160.0,
                color: Colors.red,
              ),
              new Container(
                width: 160.0,
                color: Colors.blue,
              ),
              new Container(
                width: 160.0,
                color: Colors.green,
              ),
              new Container(
                width: 160.0,
                color: Colors.yellow,
              ),
              new Container(
                width: 160.0,
                color: Colors.orange,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

使用長列表

標準的ListView構造函數適用於小列表。 爲了處理包含大量項目的列表,最好使用ListView.builder構造函數。less

雖然默認的ListView構造函數要求咱們一次建立全部條目,但ListView.builder構造函數將在滾動到屏幕上時建立條目。ide

1.建立一個數據源

首先,咱們須要一個數據源來處理。 例如,您的數據源多是消息列表,搜索結果或商店中的產品。 大多數狀況下,這些數據未來自互聯網或數據庫。函數

在這個例子中,咱們將使用List.generate構造函數生成一個10000個字符串的列表。ui

final items = new List<String>.generate(10000, (i) => "Item $i");

2.將數據源轉換成部件

爲了顯示咱們的字符串列表,咱們須要將每一個字符串呈現爲一個部件!this

這是ListView.builder將發揮做用的地方。 在咱們的例子中,咱們將在它本身的行上顯示每一個字符串。spa

new ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return new ListTile(
      title: new Text('${items[index]}'),
    );
  },
);

完整例子

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp(
    items: new List<String>.generate(10000, (i) => "Item $i"),
  ));
}

class MyApp extends StatelessWidget {
  final List<String> items;

  MyApp({Key key, @required this.items}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final title = 'Long List';

    return new MaterialApp(
      title: title,
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
        ),
        body: new ListView.builder(
          itemCount: items.length,
          itemBuilder: (context, index) {
            return new ListTile(
              title: new Text('${items[index]}'),
            );
          },
        ),
      ),
    );
  }
}

建立一個包含不一樣類型條目的列表

咱們常常須要建立顯示不一樣類型內容的列表。 例如,咱們可能正在製做一個列表,其中顯示一個標題,後面跟着與該標題相關的幾個項目,後面是另外一個標題,等等。

咱們如何用Flutter建立這樣一個結構?

路線

  1. 使用不一樣類型的條目建立數據源
  2. 將數據源轉換爲部件列表

1.使用不一樣類型的條目建立數據源

項目類型

爲了在列表中表示不一樣類型的項目,咱們須要爲每種類型的項目定義一個類別。

在這個例子中,咱們將在一個應用程序上顯示一個標題,後面跟着五條消息。 所以,咱們將建立三個類:ListItemHeadingItemMessageItem

// The base class for the different types of items the List can contain
abstract class ListItem {}

// A ListItem that contains data to display a heading
class HeadingItem implements ListItem {
  final String heading;

  HeadingItem(this.heading);
}

// A ListItem that contains data to display a message
class MessageItem implements ListItem {
  final String sender;
  final String body;

  MessageItem(this.sender, this.body);
}

建立項目列表
大多數狀況下,咱們會從互聯網或本地數據庫獲取數據,並將這些數據轉換爲項目列表。

對於這個例子,咱們將生成一個項目列表來處理。 該列表將包含一個標題,後跟五個消息。 沖洗,重複。

final items = new List<ListItem>.generate(
  1200,
  (i) => i % 6 == 0
      ? new HeadingItem("Heading $i")
      : new MessageItem("Sender $i", "Message body $i"),
);

2.將數據源轉換爲部件列表

爲了處理將每一個項目轉換爲部件,咱們將使用ListView.builder構造函數。

通常來講,咱們但願提供一個builder函數來檢查咱們正在處理的項目類型,並返回該類型項目的相應部件。

在這個例子中,使用is關鍵字來檢查咱們正在處理的項目類型可能很是方便。 速度很快,並會自動將每一個項目轉換爲適當的類型。 可是,若是您更喜歡另外一種模式,則有不一樣的方法能夠解決此問題!

new ListView.builder(
  // Let the ListView know how many items it needs to build
  itemCount: items.length,
  // Provide a builder function. This is where the magic happens! We'll
  // convert each item into a Widget based on the type of item it is.
  itemBuilder: (context, index) {
    final item = items[index];

    if (item is HeadingItem) {
      return new ListTile(
        title: new Text(
          item.heading,
          style: Theme.of(context).textTheme.headline,
        ),
      );
    } else if (item is MessageItem) {
      return new ListTile(
        title: new Text(item.sender),
        subtitle: new Text(item.body),
      );
    }
  },
);

完整例子

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp(
    items: new List<ListItem>.generate(
      1000,
      (i) => i % 6 == 0
          ? new HeadingItem("Heading $i")
          : new MessageItem("Sender $i", "Message body $i"),
    ),
  ));
}

class MyApp extends StatelessWidget {
  final List<ListItem> items;

  MyApp({Key key, @required this.items}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final title = 'Mixed List';

    return new MaterialApp(
      title: title,
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
        ),
        body: new ListView.builder(
          // Let the ListView know how many items it needs to build
          itemCount: items.length,
          // Provide a builder function. This is where the magic happens! We'll
          // convert each item into a Widget based on the type of item it is.
          itemBuilder: (context, index) {
            final item = items[index];

            if (item is HeadingItem) {
              return new ListTile(
                title: new Text(
                  item.heading,
                  style: Theme.of(context).textTheme.headline,
                ),
              );
            } else if (item is MessageItem) {
              return new ListTile(
                title: new Text(item.sender),
                subtitle: new Text(item.body),
              );
            }
          },
        ),
      ),
    );
  }
}

// The base class for the different types of items the List can contain
abstract class ListItem {}

// A ListItem that contains data to display a heading
class HeadingItem implements ListItem {
  final String heading;

  HeadingItem(this.heading);
}

// A ListItem that contains data to display a message
class MessageItem implements ListItem {
  final String sender;
  final String body;

  MessageItem(this.sender, this.body);
}

建立一個網格列表

在某些狀況下,您可能但願將項目顯示爲網格,而不是顯示下一個項目的普通列表。 對於這個任務,咱們將使用GridView部件。

開始使用網格的最簡單方法是使用GridView.count構造函數,由於它容許咱們指定咱們想要的行數或列數。

在這個例子中,咱們將生成一個100個部件的列表,在列表中顯示它們的索引。 這將幫助咱們可視化GridView的工做原理。

new GridView.count(
  // Create a grid with 2 columns. If you change the scrollDirection to 
  // horizontal, this would produce 2 rows.
  crossAxisCount: 2,
  // Generate 100 Widgets that display their index in the List
  children: new List.generate(100, (index) {
    return new Center(
      child: new Text(
        'Item $index',
        style: Theme.of(context).textTheme.headline,
      ),
    );
  }),
);

完整例子

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'Grid List';

    return new MaterialApp(
      title: title,
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
        ),
        body: new GridView.count(
          // Create a grid with 2 columns. If you change the scrollDirection to
          // horizontal, this would produce 2 rows.
          crossAxisCount: 2,
          // Generate 100 Widgets that display their index in the List
          children: new List.generate(100, (index) {
            return new Center(
              child: new Text(
                'Item $index',
                style: Theme.of(context).textTheme.headline,
              ),
            );
          }),
        ),
      ),
    );
  }
}
相關文章
相關標籤/搜索