Skip to content

Conversation

@Salby
Copy link
Contributor

@Salby Salby commented Sep 11, 2019

Description

Adds a new transitions builder imitating the new default page transition in Android 10/Q. The default transition is still the old FadeUpwardsPageTransitionsBuilder, so you have to manually set the pageTransitionsTheme like this:

pageTransitionsTheme: const PageTransitionsTheme(
  builders: <TargetPlatform, PageTransitionsBuilder>{
    TargetPlatform.android: ZoomingPageTransitionsBuilder(),
    ...
  },
),

Video of this transition in action: Google Drive

Related Issues

Tests

I added the following tests:

  • pageTranstionsTheme override builds a _ZoomingPageTransition for android

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require Flutter developers to manually update their apps to accommodate your change?

  • No, this is not a breaking change.

@fluttergithubbot fluttergithubbot added f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. labels Sep 11, 2019
@Zazo032
Copy link
Contributor

Zazo032 commented Sep 11, 2019

As this will be the default behavior for Android 10+ versions, should this be the default behavior in the Material library?

@Salby
Copy link
Contributor Author

Salby commented Sep 11, 2019

It was mentioned in #39812 that the ideal behaviour would be to automatically detect the Android version and then switch the pageTransitionsTheme. I like that idea, but I thought it was a bit out of scope for this PR.

@HansMuller
Copy link
Contributor

I had looked into this transition very recently. Here's what I came up with.

The "fastOutExtraSlowIn" curve used to animate is defined like this:

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:pathData="M 0,0 C 0.05, 0, 0.133333, 0.06, 0.166666, 0.4 C 0.208333, 0.82, 0.25, 1, 1, 1"/>

This curve is used to animate the scale of the incoming page from 85% to 100% over 400ms. The outgoing route is scaled with the same curve and duration, from 100% to 105%.

You can see what fastOutExtraSlowIn curve looks like by pasting the following into svgpad:

<svg version="1.1" x="0px" y="0px" width="400px" height="400px" viewBox="0 -1 1 1">
  <g transform="scale(1,-1)">
  <rect x="0" y="0" height="1" width="1" stroke="lightgrey" fill="none" stroke-width="0.01"/>
  <path d="M 0,0 C 0.05, 0, 0.133333, 0.06, 0.166666, 0.4 C 0.208333, 0.82, 0.25, 1, 1, 1" stroke="black" fill="none" stroke-width="0.005" />
</svg>

svg_curve

The curve can be approximated with a TweenSequence:

final TweenSequence<double> scaleCurveSequence = TweenSequence<double>(
  <TweenSequenceItem<double>>[
    TweenSequenceItem<double>(
      tween: Tween<double>(begin: 0.0, end: 0.4)
        .chain(CurveTween(curve: Cubic(0.05, 0.0, 0.133333, 0.06))),
      weight: 0.166666,
    ),
    TweenSequenceItem<double>(
      tween: Tween<double>(begin: 0.4, end: 1.0)
        .chain(CurveTween(curve: Cubic(0.208333, 0.82, 0.25, 1.0))),
      weight: 1 - 0.166666,
    ),
  ],
);

sequence_curve

The scale animations can be defined like this, and used with a ScaleTransition.

Animation<double> incomingScaleAnimation = Tween<double>(begin: 0.85, end: 1.0)
  .chain(scaleCurveSequence)
  .animate(_controller);

Animation<double> outgoingScaleAnimation = Tween<double>(begin: 1.0, end: 1.05)
  .chain(scaleCurveSequence)
  .animate(_controller);

@Salby
Copy link
Contributor Author

Salby commented Sep 12, 2019

Here's a video of the transition with the new curve sequence: Google Drive

@Salby
Copy link
Contributor Author

Salby commented Sep 16, 2019

I am having some trouble making a flipped version of this sequence. I want to flip the acceleration when reversing the transition.

With a regular Curve I could use Curve.flipped to flip the curve when reversing the transition, but I can't seem to figure out how to do it to this sequence.

static final TweenSequence<double> _scaleCurveSequence = TweenSequence<double>(
    <TweenSequenceItem<double>>[
      TweenSequenceItem<double>(
        tween: Tween<double>(begin: 0.0, end: 0.4)
            .chain(CurveTween(curve: _scaleCurveBeginning)),
        weight: 0.166666,
      ),
      TweenSequenceItem<double>(
        tween: Tween<double>(begin: 0.4, end: 1.0)
            .chain(CurveTween(curve: _scaleCurveEnd)),
        weight: 1.0 - 0.166666,
      ),
    ],
  );

@shihaohong
Copy link
Contributor

Hi @Salby, the backwards transition for this isn't simply the flipped implementation of the forwards transition curve. It still uses the fastOutExtraSlowIn curve, but you should use the following scaling (also over 400ms):

Animation<double> incomingScaleAnimation = Tween<double>(begin: 1.10, end: 1.0)
  .chain(scaleCurveSequence)
  .animate(_controller);

Animation<double> outgoingScaleAnimation = Tween<double>(begin: 1.0, end: 0.90)
  .chain(scaleCurveSequence)
  .animate(_controller);

@shihaohong
Copy link
Contributor

shihaohong commented Sep 16, 2019

Some other details that we missed out previously:
Forward Transition
End screen opacity: 0% to 100% opacity, linear curve. Starts at 50ms and lasts for 50ms
Scrim opacity: 0% to 60% black, linear curve. Starts at 83ms and lasts for 167ms

Backward transition
Start screen opacity (fade out): 100% to 0% opacity, linear curve, starts at 33ms and lasts for 50ms

Edit: Let me know if you have any more clarification questions about the details of the transition, and I'll do my best to clear up any confusion.

@shihaohong shihaohong self-assigned this Sep 16, 2019
@shihaohong shihaohong added the c: new feature Nothing broken; request for a new capability label Sep 16, 2019
@Salby
Copy link
Contributor Author

Salby commented Sep 17, 2019

I am having some trouble with the backward transition.

Since I'm not in control of the AnimationController I am forced to animate from 1.0 to 0.0 when the transition is reversing. This means that if I can't flip the curve sequence it's not going to be a very smooth transition when reversing.

The other transitions are built like this, they just take two AnimationControllers and a child and work with those, but they also use Cubic Beziér curves for the easing of the animation, so they can be easily flipped when reversing the transition, which I can't seem to do with the fastOutExtraSlowIn curve sequence.

Another solution might be to make _ZoomingPageTransition a stateful widget with it's own AnimationControllers, but that doesn't feel right to me, just throwing away the AnimationControllers that have already been created.

Edit: This is how the transition looks currently: Google drive.

@shihaohong
Copy link
Contributor

Hi @Salby, I've been out for a little over a week and might be out for up to another week. When
I'm back, I'll do some tinkering with animation and these curves on my own and see what we can do to move this forward. Thank you for your patience!

@shihaohong
Copy link
Contributor

I've started looking into working on the transition as well -- I'm currently stuck on the same piece as you and trying to reverse the TweenSequence. I'll update my WIP PR if I make any headway with it!

@Salby Salby changed the title [Android 10] Added zooming page transition [WIP] [Android 10] Added zooming page transition Oct 4, 2019
@Salby Salby changed the title [WIP] [Android 10] Added zooming page transition [WIP] - [Android 10] Added zooming page transition Oct 4, 2019
@Salby Salby changed the title [WIP] - [Android 10] Added zooming page transition WIP - [Android 10] Added zooming page transition Oct 4, 2019
@shihaohong
Copy link
Contributor

I will close this issue since my PR with the Zoom transition has been merged. Thank you so much for your initial contribution!

@shihaohong shihaohong closed this Oct 22, 2019
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

c: new feature Nothing broken; request for a new capability f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants