Для чего в Flutter существует несколько виджетов для скроллинга?

«Для чего в Flutter существует несколько виджетов для скроллинга?» — вопрос из категории UI и вёрстка, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Разные скроллинг-виджеты в Flutter оптимизированы под конкретные сценарии использования и производительность. Вот как я выбираю между ними в своих проектах:

1. SingleChildScrollView — для простых случаев с ограниченным количеством контента:

// Форма с полями ввода
SingleChildScrollView(
  padding: EdgeInsets.all(16),
  child: Column(
    children: [
      TextField(decoration: InputDecoration(labelText: 'Имя')),
      TextField(decoration: InputDecoration(labelText: 'Email')),
      // ... ещё 5-10 полей
    ],
  ),
)

2. ListView — для списков, особенно с большим количеством элементов:

// Ленивая загрузка для списка из 1000+ элементов
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(items[index].title),
    );
  },
)

3. GridView — для отображения данных в сетке:

// Галерея изображений
GridView.builder(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3, // 3 колонки
    crossAxisSpacing: 4,
    mainAxisSpacing: 4,
  ),
  itemCount: images.length,
  itemBuilder: (context, index) {
    return Image.network(images[index].url);
  },
)

4. CustomScrollView с Slivers — для сложных, кастомных скролл-эффектов:

// Комбинированный список с заголовком и сеткой
CustomScrollView(
  slivers: [
    SliverAppBar(expandedHeight: 200, flexibleSpace: FlexibleSpaceBar(title: Text('Заголовок'))),
    SliverList(delegate: SliverChildBuilderDelegate((ctx, i) => ListTile(title: Text('Элемент $i')))),
    SliverGrid(delegate: SliverChildBuilderDelegate((ctx, i) => Card(child: Text('Карточка $i'))), gridDelegate: ...),
  ],
)

Ключевые различия в производительности:

  • ListView()/GridView() — создают все дочерние виджеты сразу (подходит для небольших списков).
  • .builder конструкторы — создают виджеты лениво, только когда они появляются на экране (оптимально для больших списков).
  • .separated конструкторы — добавляют разделители между элементами без дополнительных проверок в коде.

В моём текущем проекте с лентой новостей я использую CustomScrollView с комбинацией SliverList для постов и SliverPersistentHeader для закреплённой панели фильтров.