Search code examples
flutterdartanimationflutter-sliversliverappbar

Shrink SliverAppBar Image animation Like Title Text in Flutter


I am trying to replicate the text shrink effect that comes naturally with a SliverAppBar with an image such that the background image of the sliverhead shrinks to a leading icon in the appbar of the sliverAppBar.

I have tried using the AnimatedPostioned flutter widget along with a scroll controller that toggles the state of the isSkrink boolean when the page is scrolled.

Below is AnimatedPosition widget:

AnimatedPositioned(
  width: isShrink ? 10.0 : 200.0,
  height: isShrink ? 10.0 : 200.0,
  duration: Duration(seconds: 2),
  curve: Curves.linear,
  child: Stack(
    children: [
      Container(
        child: Image.asset(
            'assets/images/user-avatar.png'),
      ),
    ],
  ),
),

Below is the SliverAppBar with the AnimatedPositioned in the stack and the user icon in the leading param of the SliverAppBar

SliverAppBar(
  leading: isShrink
      ? Padding(
          padding: EdgeInsets.all(10),
          child: CircleAvatar(
            backgroundImage:
                AssetImage('assets/images/user-avatar.png'),
            backgroundColor: Colors.white,
            radius: 3,
          ),
        )
      : Container(),
  floating: true,
  pinned: true,
  flexibleSpace: FlexibleSpaceBar(
    title: Row(
      children: <Widget>[
        Text(
          "Username",
          style: bodyText1Style(
            context,
            color: isShrink ? Colors.black : Colors.white,
            fontSize: isShrink ? 18 : 15,
            fontWeight: FontWeight.w600,
          ),
        ),
      ],
    ),
    background: Stack(
      children: <Widget>[
        AnimatedPositioned(
          width: isShrink ? 10.0 : 200.0,
          height: isShrink ? 10.0 : 200.0,
          duration: Duration(seconds: 2),
          curve: Curves.linear,
          child: Stack(
            children: [
              Container(
                child: Image.asset(
                    'assets/images/user-avatar.png'),
              ),
            ],
          ),
        ),
      ],
    ),
  ),
  expandedHeight: size.height * 0.35,
);

This is the result of the code above:

enter image description here


Solution

  • After a long research I was able to come with this using https://stackoverflow.com/a/59323713/3636615 as reference:

    Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          TransitionAppBar(
            // extent: 250,
            extent: 300,
            avatar: Container(
              decoration: BoxDecoration(
                  image: DecorationImage(
                      image: AssetImage(
                          'assets/images/user-avatar.png'), // NetworkImage(user.imageUrl),
                      fit: BoxFit.cover)),
            ),
            title: "Emmanuel Olu-Flourish",
          ),
          SliverList(
              delegate: SliverChildBuilderDelegate((context, index) {
            return Container(
                child: ListTile(
                  title: Text("${index}a"),
                ));
          }, childCount: 25))
    
        ],
      ),
    );
    

    Check out the TransitionAppBar implementation here: https://gist.github.com/Oluflourish/2f0789bd2e8ee576a2d6364d709c1c14

    Below is demo of the result:

    enter image description here