TGViewer
Flutter Friendly Flutter Friendly @flutterfriendly · 995 subscribers
Post #227 809
🔗Привет, это Роза, Flutter Dev Friflex!

В прошлом посте мы разобрали slivers и зачем они нужны. Сегодня поговорим про SliverPersistentHeader.

SliverPersistentHeader — это  виджет, который меняет свою высоту при прокрутке. Его можно использовать, например, для создания сжимающихся шапок в профилях пользователей или в деталях товара.

Так как SliverPersistentHeader сам по себе не знает, как отображать содержимое, он использует делегат — SliverPersistentHeaderDelegate. Он управляет его поведением и внешним видом через:
✔️ build — определяет, как выглядит виджет на каждом этапе прокрутки
✔️ maxExtent — задает максимальную высоту заголовка в его развернутом состоянии
✔️ minExtent — определяет минимальную высоту, до которой заголовок сжимается
✔️ shouldRebuild — условие для перерисовки делегата

Внутри метода build доступны параметры:
▪️ double shrinkOffset — показывает, насколько сильно заголовок сжался (от 0 до maxExtent — minExtent)
▪️ bool overlapsContent — указывает, перекрывает ли содержимое последующие сливеры

Для управления поведением заголовка при прокрутке у SliverPersistentHeader есть параметры pinned и floating:
▫️ pinned: true — шапка остается закрепленной, когда прокрутка достигает минимальной высоты
▫️ floating: true — заголовок появляется сразу, как только пользователь начинает прокручивать страницу вверх, даже если прокрутка еще не дошла до самого верха

Пример использования

Давайте реализуем пример «сжимающейся» шапки профиля, где аватар и заголовок плавно меняют свой размер и положение при скролле.

Шаг 1: Подготовка виджетов

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

1. ColoredContainer для затемнения фона

class ColoredContainer extends StatelessWidget {
  const ColoredContainer({super.key, required this.progress});
  final double progress;

  @override
  Widget build(BuildContext context) {
    return Opacity(
      opacity: progress,
      child: const ColoredBox(color: Colors.black54),
    );
  }
}


2. HeaderTitle для заголовка, который будет смещаться к центру

class HeaderTitle extends StatelessWidget {
  const HeaderTitle({super.key, required this.progress});
  final double progress;

  @override
  Widget build(BuildContext context) {
    return AnimatedContainer(
      duration: const Duration(milliseconds: 100),
      padding: EdgeInsets.lerp(
        const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
        const EdgeInsets.only(bottom: 16),
        progress,
      ),
      alignment: Alignment.lerp(
        Alignment.bottomLeft,
        Alignment.bottomCenter,
        progress,
      ),
      child: Text(
        'Profile',
        style: TextStyle.lerp(
          Theme.of(context).textTheme.titleLarge!.copyWith(color: Colors.white),
          Theme.of(context).textTheme.titleMedium!.copyWith(color: Colors.white),
          progress,
        ),
      ),
    );
  }
}


Продолжение — в комментариях 👇
  • 🔥 8
  • 👍 6
  • ❤ 3
More from @flutterfriendly
  1. May 14, 2026👀Какой сложный вопрос или тема по Flutter вас сейчас беспокоят? Может, задача не идет, ба…
  2. Apr 17, 2026💭Привет! Это Роза, Flutter-разработчица Friflex! Уверена, многие из вас знакомы с Dart De…
  3. Apr 8, 2026Привет, друзья! Делимся нашей страничкой на Хабре, чтобы всегда оставаться на связи. Там е…
  4. Apr 3, 2026🌸Апрель в календаре и на экране Весна зовет обновлять визуальное: убирать темные темы и в…
  5. Apr 1, 2026Всегда с нетерпением ждем этого дня, чтобы сделать подборку ИТ-мемов Пусть поводов для улы…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →