Всем привет! Продолжаем разбор сливеров, в предыдущих частях серии мы рассмотрели сливеры-списки, сливеры, которые помогают управлять компоновкой и распределением пространства. В этой же статье посмотрим на сливеры, которые дают возможности для более гибкого управления размерами и поведением элементов во время прокрутки. В частности посмотрим, что сливеры умеют делать с заголовком.
Предыдущие материалы по теме:
Такие разные Slivers. Часть 1: обзор и применение во Flutter
Такие разные Slivers. Часть 2: базовые классы и делегаты
Такие разные Slivers. Часть 3: работа с пространством

SliverLayoutBuilder — аналог обычного LayoutBuilder, создает sliver, который может зависеть от его собственных SliverConstraints, то есть от ограничений размера родительского виджета.
SliverLayoutBuilder(builder: (context, constraints) { return SliverFixedExtentList( itemExtent: constraints.viewportMainAxisExtent / 5, delegate: SliverChildListDelegate(items), ); } )

PinnedHeaderSliver — закрепляет свой дочерний виджет в верхней части CustomScrollView.
CustomScrollView( slivers: <Widget>[ PinnedHeaderSliver( child: SomeWidget(), ), SomeSliver(), ], ),

SliverResizingHeader — также закрепляет свой дочерний виджет сверху, но изменяет свой размер при прокрутке, основываясь на прототипах минимального и максимального размера.
CustomScrollView( slivers: <Widget>[ SliverResizingHeader( minExtentPrototype: AnotherPrototypeWidget(), maxExtentPrototype: SomePrototypeWidget(), child: SomeWidget(), ), SomeSliver(), ], ),

SliverFloatingHeader — закрепляется сверху, но скрывает дочерний виджет, когда пользователь прокручивает вперед, и показывает, когда пользователь прокручивает назад.
Можно настроить стиль анимации появления/скрытия с помощью параметра [animationStyle].
Во время прокрутки заголовок и остальной контент перемещаются синхронно. Параметр [snapMode] задает, будет ли заголовок, прежде чем полностью появится, накладываться на остальное содержимое (FloatingHeaderSnapMode.overlay) или по мере расширения заголовка, остальное содержимое будет продолжать прокручиваться (FloatingHeaderSnapMode.scroll).
CustomScrollView( slivers: <Widget>[ SliverFloatingHeader( snapMode: FloatingHeaderSnapMode.overlay, child: SomeWidget(), ), SomeSliver(), ], ),

SliverPersistentHeader — сливер, размер которого меняется при прокрутке. Используется, если нужно создать свой собственный пользовательский заголовок с эффектом уменьшения/увеличения во время скролла, например, SliverAppBar под капотом использует именно его.
Для настройки используется делегат SliverPersistentHeaderDelegate.
Параметр [pinned] отвечает за закрепление в начале при достижении минимального размера.
Параметр [floating] отвечает за мгновенное увеличение размера хедера при скролле наверх.
CustomScrollView( slivers: <Widget>[ SliverPersistentHeader( pinned: true, floating: false, delegate: HeaderDelegate( child: SomeWidget(), ), ), SomeSliver(), ], ), ... class HeaderDelegate extends SliverPersistentHeaderDelegate { const HeaderDelegate({required this.child}); final Widget child; @override double get minExtent => 50; @override double get maxExtent => 200; @override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { return SizedBox.expand(child: child); } @override bool shouldRebuild(HeaderDelegate oldDelegate) => false; }

TreeSliver — это сливер для отображения древовидных структур данных с возможностью сворачивания и разворачивания ветвей. Принимает массив TreeSliverNode, которые представляют параметры дочерних элементов.
TreeSliver<String>( tree: [ TreeSliverNode( 'Root 1', children: [ TreeSliverNode('Child 1.1'), TreeSliverNode('Child 1.2'), ], ), TreeSliverNode( 'Root 2', children: [ TreeSliverNode('Child 2.1'), TreeSliverNode('Child 2.2'), ], ), ], treeNodeBuilder: (BuildContext context, TreeSliverNode<Object?> node, AnimationStyle animationStyle) { return TreeSliver.defaultTreeNodeBuilder( context, node, animationStyle, ); }, ),

SliverOverlapAbsorber — захватывает перекрытую область в прокручиваемых компонентах, в основном в NestedScrollView (прокручиваемый виджет, внутри которого могут быть вложены другие прокручиваемые виджеты). SliverOverlapAbsorber работает в связке с SliverOverlapAbsorberHandle, который сохраняет данные о перекрытии, и SliverOverlapInjector, который возвращает это пространство обратно в компоновку, чтобы остальные сливеры могли корректно использовать его.В примере, без SliverOverlapInjector, SomeSliver заезжал бы под SliverAppBar, а в данном случае SliverOverlapInjector дает отступ, равный размеру SliverAppBar (хранится в SliverOverlapAbsorberHandle).
NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return <Widget>[ SliverOverlapAbsorber( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), sliver: SliverAppBar( title: const Text('NestedScroll'), pinned: true, ), ), ]; }, body: Builder( builder: (context) { return CustomScrollView( slivers: <Widget>[ SliverOverlapInjector( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), SomeSliver(), ], ); } ), )
Это была предпоследняя часть серии, в заключительной статье рассмотрим аналоги обычных (box-based) виджетов в мире сливеров.
