Наложение контента при использовании NestedScrollView с дочерними CustomScrollView. SliverOverlapAbsorber

 SliverOverlapAbsorber используется в Flutter для того, чтобы решить проблему с наложением контента при использовании NestedScrollView с дочерними CustomScrollView (или другими свитками, основанными на слотах). Его основная задача — абсорбировать часть перекрытия (overlap), которое создается в подобных вложенных структурах со свитками.

Основные задачи SliverOverlapAbsorber:

  1. Предотвращение наложений контента: Когда вы используете NestedScrollView, часто возникает ситуация, когда контент в CustomScrollView может перекрываться заголовком (SliverAppBar). Чтобы этого избежать, используется SliverOverlapAbsorber, который "поглощает" пространство, выделенное для SliverAppBar, и предотвращает наложение элементов контента.

  2. Синхронизация скроллинга: SliverOverlapAbsorber помогает синхронизировать область прокрутки между SliverAppBar и основным контентом, чтобы они корректно "перекрывались" или "откатывались" во время скроллинга.

Как его использовать:

SliverOverlapAbsorber обычно используется вместе с SliverOverlapInjector. Вот пример того, как можно его применить:

NestedScrollView(
  headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
    return <Widget>[
      SliverOverlapAbsorber(
        // Это ключевое значение для правильной работы Overlap Absorber
        handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
        sliver: SliverAppBar(
          expandedHeight: 200.0,
          floating: false,
          pinned: true,
          flexibleSpace: FlexibleSpaceBar(
            title: Text('SliverAppBar'),
          ),
        ),
      ),
    ];
  },
  body: Builder(
    builder: (BuildContext context) {
      return CustomScrollView(
        slivers: <Widget>[
          SliverOverlapInjector(
            // Тот же handle, что и в SliverOverlapAbsorber
            handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                return ListTile(title: Text('Item #$index'));
              },
              childCount: 20,
            ),
          ),
        ],
      );
    },
  ),
);

Как это работает:

  • SliverOverlapAbsorber: "поглощает" часть пространства, выделенного для перекрытия.
  • SliverOverlapInjector: возвращает это пространство, чтобы дочерние элементы знали, где начинать отрисовку без наложения.

Этот паттерн часто используется, чтобы избежать проблем с наложением контента, когда используются NestedScrollView и скролл-виджеты с разными уровнями прокрутки.