В прошлой теме был рассмотрен пример создания простейшего списка ListView:
import 'package:flutter/material.dart'; const double textSize = 22; void main() { runApp(MaterialApp( home: Scaffold( body: ListView( padding: const EdgeInsets.all(8), children:[ Text("Tom", style: TextStyle(fontSize: textSize)), Text("Alice", style: TextStyle(fontSize: textSize)), Text("Bob", style: TextStyle(fontSize: textSize)), Text("Sam", style: TextStyle(fontSize: textSize)), Text("Kate", style: TextStyle(fontSize: textSize)), ], ), appBar: AppBar(title: Text("METANIT.COM")),) )); }
Конструктор по умолчанию класса List, который использован в примере выше, подходит для создания списков с небольшим количеством элементов, поскольку в данном случае нам приходится настраивать каждый элемент списка. Однако даже в примере выше с небольшим количеством элементов мы видим, что все элементы Text отличаются только текстом. И было бы неплохо, если бы мы просто могли бы один раз определить виджет Text и каким-то образом передать ему все необходимые строки для отображения. И в этом случае мы можем использовать другой конструктр класса ListView - ListView.builder().
ListView.builder() в качестве параметра itemBuilder принимает объект IndexedWidgetBuilder, который создает элементы списка. Этот конструктор более удобен для создания больших списков.
Например, переделаем предыдущий пример с применением конструктора ListView.builder():
import 'package:flutter/material.dart'; const List<String> users = <String>["Tom", "Alice", "Bob", "Sam", "Kate"]; void main() { runApp(MaterialApp( home: Scaffold( body: ListView.builder( padding: const EdgeInsets.all(8), itemCount: users.length, itemBuilder: (BuildContext context, int index) { return Text(users[index], style: TextStyle(fontSize: 22)); } ), appBar: AppBar(title: Text("METANIT.COM")),) )); }
Объект IndexedWidgetBuilder
, который передается параметру itemBuilder
, по сути представляет функцию
Widget Function(BuildContext context, int index), которая получает контекст виджета, а также индекс и
возвращает созданный виджет. Что передается в качестве индекса?
Здесь для ListView также устанавливается количество элементов с помощью параметра itemCount
-
оно равно количеству объектов в списке users
: itemCount: users.length
(в данном случае 5 элементов). В итоге itemBuilder будет
последовательно перебирать числа от 0 до users.length
, которые передаются в параметр index
,
и таким образом для каждого передаваемого индекса создавать виджет Text и передавать в виджет значение users[index]
.
Фактически по своему действию данную функцию можно сравнивать с циклом, в котором для каждого индекса создается свой виджет Text. В итоге мы получим следующий список ListView:
При этом мы можем использовать несколько источников для создания ListView:
import 'package:flutter/material.dart'; const List<String> users = <String>["Tom", "Alice", "Bob", "Sam", "Kate"]; const List<String> companies = <String>["Microsoft", "Google", "Apple", "JetBrains", "Amazon"]; void main() { runApp(MaterialApp( home: Scaffold( body: ListView.builder( padding: const EdgeInsets.all(8), itemCount: users.length, itemBuilder: (BuildContext context, int index) { return Container( padding: EdgeInsets.symmetric(vertical: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(users[index], style: TextStyle(fontSize: 22)), Text("Место работы: ${companies[index]}", style: TextStyle(fontSize: 18)) ], ) ); } ), appBar: AppBar(title: Text("METANIT.COM")),) )); }
В данном случае есть два списка List - условно один для пользователей, а другой для компаний. При создании ListView
функция itemBuilder
для каждого элемента ListView генерирует виджет Container, который включает
два виджета Text: один выводит имя пользователя, а другой - название компании.
То есть в данном случае функция из itemBuilder
сначала выбирает первый элемент из списка users и первый
элемент из списка companies, потому выбирает по второму элементу из этих списков и так далее.
Правда, здесь надо учитывать, что в обоих списках должно быть не меньше элементов, чем указано для параметра itemCount
виджета ListView.
Естественно мы можем передавать в список и более сложные объекты:
import 'package:flutter/material.dart'; class User{ String name; int age; User(this.name, this.age); } final List<User> users = <User>[User("Tom", 36), User("Alice", 31), User("Bob", 41), User("Sam", 28)]; void main() { runApp(MaterialApp( home: Scaffold( body: ListView.builder( padding: const EdgeInsets.all(8), itemCount: users.length, itemBuilder: (BuildContext context, int index) { return Container( padding: EdgeInsets.symmetric(vertical: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(users[index].name, style: TextStyle(fontSize: 22)), Text("Возраст: ${users[index].age}", style: TextStyle(fontSize: 18)) ], ) ); } ), appBar: AppBar(title: Text("METANIT.COM")),) )); }
В данном случае для каждого объекта User в списке users создается отдельный элемент в ListView: