防止滚动的Hero跳到应用栏顶部

Col*_*son 8 dart flutter

我有一个Hero可以滚动的屏幕,所以它的一部分不在屏幕上。当我触发转换时,它似乎突然跳到的顶部,AppBar然后在转换反向时又跳回到其下方。如何强制AppBar保持在顶部Hero

视频

import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(
    home: new Example(),
    theme: new ThemeData(primaryColor: Colors.orange),
    debugShowCheckedModeBanner: false,
  ));
}

Widget positionHeroOverlay(BuildContext context, Widget overlay, Rect rect, Size size) {
  final RelativeRect offsets = new RelativeRect.fromSize(rect, size);
  return new Positioned(
    top: offsets.top,
    right: offsets.right,
    bottom: offsets.bottom,
    left: offsets.left,
    child: overlay,
  );
}

class LogoPageRoute extends MaterialPageRoute<Null> {
  LogoPageRoute(this.colors) : super(
    builder: (BuildContext context) {
      return new Scaffold(
        appBar: new AppBar(
          title: new Text('Flutter Logo'),
        ),
        body: new ConstrainedBox(
          constraints: new BoxConstraints.expand(),
          child: new Hero(
            tag: colors,
            child: new FlutterLogo(colors: colors),
          ),
        ),
      );
    },
  );

  /// The color of logo to display
  final MaterialColor colors;

  @override
  final Duration transitionDuration = const Duration(seconds: 1);
}

final List<MaterialColor> swatches = [
  Colors.blue,
  Colors.orange,
  Colors.green,
];

class Example extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('All Logos'),
      ),
      body: new ListView(
        children: swatches.map((MaterialColor colors) {
          return new InkWell(
            onTap: () {
              Navigator.push(context, new LogoPageRoute(colors));
            },
            child: new Hero(
              tag: colors,
              child: new FlutterLogo(size: 360.0, colors: colors),
            ),
          );
        }).toList(),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

Col*_*son 6

把你的包AppBar起来,Hero迫使它留在上面。

  appBar: new PreferredSize(
    child: new Hero(
      tag: AppBar,
      child: new AppBar(
        title: new Text('All Logos'),
      ),
    ),
    preferredSize: new AppBar().preferredSize,
  ),
Run Code Online (Sandbox Code Playgroud)

对于AppBar详细信息页面,我建议强制显示后退按钮,以便它在页面标题更改的同时出现。

    appBar: new PreferredSize(
      child: new Hero(
        tag: AppBar,
        child: new AppBar(
          leading: const BackButton(),
          title: new Text('Flutter Logo'),
        ),
      ),
      preferredSize: new AppBar().preferredSize,
    ),
Run Code Online (Sandbox Code Playgroud)

它看起来是这样的:

视频

  • 考虑到 Hero 使用 Navigator 覆盖层,我认为如果没有大量工作或无法维护的代码,就不可能拥有完全相同的动画。 (3认同)
  • 不过,您失去了应用栏的滑动过渡。 (2认同)