🐕

【Flutter】リスト・一覧レイアウトを作る(ListTile)

2022/10/17に公開

メモ的な感じなのでサクッと見てもらえれば🙇‍♂️
公式記事を大いに引用、意訳

ListTile Widgetで作れるもの(Flutter提供のリストのレイアウト)

              ListTile(
                title: const Text('Cardで囲んでない時'),
                tileColor: Colors.red,
              ),
              ListTile(
                onTap: (){
                  print("tapped");
                },
                leading: FlutterLogo(size: 43,),
                title: Text('title Text'),
                trailing: Icon(Icons.more_vert),
              ),
              ListTile(
                title: Text('One-line with trailing widget'),
                trailing: GestureDetector(
                    behavior: HitTestBehavior.translucent,
                    onTap: (){
                      print("tapped");
                    },
                    child: Icon(Icons.more_vert)
                ),
              ),

!()[https://github.com/tomokio123/zenn-articles/blob/main/Simulator Screen Shot - iPhone SE (2nd generation) - 2022-10-16 at 22.42.50.png?raw=true]

主なプロパティ

  • title:真ん中の核となる文章
  • tileColor:タイルの背景色を決めれる
  • leading:左にあり、プロフィール画像とかサムネみたいな役割。
  • trailing:ケツにある点々みたいなやつ
  • onTap:タップした時にそれっぽい影とか出る。{}中に処理を書ける。

だが往々にしてこんな雑なタイルを作るのにも不満もあるし、使えるプロパティが多すぎるので割愛

自分でカスタムしたリストを作る

class CustomListItem extends StatelessWidget {
  const CustomListItem({
    super.key,
    required this.thumbnail,
    required this.title,
    required this.user,
    required this.viewCount,
  });

  final Widget thumbnail;
  final String title;
  final String user;
  final int viewCount;

  
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 5.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Expanded(
            flex: 2,
            child: thumbnail,
          ),
          Expanded(
            flex: 3,
            child: _VideoDescription(
              title: title,
              user: user,
              viewCount: viewCount,
            ),
          ),
          const Icon(
            Icons.more_vert,
            size: 16.0,
          ),
        ],
      ),
    );
  }
}
class _VideoDescription extends StatelessWidget {
  const _VideoDescription({
    required this.title,
    required this.user,
    required this.viewCount,
  });

  final String title;
  final String user;
  final int viewCount;

  
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(5.0, 0.0, 0.0, 0.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text(
            title,
            style: const TextStyle(
              fontWeight: FontWeight.w500,
              fontSize: 14.0,
            ),
          ),
          const Padding(padding: EdgeInsets.symmetric(vertical: 2.0)),
          Text(
            user,
            style: const TextStyle(fontSize: 10.0),
          ),
          const Padding(padding: EdgeInsets.symmetric(vertical: 1.0)),
          Text(
            '$viewCount views',
            style: const TextStyle(fontSize: 10.0),
          ),
        ],
      ),
    );
  }
}

class MyStatelessWidget extends StatelessWidget {
  const MyStatelessWidget({super.key});

  
  Widget build(BuildContext context) {
    return ListView(
      padding: const EdgeInsets.all(8.0),
      itemExtent: 106.0,
      children: <CustomListItem>[
        //自分で作ったWidgetをListViewでListにしろってこと
        CustomListItem(
          user: 'Flutter',
          viewCount: 999000,
          thumbnail: Container(
            decoration: const BoxDecoration(color: Colors.blue),
          ),
          title: 'The Flutter YouTube Channel',
        ),
        CustomListItem(
          user: 'Dash',
          viewCount: 884000,
          thumbnail: Container(
            decoration: const BoxDecoration(color: Colors.yellow),
          ),
          title: 'Announcing Flutter 1.0',
        ),
      ],
    );
  }
}

要は

「じぶんでColumnやRowを使ってカスタムWidget作れ。ListViewでListにするといいぞ」ってこと

ListView Widgetとは

  • スクロールできる「リストに適した」Culumnみたいなもん
  • リストに使えるいろんなプロパティがある
  • 少数の子を持つリストに適してる
ListView(
  padding: const EdgeInsets.all(8),
  children: <Widget>[
    Container(
      height: 50,
      color: Colors.amber[600],
      child: const Center(child: Text('Entry A')),
    ),
    Container(
      height: 50,
      color: Colors.amber[500],
      child: const Center(child: Text('Entry B')),
    ),
    Container(
      height: 50,
      color: Colors.amber[100],
      child: const Center(child: Text('Entry C')),
    ),
  ],
)

ListView.builder との違いについて

  • itemCount: itemCount(entries.length),としてbuilderに渡すリストの数を持たせる。
  • entries.length(配列の要素の数)を読み取り適当な数にできるから比較的子要素の多いものにも対応できる
final List<String> entries = <String>['A', 'B', 'C'];
final List<int> colorCodes = <int>[600, 500, 100];

ListView.builder(
  padding: const EdgeInsets.all(8),
  itemCount: entries.length,
  itemBuilder: (BuildContext context, int index) {
    return Container(
      height: 50,
      color: Colors.amber[colorCodes[index]],
      child: Center(child: Text('Entry ${entries[index]}')),
    );
  }
);

以上です。

GitHubで編集を提案

Discussion