Спросите помощника
0/400
Вопрос обрабатывается ИИ-сервисом и сохраняется для улучшения ответов. Не вводите персональные данные.

    ListView

    Прокручиваемый список. Есть две формы: 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 — список с фокусом и навигацией
    menu_baseline