Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent scrolled Hero from jumping on top of the app bar

Tags:

flutter

dart

I have a Hero that can be scrolled so that part of it is offscreen. When I trigger a transition, it appears to abruptly jump on top of the AppBar and then jumps back under it when the transition is reversed. How do I force the AppBar to stay on top of the Hero?

video

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(),
      ),
    );
  }
}
like image 827
Collin Jackson Avatar asked Aug 25 '17 19:08

Collin Jackson


2 Answers

Wrap your AppBar in a Hero to force it to stay on top.

  appBar: new PreferredSize(
    child: new Hero(
      tag: AppBar,
      child: new AppBar(
        title: new Text('All Logos'),
      ),
    ),
    preferredSize: new AppBar().preferredSize,
  ),

For the AppBar of the detail page, I would recommend forcing the back button to be displayed so that it appears at the same time that the page title changes.

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

Here's what it looks like:

video

like image 126
Collin Jackson Avatar answered Nov 19 '22 20:11

Collin Jackson


i've fixed it here https://github.com/zombie6888/scrolled_hero by providing bottom and top offset to hero animation builder

like image 2
Sergey Zhukov Avatar answered Nov 19 '22 21:11

Sergey Zhukov