Omar Mir
Omar Mir

Reputation: 1624

How do I go about removing the elevation from SliverPersistentHeader?

Hopefully a simple question, I have SliverPersistentHeader inside a CustomScrollView, and it looks like this SliverPersistentHeader has some sort of shadow/elevation. Is there a way to remove it (I've outlined the shadow in the red box)?

See picture below: enter image description here

This basic body is a scaffold with the SliverPersistentHeader coming from the _makeHeader call:

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Consts.coMainBackground,
      body: CustomScrollView(
        slivers: <Widget>[
          _sliverAppBar(),
          _makeHeader(),
          BlocBuilder<AllPersonsBloc, AllPersonsState>(
            builder: (context, state) {
              if (state is AllPersonsLoading) {
                return _buildLoading();
              } else if (state is AllPersonsLoaded) {
                return _sliverList(context, state.persons);
              } else if (state is AllPersonsError) {
                return _buildErrorMessage(state.message);
              } else {
                return _buildErrorMessage('Unknown error!');
              }
            },
          ),
        ],
      ),
    );
  }

the Make Header function:

  Widget _makeHeader() {
    return SliverPersistentHeader(
      pinned: true,
      delegate: _SliverAppBarDelegate(
        minHeight: 130.0,
        maxHeight: 130.0,
        child: Container(
          color: Consts.coForestGreenBackground,
          child: Container(
            decoration: BoxDecoration(
              color: Consts.coMainBackground,
              borderRadius: BorderRadius.only(topLeft: Radius.circular(15), topRight: Radius.circular(15))
            ),
            child: _cardHeader('People', Icons.search, 'Name')),
          )
      ),
    );
  }

And finally the Delegate function:

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  _SliverAppBarDelegate({
    @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 => math.max(maxHeight, minHeight);

  @override
  Widget build(
      BuildContext context, 
      double shrinkOffset, 
      bool overlapsContent) 
  {
    return new SizedBox.expand(child: child);
  }
  @override
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
}

And card header (not actually a card)

 Widget _cardHeader(String titleText, IconData inputIcon, String hint) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: standardEdgePadding),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(titleText, style: Consts.cardHeaderStyle,),
          Container(
            margin: EdgeInsets.only(top: 20),
            height: 40,
            decoration: BoxDecoration(
              color: Consts.inputGreen,
              borderRadius: BorderRadius.all(Radius.circular(10))
            ),
            child: Row(
              children: <Widget>[
                Padding(
                  padding: EdgeInsets.symmetric(horizontal: 10),
                  child: Icon(
                    inputIcon,
                    color: Consts.inputGreenText,
                    size: Consts.cardInputIconSize,
                  ),
                ),
                Flexible(child: TextField(
                  decoration: new InputDecoration.collapsed(
                    hintText: hint,
                    hintStyle: Consts.cardInputStyle,
                  ),
                ),)
              ],
            ),
          )
        ],
      ),
    );
  }

Upvotes: 0

Views: 1491

Answers (2)

Omar Mir
Omar Mir

Reputation: 1624

So it turns out because, i have a container inside a container:

Widget _makeHeader() {
    return SliverPersistentHeader(
      pinned: true,
      delegate: _SliverAppBarDelegate(
        minHeight: 130.0,
        maxHeight: 130.0,
        child: Container(
          color: Consts.coForestGreenBackground,
          child: Container(
            //There seemed to be some spacing between the search header and the rest of the list, this takes care of it
            //transform: Matrix4.translationValues(0.0, 1.0, 0.0),
            decoration: BoxDecoration(
              color: Consts.coMainBackground,
              borderRadius: BorderRadius.only(topLeft: Radius.circular(15), topRight: Radius.circular(15))
            ),
            child: _cardHeader('People', Icons.search, 'Name')),
          )
      ),
    );
  }

The way that the Header "meets" the SliverList there is an very minor gap (might be related to the emulator only). So the "coForestGreenBackground" colour in the parent container is showing through in that gap. There is no actual elevation/shadow.

If I uncomment the code, then the gap (aka elevation in my original question) vanishes.

I slept very poorly last night as I couldn't stop thinking about where I made a mistake. Thanks to @drogel for confirming there is no actual shadow/elevation on the SliverPersistentHeader.

Upvotes: 0

drogel
drogel

Reputation: 2717

SliverPersistentHeader alone does not have a shadow, therefore that elevation effect is not coming from your SliverPersistentHeader. It is not explicit from your code snippets, but I can see you have a _cardHeader('People', Icons.search, 'Name') method in your widget tree. I suspect it contains a Card widget inside the widget tree this method returns.

As seen in the Card widget Flutter documentation, Cards have a default non-zero elevation value, which might be casting the shadow in your case. See if there is any Card widget in your widget tree, and set its elevation parameter to zero.

Upvotes: 1

Related Questions