1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.quickstep.util;
17 
18 import android.annotation.CallSuper;
19 import android.view.Surface.Rotation;
20 import android.view.View;
21 import android.view.ViewGroup;
22 import android.view.WindowManager;
23 
24 import androidx.annotation.MainThread;
25 
26 import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator;
27 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
28 import com.android.systemui.unfold.dagger.UnfoldMain;
29 import com.android.systemui.unfold.updates.RotationChangeProvider;
30 
31 import java.util.HashMap;
32 import java.util.Map;
33 
34 /**
35  * Animation that moves launcher icons and widgets from center to the sides (final position)
36  */
37 public abstract class BaseUnfoldMoveFromCenterAnimator implements TransitionProgressListener {
38 
39     private final UnfoldMoveFromCenterAnimator mMoveFromCenterAnimation;
40     @UnfoldMain private final RotationChangeProvider mRotationChangeProvider;
41 
42     private final Map<ViewGroup, Boolean> mOriginalClipToPadding = new HashMap<>();
43     private final Map<ViewGroup, Boolean> mOriginalClipChildren = new HashMap<>();
44 
45     private final UnfoldMoveFromCenterRotationListener mRotationListener =
46             new UnfoldMoveFromCenterRotationListener();
47     private boolean mAnimationInProgress = false;
48 
49     // Save the last transition progress so we can re-apply it in case we re-register the view for
50     // the animation (by calling onPrepareViewsForAnimation)
51     private Float mLastTransitionProgress = null;
52 
BaseUnfoldMoveFromCenterAnimator(WindowManager windowManager, @UnfoldMain RotationChangeProvider rotationChangeProvider)53     public BaseUnfoldMoveFromCenterAnimator(WindowManager windowManager,
54             @UnfoldMain RotationChangeProvider rotationChangeProvider) {
55         mMoveFromCenterAnimation = new UnfoldMoveFromCenterAnimator(windowManager,
56                 new LauncherViewsMoveFromCenterTranslationApplier());
57         mRotationChangeProvider = rotationChangeProvider;
58     }
59 
60     @CallSuper
61     @Override
onTransitionStarted()62     public void onTransitionStarted() {
63         mAnimationInProgress = true;
64         mMoveFromCenterAnimation.updateDisplayProperties();
65         onPrepareViewsForAnimation();
66         mRotationChangeProvider.addCallback(mRotationListener);
67     }
68 
69     @CallSuper
70     @Override
onTransitionProgress(float progress)71     public void onTransitionProgress(float progress) {
72         mMoveFromCenterAnimation.onTransitionProgress(progress);
73         mLastTransitionProgress = progress;
74     }
75 
76     @CallSuper
77     @Override
onTransitionFinished()78     public void onTransitionFinished() {
79         mLastTransitionProgress = null;
80         mAnimationInProgress = false;
81         mRotationChangeProvider.removeCallback(mRotationListener);
82         mMoveFromCenterAnimation.onTransitionFinished();
83         clearRegisteredViews();
84     }
85 
86     /**
87      * Re-prepares views for animation. This is useful in case views are re-bound while the
88      * animation is in progress.
89      */
updateRegisteredViewsIfNeeded()90     public void updateRegisteredViewsIfNeeded() {
91         if (mAnimationInProgress) {
92             clearRegisteredViews();
93             onPrepareViewsForAnimation();
94         }
95     }
96 
clearRegisteredViews()97     private void clearRegisteredViews() {
98         restoreClippings();
99         mMoveFromCenterAnimation.clearRegisteredViews();
100 
101         mOriginalClipChildren.clear();
102         mOriginalClipToPadding.clear();
103     }
104 
105     @CallSuper
onPrepareViewsForAnimation()106     protected void onPrepareViewsForAnimation() {
107         if (mLastTransitionProgress != null) {
108             mMoveFromCenterAnimation.onTransitionProgress(mLastTransitionProgress);
109         }
110     }
111 
registerViewForAnimation(View view)112     protected void registerViewForAnimation(View view) {
113         mMoveFromCenterAnimation.registerViewForAnimation(view);
114     }
115 
116     /**
117      * Sets clipToPadding for the view which then could be restored to the original value
118      * using {@link BaseUnfoldMoveFromCenterAnimator#restoreClippings} method call
119      * @param view view to set the property
120      * @param clipToPadding value of the property
121      */
setClipToPadding(ViewGroup view, boolean clipToPadding)122     protected void setClipToPadding(ViewGroup view, boolean clipToPadding) {
123         mOriginalClipToPadding.put(view, view.getClipToPadding());
124         view.setClipToPadding(clipToPadding);
125     }
126 
127     /**
128      * Sets clipChildren for the view which then could be restored to the original value
129      * using {@link BaseUnfoldMoveFromCenterAnimator#restoreClippings} method call
130      * @param view view to set the property
131      * @param clipChildren value of the property
132      */
setClipChildren(ViewGroup view, boolean clipChildren)133     protected void setClipChildren(ViewGroup view, boolean clipChildren) {
134         mOriginalClipChildren.put(view, view.getClipChildren());
135         view.setClipChildren(clipChildren);
136     }
137 
138     /**
139      * Restores original clip properties after their modifications
140      */
restoreClippings()141     protected void restoreClippings() {
142         mOriginalClipToPadding.forEach(ViewGroup::setClipToPadding);
143         mOriginalClipChildren.forEach(ViewGroup::setClipChildren);
144     }
145 
146     private class UnfoldMoveFromCenterRotationListener implements
147             RotationChangeProvider.RotationListener {
148 
149         @MainThread
150         @Override
onRotationChanged(@otation int newRotation)151         public void onRotationChanged(@Rotation int newRotation) {
152             onRotationChangedInternal(newRotation);
153         }
154 
155         @MainThread
onRotationChangedInternal(@otation int newRotation)156         private void onRotationChangedInternal(@Rotation int newRotation) {
157             mMoveFromCenterAnimation.updateDisplayProperties(newRotation);
158             updateRegisteredViewsIfNeeded();
159         }
160     }
161 }
162