我需要实现自定义动画,同时滚动用户列表.请参阅一个示例

enter image description here

我当前的视图由以下元素组成:

SingleChildScrollView包含Column,其中包含:

  • 三个顶级元素中的Row个(每个元素都是一个自定义小部件,基本上有Stack个头像、奖牌和详细信息(Column))
  • Row作为表头
  • ListView个其他用户.

SingleChildScrollView与填充到提供程序的ScrollNotificationNotificationListener包装在一起.然后在每个顶层元素中监听滚动值,以执行其自身的动画.

我想知道这里要采取的一些一般路径和算法.我try 了AnimatedPositioned,但一旦将其应用于多个元素,就会导致性能问题.到目前为止,我应该使用AnimationController或更多定制的东西吗?任何帮助都将不胜感激.

推荐答案

正如PSkink提到的,使用SliverPersistentHeader可以存档,这是一个演示小部件,用来说明如何做到这一点.你需要玩弄价值.我最喜欢的部分是用.lerp,doubleLerp……以定位这些项目.

class Appx extends StatelessWidget {
  const Appx({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          SliverPersistentHeader(
            pinned: true,
            delegate: CustomSliverPersistentHeaderDelegate(),
          ),
          const SliverToBoxAdapter(
            child: SizedBox(
              height: 3333,
              width: 200,
            ),
          ),
        ],
      ),
    );
  }
}

class CustomSliverPersistentHeaderDelegate
    extends SliverPersistentHeaderDelegate {
  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return LayoutBuilder(builder: (_, constraints) {


      final t = shrinkOffset / maxExtent;
      final width = constraints.maxWidth;
      final itemMaxWidth = width / 4;

      double xFactor = -.4;
      return ColoredBox(
        color: Colors.cyanAccent.withOpacity(.3),
        child: Stack(
          children: [
            Align(
              alignment:
                  Alignment.lerp(Alignment.center, Alignment(xFactor, -.2), t)!
                    ..x,
              child: buildRow(
                  color: Colors.deepPurple, itemMaxWidth: itemMaxWidth, t: t),
            ),
            Align(
              alignment: Alignment.lerp(
                  Alignment.centerRight, Alignment(xFactor, 0), t)!,
              child:
                  buildRow(color: Colors.red, itemMaxWidth: itemMaxWidth, t: t),
            ),
            Align(
              alignment: Alignment.lerp(
                  Alignment.centerLeft, Alignment(xFactor, .2), t)!,
              child: buildRow(
                  color: Colors.amber, itemMaxWidth: itemMaxWidth, t: t),
            ),
          ],
        ),
      );
    });
  }

  Container buildRow(
      {required Color color, required double itemMaxWidth, required double t}) {
    return Container(
      width: lerpDouble(itemMaxWidth, itemMaxWidth * .3, t),
      height: lerpDouble(itemMaxWidth, itemMaxWidth * .3, t),
      color: color,
    );
  }
/// you need to increase when it it not pinned 
  @override
  double get maxExtent => 400;

  @override
  double get minExtent => 300;

  @override
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
    return false;
  }
}

Flutter相关问答推荐

如何从外部控制有状态窗口小部件本身?

查询满足AND条件的文档的FiRestore

框中的Flutter 适配图像

如何从RealmResults获取Flutter Flutter 流?

参数类型';List<;Dynamic&>不能分配给参数类型';List<;SingleChildWidget&>';

Flutter 渲染HTML和数学(LaTeX和Katex)

了解多Provider 和流

Flutter:使用不包含导航器的上下文请求导航器操作

要禁用按钮上的通知声音,请点击Flutter

网页浏览器不支持鼠标滚动的行项目

围绕父组件旋转位置组件

如何将行推到列的底部

如何删除或隐藏覆盖

Flutter Dart 功能弹出错误的小部件?

如何在 GridView.builder 中设置 textform 字段并在 flutter 中将 12 个 textformfield 作为单个字符串获取?

Flutter中如何连续获取TextField的文本是否为空?

Banner Ad.test 广告单元 ID 是否已过时?

扫描flutter生成的二维码后如何弹出文本字段值

如何将变量翻译成其他语言

Android Studio 模拟器屏幕闪烁