Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 465c2c07 authored by Lyn Han's avatar Lyn Han
Browse files

Save and later cancel ViewPropertyAnimator on bubble view tag

When a bubble autoexpands (via button button)
 1) order changes and reorder animations start
 2) active controller changes from StackAnimationController to ExpandedAnimationController
 3) the stack expands
 4) PhysicalAnimationLayout doesn't find reorder animations by tag, so they don't get canceled
 5) the "swoop up" reorder animation runs right after expansion completes

This change saves StackAnimationController's reorder animators on bubble
view so that PhysicsAnimationLayout cancels it when the active
controller changes to ExpandedAnimationController.

Fixes: 171850447
Bug: 170267512
Test: manual
 1) Unbubble notif
 2) Send another bubbling notif => HUN shows
 3) Tap HUN's bubble button
     => See that bubble autoexpands without leftover reorder animation
Change-Id: Idd0543659a65fddba4b4fc5bee0ff7b9aad8b352
parent fa010049
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -155,6 +155,7 @@
    <item type="id" name="scale_y_dynamicanimation_tag"/>
    <item type="id" name="physics_animator_tag"/>
    <item type="id" name="target_animator_tag" />
    <item type="id" name="reorder_animator_tag"/>

    <!-- Global Actions Menu -->
    <item type="id" name="global_actions_view" />
+26 −10
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.util.FloatProperty;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.widget.FrameLayout;

import androidx.annotation.Nullable;
@@ -385,7 +386,7 @@ public class PhysicsAnimationLayout extends FrameLayout {
            View view, DynamicAnimation.ViewProperty... properties) {
        final ObjectAnimator targetAnimator = getTargetAnimatorFromView(view);
        for (DynamicAnimation.ViewProperty property : properties) {
            final SpringAnimation animation = getAnimationFromView(property, view);
            final SpringAnimation animation = getSpringAnimationFromView(property, view);
            if (animation != null && animation.isRunning()) {
                return true;
            }
@@ -422,11 +423,15 @@ public class PhysicsAnimationLayout extends FrameLayout {

        for (int i = 0; i < getChildCount(); i++) {
            for (DynamicAnimation.ViewProperty property : properties) {
                final DynamicAnimation anim = getAnimationAtIndex(property, i);
                final DynamicAnimation anim = getSpringAnimationAtIndex(property, i);
                if (anim != null) {
                    anim.cancel();
                }
            }
            final ViewPropertyAnimator anim = getViewPropertyAnimatorFromView(getChildAt(i));
            if (anim != null) {
                anim.cancel();
            }
        }
    }

@@ -441,7 +446,7 @@ public class PhysicsAnimationLayout extends FrameLayout {

        // Cancel physics animations on the view.
        for (DynamicAnimation.ViewProperty property : mController.getAnimatedProperties()) {
            final DynamicAnimation animationFromView = getAnimationFromView(property, view);
            final DynamicAnimation animationFromView = getSpringAnimationFromView(property, view);
            if (animationFromView != null) {
                animationFromView.cancel();
            }
@@ -502,17 +507,27 @@ public class PhysicsAnimationLayout extends FrameLayout {
     * Retrieves the animation of the given property from the view at the given index via the view
     * tag system.
     */
    @Nullable private SpringAnimation getAnimationAtIndex(
    @Nullable private SpringAnimation getSpringAnimationAtIndex(
            DynamicAnimation.ViewProperty property, int index) {
        return getAnimationFromView(property, getChildAt(index));
        return getSpringAnimationFromView(property, getChildAt(index));
    }

    /** Retrieves the animation of the given property from the view via the view tag system. */
    @Nullable private SpringAnimation getAnimationFromView(
    /**
     * Retrieves the spring animation of the given property from the view via the view tag system.
     */
    @Nullable private SpringAnimation getSpringAnimationFromView(
            DynamicAnimation.ViewProperty property, View view) {
        return (SpringAnimation) view.getTag(getTagIdForProperty(property));
    }

    /**
     * Retrieves the view property animation of the given property from the view via the view tag
     * system.
     */
    @Nullable private ViewPropertyAnimator getViewPropertyAnimatorFromView(View view) {
        return (ViewPropertyAnimator) view.getTag(R.id.reorder_animator_tag);
    }

    /** Retrieves the target animator from the view via the view tag system. */
    @Nullable private ObjectAnimator getTargetAnimatorFromView(View view) {
        return (ObjectAnimator) view.getTag(R.id.target_animator_tag);
@@ -539,7 +554,8 @@ public class PhysicsAnimationLayout extends FrameLayout {

            final float offset = mController.getOffsetForChainedPropertyAnimation(property);
            if (nextAnimInChain < getChildCount()) {
                final SpringAnimation nextAnim = getAnimationAtIndex(property, nextAnimInChain);
                final SpringAnimation nextAnim = getSpringAnimationAtIndex(
                        property, nextAnimInChain);
                if (nextAnim != null) {
                    nextAnim.animateToFinalPosition(value + offset);
                }
@@ -902,9 +918,9 @@ public class PhysicsAnimationLayout extends FrameLayout {
            // and TRANSLATION_Y animations ending, and call them once both have finished.
            if (mPositionEndActions != null) {
                final SpringAnimation translationXAnim =
                        getAnimationFromView(DynamicAnimation.TRANSLATION_X, mView);
                        getSpringAnimationFromView(DynamicAnimation.TRANSLATION_X, mView);
                final SpringAnimation translationYAnim =
                        getAnimationFromView(DynamicAnimation.TRANSLATION_Y, mView);
                        getSpringAnimationFromView(DynamicAnimation.TRANSLATION_Y, mView);
                final Runnable waitForBothXAndY = () -> {
                    if (!translationXAnim.isRunning() && !translationYAnim.isRunning()) {
                        if (mPositionEndActions != null) {
+15 −7
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.graphics.RectF;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.ViewPropertyAnimator;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -795,12 +796,15 @@ public class StackAnimationController extends
        final float swapY = newIndex == 0
                ? newY - mSwapAnimationOffset  // Above top of stack
                : newY + mSwapAnimationOffset;  // Below where bubble will be
        view.animate()
        final ViewPropertyAnimator animator = view.animate()
                .scaleX(BUBBLE_SWAP_SCALE)
                .scaleY(BUBBLE_SWAP_SCALE)
                .translationY(swapY)
                .setDuration(BUBBLE_SWAP_DURATION)
                .withEndAction(() -> finishSwapAnimation(view, oldIndex, newIndex, finishReorder));
                .withEndAction(() -> {
                    finishSwapAnimation(view, oldIndex, newIndex, finishReorder);
                });
        view.setTag(R.id.reorder_animator_tag, animator);
    }

    private void finishSwapAnimation(View view, int oldIndex, int newIndex,
@@ -818,12 +822,16 @@ public class StackAnimationController extends

        // Animate bubble back into stack, at new index and original size.
        final float newY = getStackPosition().y + newIndex * mStackOffset;
        view.animate()
        final ViewPropertyAnimator animator = view.animate()
                .scaleX(1f)
                .scaleY(1f)
                .translationY(newY)
                .setDuration(BUBBLE_SWAP_DURATION)
                .withEndAction(() -> finishReorder.run());
                .withEndAction(() -> {
                    view.setTag(R.id.reorder_animator_tag, null);
                    finishReorder.run();
                });
        view.setTag(R.id.reorder_animator_tag, animator);
    }

    @Override