Ask the assistant
0/400
Your question is processed by an AI service and kept to improve answers. Do not enter personal data.

    ListView

    This page has not been translated into English yet. The Russian original is below.

    Прокручиваемый список. Есть две формы: ListView — дети перечислены прямо в разметке, и ListView.builder — строки строятся по шаблону-макросу @Macros id:itemBuilder , обычно из данных. Для длинных и динамических списков берите ListView.builder .

    Тип: multi-child ( ListView ), multi-child с макросом-шаблоном ( ListView.builder )

    SizedBox height:200
      ListView
        Text "Первая строка"
        Text "Вторая строка"
        Text "Третья строка"
    Список, как и любой скроллер, должен получать ограниченную высоту (или ширину при горизонтальной прокрутке): внутри Column оберните его в Expanded , либо задайте размер через SizedBox . Подробнее — в Bad practices.

    Параметры

    Общие для обеих форм:

    Параметр Тип Default Описание
    scrollDirection string vertical Направление: vertical , horizontal
    reverse bool false Начинать с конца (первая строка — внизу или справа)
    shrinkWrap bool false Занимать место по содержимому, а не всё доступное
    physics string always Реакция на жест: never (не прокручивать), bouncing , clamp , always . never отдаёт колесо скроллеру снаружи — нужен вложенному списку
    itemExtent double — Фиксированный размер строки по главной оси — быстрее, чем считать каждую
    clipBehavior string hardEdge Обрезка по границам списка
    keyboardDismissBehavior string manual onDrag — убирать экранную клавиатуру при протаскивании списка

    Только у ListView.builder :

    Параметр Тип Default Описание
    itemCount int 0 Сколько строк строить
    keepVisible int — Индекс строки, которую список держит на экране: при его изменении список прокручивается к ней минимально необходимым образом

    Вложенные структуры

    #padding

    Отступ внутри области прокрутки: содержимое отступает от краёв, но прокручивается до самого края.

    SizedBox height:160
      ListView
        #padding symmetric horizontal:16 vertical:8
        Text "Строка 1"
        Text "Строка 2"
        Text "Строка 3"

    Дочерние элементы

    В ListView дети — сами строки.

    В ListView.builder ребёнок один — макрос @Macros id:itemBuilder . Его тело — шаблон строки, а параметр index (в объявлении пишется index:0 ) получает номер строки при каждой сборке. Второй макрос с id:separatorBuilder превращает список в «со разделителями»: он ставится между строками ( itemCount - 1 раз), но не после последней.

    SizedBox height:240
      ListView.builder itemCount:20
        @Macros id:itemBuilder index:0
          Padding
            #padding all 12
            Text $"Строка ${index}"
        @Macros id:separatorBuilder index:0
          Divider

    Список из данных

    Строки обычно берут из генератора данных. Макрос получает только index ; поля достаются индексом на месте вызова, всегда с ?? — пока данные не загрузились, значение null :

    JsonData src:"data/products.json" data:@products count:@count
      SizedBox height:320
        ListView.builder itemCount:$count
          @Macros id:itemBuilder index:0
            Padding
              #padding all 12
              Text {products[index]['title'] ?? ""}

    Фильтрацию и сортировку выполняют генераторами ( FilterData ) до списка, а не скрытием строк внутри шаблона: скрытые строки ломают счётчики и прокрутку.

    Примеры

    Горизонтальная лента

    SizedBox height:96
      ListView scrollDirection:horizontal
        SizedBox width:120
          ColoredBox color:#4f46e5
        SizedBox width:120
          ColoredBox color:#7c3aed
        SizedBox width:120
          ColoredBox color:#059669

    Список под шапкой

    Column
      Padding
        #padding all 16
        Text "Заголовок"
      Expanded
        ListView.builder itemCount:50
          @Macros id:itemBuilder index:0
            Padding
              #padding symmetric horizontal:16 vertical:8
              Text $"Элемент ${index}"

    Выбранная строка остаётся на экране

    @sel:0
    Column
      SizedBox height:200
        ListView.builder itemCount:30 keepVisible:$sel
          @Macros id:itemBuilder index:0
            Text $"Строка ${index}"
      Button onPressed:{sel = sel + 1}
        Text "Дальше"

    Различия между приложением и сайтом

    Сайт превращает список в HTML-список с прокруткой, и не все параметры у него работают:

    ListView ListView.builder
    scrollDirection работает не работает — всегда вертикально
    #padding работает не работает
    itemExtent работает не работает
    reverse , shrinkWrap , physics , clipBehavior не работают не работают
    keyboardDismissBehavior у страницы нет своей экранной клавиатуры — не имеет смысла то же
    keepVisible — не работает

    Для горизонтальной ленты на сайте берите статический ListView scrollDirection:horizontal . Строки ListView.builder на сайте попадают в страницу все сразу, поэтому не стройте списком на тысячи строк то, что должно читаться поисковиком как страница.

    Bad practices

    Список без ограниченной высоты

    // BAD — Column даёт ListView бесконечную высоту: в приложении это ошибка раскладки
    Column
      Text "Заголовок"
      ListView
        Text "Строка 1"
        Text "Строка 2"
    // GOOD — Expanded отдаёт списку оставшееся место
    Column
      Text "Заголовок"
      Expanded
        ListView
          Text "Строка 1"
          Text "Строка 2"

    Скрытие строк вместо фильтрации данных

    // BAD — строка прячется, но остаётся в itemCount: счётчики и «пусто» врут
    ListView.builder itemCount:20
      @Macros id:itemBuilder index:0
        Visibility visible:{index % 2 == 0}
          Text $"Строка ${index}"

    Отфильтруйте данные генератором ( FilterData ), а itemCount возьмите из его count .

    Best practices

    • Задавайте itemExtent , если строки одной высоты: список не тратит время на измерение.
    • Вложенный список (внутри другого скроллера) — shrinkWrap:true и physics:never .
    • Не копируйте макрос в цикле вручную : то, что повторяется сотни раз, выводится ListView.builder .
    • Если нужна навигация по фокусу с пульта — смотрите ReeelScroll.

    See also

    • SingleChildScrollView — прокрутка одного ребёнка
    • GridView — та же идея, но сеткой
    • Expanded — как дать списку место внутри Column
    • ReeelScroll — список с фокусом и навигацией
    DOCS
    dark_mode_baseline
    RU/EN
    menu_baseline