Mockup

我正在try 创建上面的样机中描述的动态动画.我需要的是:

  • 代表化身的圆形(例如用户图片);
  • 在它下面居中的文字.
  • 在它们(使用半个屏幕)下面是一个可滚动的PageView.

动画应如下所示:

Begin: In a Stack both centered at the begin.
Animation: Scaling down and sliding the text (with variable lenght) that must be to the right of the avatar.
End:
As the second image in the mockup. Side-to-side while the content below keeps scrolling.

想在SliverPersistentHeaderCustomMultiChildLayout结合起来,但问题是文本开始居中,结束时向左对齐,我可以动态地制作动画.我试着go 掉最后居中文本的偏移量,但感觉不对劲.

任何帮助或样品只与此动画将不胜感激.谢谢.

推荐答案

您需要一个小条来根据滚动偏移设置布局动画.更具体地说,你的情况是SliverPersistentHeader美元.

虽然CustomMultiChildLayout不是必需的,但是您可以使用补间和对齐/填充/填充来达到相同的效果.但是如果你的布局开始变得太复杂,你可以试一试.

诀窍是使用SliverPersistentHeader给出的滚动偏移量来计算当前进度.然后用这个级数将元素定位在原始位置和最终位置之间.

以下是一个原始示例:

enter image description here

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(150.0, 150.0), end: Size(50.0, 50.0));
  final _avatarMarginTween =
      EdgeInsetsTween(begin: EdgeInsets.zero, end: EdgeInsets.only(left: 10.0));
  final _avatarAlignTween =
      AlignmentTween(begin: Alignment.topCenter, end: Alignment.centerLeft);

  final _titleMarginTween = EdgeInsetsTween(
      begin: EdgeInsets.only(top: 150.0 + 5.0),
      end: EdgeInsets.only(left: 10.0 + 50.0 + 5.0));
  final _titleAlignTween =
      AlignmentTween(begin: Alignment.center, 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;
  }
}

可与CustomScrollView一起使用:

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'),
          );
        }),
      )
    ],
  ),
);

Dart相关问答推荐

在异步方法中,有没有更优雅的方式在DART中等待!=NULL?

Dart:判断泛型函数的类型 T

切换到可靠的零安全后简单分配中的可空性不匹配

如何在polymer应用程序中实现主要功能

可调用云函数错误:响应缺少数据字段

如何防止意外发布私有 pub 包

Flutter - 为什么滑块不会在 AlertDialog 中更新?

dart中整数的最大值是多少?

如何解决Id does not exist错误?

Flutter DataTable - 点击行

使用 Stream.periodic 时如何取消 Stream?

用 Dart 模式替换静态继承

如何从 Dart 中的字符串中删除换行符?

Dart 的输出是什么样的?

如何在 Dart 中扁平化map列表?

Dart 中的 Math.round() 在哪里?

在 Dart 和 Pub 中,我应该将 pubspec.lock 添加到我的 .gitignore 吗?

Dart 中的函数重载

List firstWhere Bad state: No element

如何在 Dart 中将 double 转换为 int?