我怎样才能有一个像这样的动画SliverAppBar?

Ser*_*ğlu 2 user-interface animation dart visual-studio-code flutter

这是 SliverAppBar 扩展\n这是折叠的 SliverAppBar

\n

我希望这些动画之间能够平滑,我尝试使用AnimatedSizeAnimatedOpacityAnimatedPositioned几乎没有错误。而且我不知道如何将它们与SliverAppBar. 在其他示例中,我看到人们使用LayoutBuilder但他们没有共享完整的代码,因此我无法测试它。我将分享我的代码片段,但它在两种状态之间有一个非常奇怪的转换。

\n

我想要CircleAvatar变小并改变位置\n我想要Icon(Icons.arrow_back)Text(\'Previous Page\')消失。\n我也希望我的名字和工作消失。\n我希望那三个Containers变小并改变位置。

\n
import \'package:flutter/material.dart\';\n\nvoid main() {\n  runApp(MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  // This widget is the root of your application.\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \'Dialog Demo\',\n      debugShowCheckedModeBanner: false,\n      theme: ThemeData(\n        primarySwatch: Colors.blue,\n      ),\n      home: Scaffold(\n        body: CustomScrollView(\n          slivers: [\n            SliverAppBar(\n              elevation: 0,\n              pinned: true,\n              expandedHeight: 190,\n              collapsedHeight: kToolbarHeight + 8,\n              flexibleSpace: FlexibleSpaceBar(\n                collapseMode: CollapseMode.none,\n                centerTitle: true,\n                titlePadding: EdgeInsetsDirectional.only(\n                  start: 20.0,\n                  end: 20.0,\n                  top: 12.0,\n                  bottom: 12.0,\n                ),\n                title: SafeArea(\n                  child: Column(\n                    children: [\n                      Row(\n                        mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                        children: [\n                          CircleAvatar(\n                            radius: 16,\n                          ),\n                          Row(\n                            children: [\n                              Container(\n                                decoration: BoxDecoration(\n                                  color: Colors.white10,\n                                  borderRadius: BorderRadius.all(\n                                    Radius.circular(12),\n                                  ),\n                                ),\n                                padding: EdgeInsets.all(8.0),\n                                child: Icon(Icons.person),\n                              ),\n                              SizedBox(\n                                width: 8,\n                              ),\n                              Container(\n                                decoration: BoxDecoration(\n                                  color: Colors.white10,\n                                  borderRadius: BorderRadius.all(\n                                    Radius.circular(12),\n                                  ),\n                                ),\n                                padding: EdgeInsets.all(8.0),\n                                child: Icon(Icons.menu),\n                              ),\n                              SizedBox(\n                                width: 8,\n                              ),\n                              Container(\n                                decoration: BoxDecoration(\n                                  color: Colors.white10,\n                                  borderRadius: BorderRadius.all(\n                                    Radius.circular(12),\n                                  ),\n                                ),\n                                padding: EdgeInsets.all(8.0),\n                                child: Icon(Icons.message),\n                              ),\n                            ],\n                          ),\n                        ],\n                      ),\n                    ],\n                  ),\n                ),\n                background: SafeArea(\n                  child: Column(\n                    children: [\n                      Container(\n                        alignment: Alignment.topLeft,\n                        child: Row(\n                          children: [\n                            IconButton(\n                              icon: Icon(Icons.arrow_back),\n                              onPressed: () {},\n                            ),\n                            Text(\n                              \'PREVIOUS PAGE\',\n                              style: TextStyle(\n                                fontSize: 12,\n                                fontWeight: FontWeight.bold,\n                              ),\n                            ),\n                          ],\n                        ),\n                      ),\n                      Padding(\n                        padding: const EdgeInsets.only(\n                          left: 20,\n                          top: 12,\n                          bottom: 24,\n                        ),\n                        child: Row(\n                          crossAxisAlignment: CrossAxisAlignment.start,\n                          children: [\n                            CircleAvatar(\n                              radius: 20,\n                            ),\n                            SizedBox(\n                              width: 12,\n                            ),\n                            Column(\n                              crossAxisAlignment: CrossAxisAlignment.start,\n                              children: [\n                                Text(\n                                  \'Sertan Hakk\xc4\xb1 \xc4\xb0mamo\xc4\x9flu\',\n                                  style: TextStyle(\n                                    fontSize: 18,\n                                    color: Colors.white,\n                                    fontWeight: FontWeight.bold,\n                                  ),\n                                ),\n                                Text(\n                                  \'Student\',\n                                  style: TextStyle(\n                                    fontSize: 14,\n                                    color: Colors.grey,\n                                  ),\n                                ),\n                                SizedBox(\n                                  height: 12,\n                                ),\n                                Row(\n                                  children: [\n                                    Container(\n                                      decoration: BoxDecoration(\n                                        color: Colors.white10,\n                                        borderRadius: BorderRadius.all(\n                                          Radius.circular(12),\n                                        ),\n                                      ),\n                                      padding: EdgeInsets.symmetric(\n                                        horizontal: 34,\n                                        vertical: 12,\n                                      ),\n                                      child: Icon(Icons.menu),\n                                    ),\n                                    SizedBox(\n                                      width: 4,\n                                    ),\n                                    Container(\n                                      decoration: BoxDecoration(\n                                        color: Colors.white10,\n                                        borderRadius: BorderRadius.all(\n                                          Radius.circular(12),\n                                        ),\n                                      ),\n                                      padding: EdgeInsets.symmetric(\n                                        horizontal: 34,\n                                        vertical: 12,\n                                      ),\n                                      child: Icon(Icons.person),\n                                    ),\n                                    SizedBox(\n                                      width: 4,\n                                    ),\n                                    Container(\n                                      decoration: BoxDecoration(\n                                        color: Colors.white10,\n                                        borderRadius: BorderRadius.all(\n                                          Radius.circular(12),\n                                        ),\n                                      ),\n                                      padding: EdgeInsets.symmetric(\n                                        horizontal: 34,\n                                        vertical: 12,\n                                      ),\n                                      child: Icon(Icons.message),\n                                    ),\n                                  ],\n                                )\n                              ],\n                            )\n                          ],\n                        ),\n                      ),\n                    ],\n                  ),\n                ),\n              ),\n            ),\n            SliverList(\n              delegate: SliverChildBuilderDelegate(\n                (BuildContext context, int index) {\n                  return Container(\n                    color: index.isOdd ? Colors.white : Colors.black12,\n                    height: 100.0,\n                    child: Center(\n                      child: Text(\'$index\', textScaleFactor: 5),\n                    ),\n                  );\n                },\n                childCount: 20,\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Gui*_*oux 5

这是我对您的问题的看法,正如pskink所建议的那样,我已经使用了 aSliverPersistentHeader并尝试使其具有响应性,以便当尺寸减小时它有一点动画。

\n

示例代码

\n
class CustomPageHeader extends SliverPersistentHeaderDelegate {\n  CustomPageHeader({\n    required double collapsedHeight,\n    required double expandedHeight,\n  }) : minExtent = collapsedHeight, maxExtent = expandedHeight;\n\n  @override\n  final double minExtent;\n\n  @override\n  final double maxExtent;\n\n  Widget _buildBtn(IconData icon, double scale) {\n    double horizontal = 34.0 * scale;\n    horizontal = horizontal < 8 ? 8.0 : horizontal;\n\n    double vertical = 12.0 * scale;\n    vertical = vertical < 8 ? 8.0 : vertical;\n\n    return Container(\n      decoration: const BoxDecoration(\n        color: Colors.white10,\n        borderRadius: BorderRadius.all(\n          Radius.circular(12),\n        ),\n      ),\n      padding: EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical),\n      child: Icon(icon),\n    );\n  }\n\n  @override\n  Widget build(\n      BuildContext context, double shrinkOffset, bool overlapsContent) {\n    final theme = Theme.of(context);\n    final backgroundColor =\n        theme.appBarTheme.backgroundColor ?? theme.colorScheme.primary;\n    final scale = 1 - shrinkOffset / maxExtent;\n    final isReduced = shrinkOffset >= maxExtent * 0.12;\n    final wrappedBtns = Wrap(\n      spacing: 8,\n      children: [\n        _buildBtn(Icons.menu, scale),\n        _buildBtn(Icons.person, scale),\n        _buildBtn(Icons.message, scale),\n      ],\n    );\n    \n    double avatarRadius = 20.0 * scale;\n    avatarRadius = avatarRadius > 16 ? avatarRadius : 16.0;\n\n    return Container(\n      padding: const EdgeInsets.only(\n        left: 20,\n        top: 12,\n        bottom: 12,\n      ),\n      color: backgroundColor,\n      child: Column(\n        children: [\n          Row(\n            crossAxisAlignment: CrossAxisAlignment.start,\n            children: [\n              CircleAvatar(radius: avatarRadius),\n              !isReduced\n                  ? const SizedBox(width: 12)\n                  : Expanded(child: Container()),\n              Column(\n                crossAxisAlignment: CrossAxisAlignment.start,\n                children: [\n                  if (!isReduced)\n                    Text(\n                      \'Sertan Hakk\xc4\xb1 \xc4\xb0mamo\xc4\x9flu\',\n                      style: TextStyle(\n                        fontSize: 18 * scale,\n                        color: Colors.white,\n                        fontWeight: FontWeight.bold,\n                      ),\n                    ),\n                  if (!isReduced)\n                    Text(\n                      \'Student\',\n                      style: TextStyle(\n                        fontSize: 14 * scale,\n                        color: Colors.grey,\n                      ),\n                    ),\n                ],\n              ),\n              if (isReduced) wrappedBtns,\n            ],\n          ),\n          Flexible(\n            child: Container(\n              constraints: const BoxConstraints(maxHeight: 12),\n            ),\n          ),\n          if (!isReduced) wrappedBtns,\n        ],\n      ),\n    );\n  }\n\n  @override\n  bool shouldRebuild(_) => true;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在你的条子列表中使用它,如下所示:

\n
SliverPersistentHeader(\n  pinned: true,\n  delegate: CustomPageHeader(\n    collapsedHeight: kToolbarHeight + 8,\n    expandedHeight: 190,\n  ),\n),\n
Run Code Online (Sandbox Code Playgroud)\n

在 DartPad 上尝试完整的测试代码

\n

该代码是完美的,但应该对您有足够的帮助,以便您可以改进它并自己继续。

\n