flutter:slivers实现悬浮、停靠吸顶、隐藏等view

一,代码:

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

class  MyviewDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("个人主页")),
        body: CustomScrollView(
          slivers: [
            _buildFloatBox(),
            _buildStickBox(),
            _buildSliverList()
          ],
        ),
    );
  }

  Widget _buildFloatBox() {
    return SliverPersistentHeader(
      floating: true,
      delegate: FloatingSPHD(height: 54),
    );
  }

  Widget _buildStickBox() {
    return SliverPersistentHeader(
        pinned: true,
        delegate: FlexibleSPHD(min: 40, max: 80));
  }

  Widget _buildSliverList() {
    return SliverList(
        delegate: SliverChildBuilderDelegate(
              (context, index) {
            return Container(
              height: 50,
              color: index % 2 == 0 ? Colors.white : Colors.black12,
              width: double.infinity,
              alignment: Alignment.center,
              child: Text("我是第${index}个item"),
            );
          },
          childCount: 30,
        ));
  }


}


class FloatingSPHD extends SliverPersistentHeaderDelegate {
  final double height;

  FloatingSPHD({required this.height});

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Container(
      height: height,
      alignment: Alignment.center,
      color: Colors.green,
      child: const Text(
        "悬浮Header",
        style: TextStyle(
          color: Colors.white,
          fontSize: 16,
          fontWeight: FontWeight.bold,
        ),
      ),
    );
  }

  @override
  double get maxExtent => height;

  @override
  double get minExtent => height;

  @override
  bool shouldRebuild(covariant FloatingSPHD oldDelegate) {
    return oldDelegate.height != height;
  }

  @override
  PersistentHeaderShowOnScreenConfiguration get showOnScreenConfiguration =>
      const PersistentHeaderShowOnScreenConfiguration(
          minShowOnScreenExtent: double.infinity);
}


class FlexibleSPHD extends SliverPersistentHeaderDelegate {
  final double max;
  final double min;

  FlexibleSPHD({required this.max, required this.min});

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    double progress = shrinkOffset / (max - min);
    progress = progress > 1 ? 1 : progress;

    return Container(
      color: Color.lerp(Colors.blue, Colors.red, progress),
      child: Column(children: [
        const Text(
          "可伸缩区域",
          style: TextStyle(
              color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),
        ),
        SizedBox(height: (1 - progress) * 20),
        Opacity(
          opacity: 1 - progress,
          child: SizedBox(
            height: (1 - progress) * 30,
            child: const Text("需要隐藏部分",
                style: TextStyle(
                    color: Colors.white,
                    fontSize: 16,
                    fontWeight: FontWeight.bold)),
          ),
        )
      ]),
    );
  }

  @override
  double get maxExtent => max;

  @override
  double get minExtent => min;

  @override
  bool shouldRebuild(covariant FlexibleSPHD oldDelegate) {
    return oldDelegate.min != min || oldDelegate.max != max;
  }
}

二,测试效果:

未上滑时:

下滑后:

posted @ 2025-04-19 10:40  刘宏缔的架构森林  阅读(273)  评论(0)    收藏  举报