Хотя в качестве элементов в ListView мы можем использовать различные виджеты, например, Container или Text, но более удобно использовать специально предназначенный виджет ListTile. ListTile представляет строку фиксированной высоты, которая обычно содержит некоторый текст и иконку, хотя это необязательно.
ListTile имеет следующий конструктор:
ListTile({Key key, Widget leading, Widget title, Widget subtitle, Widget trailing, bool isThreeLine: false, bool dense, VisualDensity visualDensity, ShapeBorder shape, EdgeInsetsGeometry contentPadding, bool enabled: true, GestureTapCallback onTap, GestureLongPressCallback onLongPress, MouseCursor mouseCursor, bool selected: false, Color focusColor, Color hoverColor, FocusNode focusNode, bool autofocus: false, Color tileColor, Color selectedTileColor})
Основные параметры конструктора:
autofocus: представляет тип bool
и указывает, получит ли данный виджет фокус (при значении true
)
contentPadding: устанавливает внутренние отступы между содержимым и границами контейнера в виде
объекта EdgeInsetsGeometry
enabled: представляет тип bool
и указывает, доступен ли элемент для взаимодействия
focusColor: устанавливает цвет Color, который принимает виджет при получении фокуса
hoverColor: устанавливает цвет Color, который принимает виджет при наведении указателя мыши
isThreeLine: представляет тип bool
и указывает, будет ли элемент списка
содержать трехстрочный текст
leading: виджет, который помещается перед элементом списка
mouseCursor: форма курсора, которую получает указатель мыши при наведении на данный элемент списка. Представляет тип MouseCursor
onLongPress: функция типа GestureLongPressCallback
, которая вызывается при
долгом нажатии на данный элемент списка
onTap: функция типа GestureTapCallback
, которая вызывается при
нажатии на данный элемент списка
selected: представляет тип bool
и указывает, будет ли выделен данный
элемент списка
selectedTileColor: устанавливает цвет, который получит ListTile при выделении
subtitle: устанавливает дополнительный виджет, который располагается под основным содержимым
tileColor: устанавливает цвет ListTile, когда виджет не выделен
title: устанавливает виджет, который представляет основное содержимое ListTile
trailing: устанавливает виджет, который отображается после основного содержимого
Основное содержимое в ListTile задается с помощью параметра title, в качестве которого может выступать любой виджет, но чаще всего применяется виджет Text:
import 'package:flutter/material.dart'; final List<String> users = ["Tom", "Alice", "Sam", "Bob", "Kate"]; void main() { runApp(MaterialApp( home: Scaffold( body: ListView.separated( padding: const EdgeInsets.all(8), itemCount: users.length, separatorBuilder: (BuildContext context, int index) => Divider(), itemBuilder: (BuildContext context, int index) { return ListTile(title: Text(users[index], style:TextStyle(fontSize: 22))); } ), appBar: AppBar(title: Text("METANIT.COM")),) )); }
С помощью параметра leading можно установить виджет, который будет отображаться перед виджетом из параметра
title
. Например, отобразим перед основным содержимым иконку:
import 'package:flutter/material.dart'; final List<String> users = ["Tom", "Bob", "Sam", "Mike"]; final List<IconData> icons = [Icons.face, Icons.tag_faces, Icons.work, Icons.book]; void main() { runApp(MaterialApp( home: Scaffold( body: ListView.separated( padding: const EdgeInsets.all(8), itemCount: users.length, separatorBuilder: (BuildContext context, int index) => Divider(), itemBuilder: (BuildContext context, int index) { return ListTile( title: Text(users[index], style:TextStyle(fontSize: 22)), leading: Icon(icons[index]), ); } ), appBar: AppBar(title: Text("METANIT.COM")),) )); }
В данном случае использованы встроенные иконки, которые представляют объект IconData и которые передаются в виджет Icon() для отображения слева от заголовка ListTile:
Или, к примеру, добавим параметры trailing
и subtitle
, которые устанавливают соответственно
виджеты после виджета title
и под ним:
import 'package:flutter/material.dart'; final List<String> users = ["Tom", "Bob", "Sam", "Mike"]; final List<String> companies = ["Google", "Microsoft", "Apple", "JetBrains"]; void main() { runApp(MaterialApp( home: Scaffold( body: ListView.separated( padding: const EdgeInsets.all(8), itemCount: users.length, separatorBuilder: (BuildContext context, int index) => Divider(), itemBuilder: (BuildContext context, int index) { return ListTile( title: Text(users[index], style:TextStyle(fontSize: 22)), leading: Icon(Icons.face), trailing: Icon(Icons.phone), subtitle: Text("Works in ${companies[index]}") ); } ), appBar: AppBar(title: Text("METANIT.COM")),) )); }
ListTile с помощью параметров onTap
и nLongPress
позволяет задать обработчики нажатия.
В целом техника выбора элемента похожа на ту, что была описана в прошлой теме. В частности, определим следующий код:
import 'package:flutter/material.dart'; void main() { runApp(MaterialApp( home: Scaffold( body: UsersList(), appBar: AppBar(title: Text("METANIT.COM")),) )); } class UsersList extends StatefulWidget { @override _UsersListState createState() => _UsersListState(); } class _UsersListState extends State<UsersList> { final List<String> _users = ["Tom", "Alice", "Sam", "Bob", "Kate"]; int _selectedIndex = -1; @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _selectedIndex==-1?"Не выбрано": "Выбрано: ${_users[_selectedIndex]}", style: TextStyle(fontSize: 30)), Expanded(child: ListView.builder( itemCount: _users.length, itemBuilder: (BuildContext context, int index) => ListTile( onTap: () { setState(() { // устанавливаем индекс выделенного элемента _selectedIndex = index; }); }, title: Text(_users[index], style: TextStyle(fontSize: 24)), selected: index == _selectedIndex, selectedTileColor: Colors.black12, ), )) ]); } }
В данном случае ListView инкапсулирован в отдельном виджете UsersList. В классе состояния виджета _UsersListState определяем
данные, которые будут отображаться в ListView - список users и переменную _selectedIndex
для отслеживания индекса выбранного
элемента. По умолчанию _selectedIndex
равен -1 для индикации, что на начальном этапе ни одного элемента не выбрано.
С помощью параметра onTap
в конструкторе ListTile изменяем состояние - изменяем индекс выбранного элемента:
onTap: () { setState(() { // устанавливаем индекс выделенного элемента _selectedIndex = index; }); },
Чтобы указать, что элемент выделен, устанавливаем параметр selected:
selected: index == _selectedIndex,
И, кроме того, мы можем установить цвет выделенного элемента с помощью параметра selectedTileColor
:
selectedTileColor: Colors.black12,
Результат работы программы: