1. 기본 예제

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          SliverAppBar(
            title: Text("Flutter Shopping App"),
            centerTitle: true,
            pinned: false,
          ),
          SliverAppBar(
            title: Text(
              "앱바",
              style: TextStyle(color: Colors.white),
            ),
            pinned: true,
            //snap: true,
            //floating: true,
            expandedHeight: 250,
            flexibleSpace: PageView.builder(
              itemCount: 5,
              itemBuilder: (context, index) {
                return Image.network(
                  "<https://picsum.photos/id/$>{index + 1}/200/300",
                  fit: BoxFit.cover,
                );
              },
            ),
          ),
          SliverToBoxAdapter(
            child: Container(
              color: Colors.red,
              height: 300,
            ),
          ),
          SliverPersistentHeader(
            pinned: true,
            delegate: MyPersistentHeaderDelegate(
              child: Container(
                color: Colors.blueGrey,
                child: Center(
                  child: Text(
                    'SliverPersistentHeader',
                    style: TextStyle(fontSize: 20.0, color: Colors.white),
                  ),
                ),
              ),
              minHeight: 50,
              maxHeight: 500,
            ),
          ),
          SliverPersistentHeader(
            pinned: true,
            delegate: MyPersistentHeaderDelegate(
              child: ListView.builder(
                scrollDirection: Axis.horizontal,
                itemCount: 30,
                itemBuilder: (context, index) {
                  return Container(
                    width: 100,
                    color: Colors.yellow[((index % 9) + 1) * 100], // 0 ~ 8
                  );
                },
              ),
              minHeight: 100,
              maxHeight: 100,
            ),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              childCount: 20,
              (context, index) {
                return Container(
                  height: 50,
                  color: Colors.blue[((index % 9) + 1) * 100], // 0 ~ 8
                );
              },
            ),
          ),
          SliverFillRemaining(
            child: Center(
              child: Text('This is the remaining content.'),
            ),
          ),
        ],
      ),
    );
  }
}

class MyPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
  final double minHeight;
  final double maxHeight;
  final Widget child;

  MyPersistentHeaderDelegate({
    required this.child,
    required this.minHeight,
    required this.maxHeight,
  });

  @override
  double get maxExtent => maxHeight;

  @override
  double get minExtent => minHeight;

  @override
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
    return true;
  }

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return child;
  }
}

2. 실습 예제

[Flutter] 스크롤 + Sliver 정복하기