通常用于CustomScrollView中,可以让一个组件在滑动中停留在顶部,不会滑动消失。

相关组件

CustomScrollView

SliverPersistentHeader基本使用

  1. <br />【delegate】 : 代理 【SliverPersistentHeaderDelegate】<br />【floating】 : 是否浮动 【bool】<br />【pinned】 : 是否顶部停留 【bool】<br />![201.gif](https://cdn.nlark.com/yuque/0/2020/gif/326147/1589509983273-361b57b5-fa00-4b36-83ca-1ab47d928862.gif#align=left&display=inline&height=455&margin=%5Bobject%20Object%5D&name=201.gif&originHeight=455&originWidth=404&size=1388253&status=done&style=none&width=404)
import 'dart:math';
import 'package:flutter/material.dart';
class SliverPersistentHeaderDemo extends StatelessWidget {
  final data = <Color>[
    Colors.purple[50],
    Colors.purple[100],
    Colors.purple[200],
    Colors.purple[300],
    Colors.purple[400],
    Colors.purple[500],
    Colors.purple[600],
    Colors.purple[700],
    Colors.purple[800],
    Colors.purple[900],
  ];

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 500,
      child: CustomScrollView(
        slivers: <Widget>[
          _buildSliverAppBar(),
          _buildPersistentHeader('袅缈岁月,青丝银发',Color(0xffe7fcc9)),
          _buildCommonWidget(),
          _buildPersistentHeader('以梦为马,不负韶华',Color(0xffcca4ff)),
          _buildSliverList()
        ],
      ),
    );
  }

  Widget _buildCommonWidget() => SliverToBoxAdapter(
    child: Container(
      padding: EdgeInsets.symmetric(horizontal: 10),
      color: Colors.grey.withAlpha(22),
      child: ListTile(
        leading: Image.asset("assets/images/icon_head.png"),
        title: Text("以梦为马"),
        subtitle: Text("海子"),
        selected: true,
        contentPadding: EdgeInsets.all(5),
        trailing: Icon(Icons.more_vert),
      ),
    ),
  );
  Widget _buildPersistentHeader(String text,Color color) => SliverPersistentHeader(
    pinned: true,
    delegate: _SliverDelegate(
        minHeight: 40.0,
        maxHeight: 100.0,
        child: Container(
          color: color,
          child: Center(
            child: Text(text, style: TextStyle(
                fontSize: 18,
                shadows: [Shadow(color: Colors.white, offset: Offset(1, 1))]),
          ),
        )),
  ));

  Widget _buildSliverList() => SliverList(
    delegate: SliverChildBuilderDelegate(
            (_, int index) => Container(
          alignment: Alignment.center,
          width: 100,
          height: 60,
          color: data[index],
          child: Text(
            colorString(data[index]),
            style: TextStyle(color: Colors.white, shadows: [
              Shadow(
                  color: Colors.black,
                  offset: Offset(.5, .5),
                  blurRadius: 2)
            ]),
          ),
        ),
        childCount: data.length),
  );

  Widget _buildSliverAppBar() {
    return SliverAppBar(
      expandedHeight: 190.0,
      leading: _buildLeading(),
      title: Text('张风捷特烈'),
      actions: _buildActions(),
      elevation: 2,
      pinned: true,
      backgroundColor: Colors.orange,
      flexibleSpace: FlexibleSpaceBar(
        //伸展处布局
        titlePadding: EdgeInsets.only(left: 55, bottom: 15), //标题边距
        collapseMode: CollapseMode.parallax, //视差效果
        background: Image.asset(
          "assets/images/caver.jpeg",
          fit: BoxFit.cover,
        ),
      ),
    );
  }

  Widget _buildLeading() => Container(
      margin: EdgeInsets.all(10),
      child: Image.asset('assets/images/icon_head.png'));

  List<Widget> _buildActions() => <Widget>[
    IconButton(
      onPressed: () {},
      icon: Icon(
        Icons.star_border,
        color: Colors.white,
      ),
    )
  ];

  String colorString(Color color) =>
      "#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}";
}


class _SliverDelegate extends SliverPersistentHeaderDelegate {
  _SliverDelegate({
    @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 new SizedBox.expand(child: child);
  }

  @override //是否需要重建
  bool shouldRebuild(_SliverDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
}