简单的侧边吸顶

480 阅读1分钟

需求:侧边吸顶,底部要跟随滑动

简单改下别人的代码

使用 SliverCrossAxisGroup + CustomScrollView

5月4日.gif

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('SliverGroup'),),
      body: CustomScrollView(
        slivers: <Widget>[
          SliverToBoxAdapter(
            child: Container(
              height: 200,
              width: double.infinity,
              color: Colors.green,
              alignment: Alignment.center,
              child: const Text(
                '顶部固定banner',
                style: TextStyle(
                    fontSize: 25
                ),
              ),
            ),
          ),
          SliverCrossAxisGroup(
            slivers: <Widget>[
              SliverPersistentHeader(
                delegate: _MySliverHeaderDelegate(
                  minHeight: 600.0, // 最小高度
                  maxHeight: 600.0, // 最大高度
                  child: Container(
                    width: 100,
                    color: Colors.blue,
                    child: const Center(child: Text('吸顶组件')),
                  ),
                ),
                pinned: true, // 使组件吸顶
              ),
              SliverConstrainedCrossAxis(
                maxExtent: 300,
                sliver: SliverColorList(
                  height: 100.0,
                  fontSize: 24,
                  count: 20,
                  color1: Colors.amber[300],
                  color2: Colors.blue[300],
                ),
              ),
            ],
          ),
          SliverToBoxAdapter(
            child: Container(
              height: 300,
              width: double.infinity,
              color: Colors.brown,
              alignment: Alignment.center,
              child: const Text(
                '底部文字说明',
                style: TextStyle(
                    fontSize: 25
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class SliverColorList extends StatelessWidget {
  final double height;
  final double fontSize;
  final Color? color1;
  final Color? color2;
  final int count;
  const SliverColorList(
      {super.key,
        required this.height,
        required this.fontSize,
        required this.count,
        this.color1,
        this.color2});

  @override
  Widget build(BuildContext context) {
    return SliverList.builder(
      itemBuilder: (BuildContext context, int index) {
        return Container(
          color: index.isEven ? color1 : color2,
          height: height,
          child: Center(
            child: Text(
              'Item $index',
              style: TextStyle(fontSize: fontSize),
            ),
          ),
        );
      },
      itemCount: count,
    );
  }
}

class _MySliverHeaderDelegate extends SliverPersistentHeaderDelegate {
  _MySliverHeaderDelegate({
    required this.minHeight,
    required this.maxHeight,
    required this.child,
  });

  final double minHeight;
  final double maxHeight;
  final Widget child;

  @override
  double get minExtent => minHeight;

  @override
  double get maxExtent => max(maxHeight, minHeight);

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

  @override
  bool shouldRebuild(_MySliverHeaderDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
}