0

I'm trying to create a dynamic animation described in the mockup above. What I need is:

A round shape that will represent an avatar (user pic, for example); A text centered below it. Below those (that use half of the screen) is a scrollable PageView.

class TransitionAppBar extends StatelessWidget {
      final Widget avatar;
      final Widget title;
    
      const TransitionAppBar({this.avatar, this.title, Key key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return SliverPersistentHeader(
          pinned: true,
          delegate: _TransitionAppBarDelegate(
            avatar: avatar,
            title: title,
          ),
        );
      }
    }
    
    class _TransitionAppBarDelegate extends SliverPersistentHeaderDelegate {
      final _avatarTween =
          SizeTween(begin: Size(96.0, 96.0), end: Size(72.0, 72.0));
      final _avatarMarginTween =
          EdgeInsetsTween(begin: EdgeInsets.zero, end: EdgeInsets.only(left: 10.0));
      final _avatarAlignTween =
          AlignmentTween(begin: Alignment.center, end: Alignment.topLeft);
    
      final _titleMarginTween = EdgeInsetsTween(
          begin: EdgeInsets.only(top: 150.0 ),
          end: EdgeInsets.only(left: 10.0 + 50.0 + 5.0));
      final _titleAlignTween =
          AlignmentTween(begin: Alignment.bottomCenter, end: Alignment.centerLeft);
    
      final Widget avatar;
      final Widget title;
    
      _TransitionAppBarDelegate({this.avatar, this.title})
          : assert(avatar != null),
            assert(title != null);
    
      @override
      Widget build(
          BuildContext context, double shrinkOffset, bool overlapsContent) {
        final progress = shrinkOffset / 200.0;
    
        final avatarSize = _avatarTween.lerp(progress);
        final avatarMargin = _avatarMarginTween.lerp(progress);
        final avatarAlign = _avatarAlignTween.lerp(progress);
    
        final titleMargin = _titleMarginTween.lerp(progress);
        final titleAlign = _titleAlignTween.lerp(progress);
        return Stack(
          fit: StackFit.expand,
          children: <Widget>[
            Padding(
              padding: avatarMargin,
              child: Align(
                alignment: avatarAlign,
                child: SizedBox.fromSize(size: avatarSize, child: avatar),
              ),
            ),
            Padding(
              padding: titleMargin,
              child: Align(
                alignment: titleAlign,
                child: DefaultTextStyle(
                    style: Theme.of(context).textTheme.title, child: title),
              ),
            )
          ],
        );
      }
    
      @override
      double get maxExtent => 200.0;
    
      @override
      double get minExtent => 100.0;
    
      @override
      bool shouldRebuild(_TransitionAppBarDelegate oldDelegate) {
        return avatar != oldDelegate.avatar || title != oldDelegate.title;
      }
    }
    

which you can use with a CustomScrollView for calling sliver animation with sliver list with delegate SliverChildBuilderDelegate Trying to animate image and text from center to topleft corner but getting overflow issue due to padding changes

    Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          TransitionAppBar(
            avatar: Material(
              color: Colors.blue,
              elevation: 3.0,
            ),
            title: Text("Hello World"),
          ),SliverList(
            delegate: SliverChildBuilderDelegate((context, index) {
              return ListTile(
                title: Text('$index'),
              );
            }),
          )
        ],
      ),
    );
Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
Pramanshu
  • 71
  • 6

0 Answers0