Merge "Fix clip reveal animation in docked window case" into nyc-dev
This commit is contained in:
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.view.animation;
|
||||
|
||||
import android.graphics.Rect;
|
||||
|
||||
/**
|
||||
* Special case of ClipRectAnimation that animates only the top/bottom
|
||||
* dimensions of the clip, picking up the other dimensions from whatever is
|
||||
* set on the transform already.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ClipRectTBAnimation extends ClipRectAnimation {
|
||||
|
||||
/**
|
||||
* Constructor. Passes in 0 for Left/Right parameters of ClipRectAnimation
|
||||
*/
|
||||
public ClipRectTBAnimation(int fromT, int fromB, int toT, int toB) {
|
||||
super(0, fromT, 0, fromB, 0, toT, 0, toB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates and sets clip rect on given transformation. It uses existing values
|
||||
* on the Transformation for Left/Right clip parameters.
|
||||
*/
|
||||
@Override
|
||||
protected void applyTransformation(float it, Transformation tr) {
|
||||
Rect oldClipRect = tr.getClipRect();
|
||||
tr.setClipRect(oldClipRect.left, mFromRect.top + (int) ((mToRect.top - mFromRect.top) * it),
|
||||
oldClipRect.right,
|
||||
mFromRect.bottom + (int) ((mToRect.bottom - mFromRect.bottom) * it));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -46,7 +46,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Debug;
|
||||
@@ -64,8 +63,6 @@ import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationSet;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.ClipRectAnimation;
|
||||
import android.view.animation.ClipRectLRAnimation;
|
||||
import android.view.animation.ClipRectTBAnimation;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
import android.view.animation.ScaleAnimation;
|
||||
@@ -74,10 +71,11 @@ import android.view.animation.TranslateAnimation;
|
||||
import com.android.internal.util.DumpUtils.Dump;
|
||||
import com.android.server.AttributeCache;
|
||||
import com.android.server.wm.WindowManagerService.H;
|
||||
import com.android.server.wm.animation.ClipRectLRAnimation;
|
||||
import com.android.server.wm.animation.ClipRectTBAnimation;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@@ -136,6 +134,16 @@ public class AppTransition implements Dump {
|
||||
private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.5f;
|
||||
|
||||
static final int DEFAULT_APP_TRANSITION_DURATION = 336;
|
||||
|
||||
/** Interpolator to be used for animations that respond directly to a touch */
|
||||
static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
|
||||
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
|
||||
|
||||
/**
|
||||
* Maximum duration for the clip reveal animation. This is used when there is a lot of movement
|
||||
* involved, to make it more understandable.
|
||||
*/
|
||||
private static final int MAX_CLIP_REVEAL_TRANSITION_DURATION = 420;
|
||||
private static final int THUMBNAIL_APP_TRANSITION_DURATION = 336;
|
||||
private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 336;
|
||||
private static final long APP_TRANSITION_TIMEOUT_MS = 5000;
|
||||
@@ -200,13 +208,10 @@ public class AppTransition implements Dump {
|
||||
private final Interpolator mFastOutLinearInInterpolator;
|
||||
private final Interpolator mClipHorizontalInterpolator = new PathInterpolator(0, 0, 0.4f, 1f);
|
||||
|
||||
/** Interpolator to be used for animations that respond directly to a touch */
|
||||
private final Interpolator mTouchResponseInterpolator =
|
||||
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
|
||||
|
||||
private final int mClipRevealTranslationY;
|
||||
|
||||
private int mCurrentUserId = 0;
|
||||
private long mLastClipRevealTransitionDuration = DEFAULT_APP_TRANSITION_DURATION;
|
||||
|
||||
private final ArrayList<AppTransitionListener> mListeners = new ArrayList<>();
|
||||
private final ExecutorService mDefaultExecutor = Executors.newSingleThreadExecutor();
|
||||
@@ -636,50 +641,101 @@ public class AppTransition implements Dump {
|
||||
bitmap, new Rect(left, top, left + width, top + height));
|
||||
}
|
||||
|
||||
private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame) {
|
||||
long getLastClipRevealTransitionDuration() {
|
||||
return mLastClipRevealTransitionDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the duration for the clip reveal animation. If the clip is "cut off", meaning that
|
||||
* the start rect is outside of the target rect, and there is a lot of movement going on.
|
||||
*
|
||||
* @param cutOff whether the start rect was not fully contained by the end rect
|
||||
* @param translationX the total translation the surface moves in x direction
|
||||
* @param translationY the total translation the surfaces moves in y direction
|
||||
* @param displayFrame our display frame
|
||||
*
|
||||
* @return the duration of the clip reveal animation, in milliseconds
|
||||
*/
|
||||
private long calculateClipRevealTransitionDuration(boolean cutOff, float translationX,
|
||||
float translationY, Rect displayFrame) {
|
||||
if (!cutOff) {
|
||||
return DEFAULT_APP_TRANSITION_DURATION;
|
||||
}
|
||||
final float fraction = Math.max(Math.abs(translationX) / displayFrame.width(),
|
||||
Math.abs(translationY) / displayFrame.height());
|
||||
return (long) (DEFAULT_APP_TRANSITION_DURATION + fraction *
|
||||
(MAX_CLIP_REVEAL_TRANSITION_DURATION - DEFAULT_APP_TRANSITION_DURATION));
|
||||
}
|
||||
|
||||
private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame,
|
||||
Rect displayFrame) {
|
||||
final Animation anim;
|
||||
if (enter) {
|
||||
// Reveal will expand and move faster in horizontal direction
|
||||
|
||||
final int appWidth = appFrame.width();
|
||||
final int appHeight = appFrame.height();
|
||||
|
||||
// mTmpRect will contain an area around the launcher icon that was pressed. We will
|
||||
// clip reveal from that area in the final area of the app.
|
||||
getDefaultNextAppTransitionStartRect(mTmpRect);
|
||||
|
||||
float t = 0f;
|
||||
if (appHeight > 0) {
|
||||
t = (float) mTmpRect.left / appHeight;
|
||||
t = (float) mTmpRect.top / displayFrame.height();
|
||||
}
|
||||
int translationY = mClipRevealTranslationY + (int)(appHeight / 7f * t);
|
||||
|
||||
int translationY = mClipRevealTranslationY + (int)(displayFrame.height() / 7f * t);
|
||||
int translationX = 0;
|
||||
int translationYCorrection = translationY;
|
||||
int centerX = mTmpRect.centerX();
|
||||
int centerY = mTmpRect.centerY();
|
||||
int halfWidth = mTmpRect.width() / 2;
|
||||
int halfHeight = mTmpRect.height() / 2;
|
||||
int clipStartX = centerX - halfWidth - appFrame.left;
|
||||
int clipStartY = centerY - halfHeight - appFrame.top;
|
||||
boolean cutOff = false;
|
||||
|
||||
// If the starting rectangle is fully or partially outside of the target rectangle, we
|
||||
// need to start the clipping at the edge and then achieve the rest with translation
|
||||
// and extending the clip rect from that edge.
|
||||
if (appFrame.top > centerY - halfHeight) {
|
||||
translationY = (centerY - halfHeight) - appFrame.top;
|
||||
translationYCorrection = 0;
|
||||
clipStartY = 0;
|
||||
cutOff = true;
|
||||
}
|
||||
if (appFrame.left > centerX - halfWidth) {
|
||||
translationX = (centerX - halfWidth) - appFrame.left;
|
||||
clipStartX = 0;
|
||||
cutOff = true;
|
||||
}
|
||||
if (appFrame.right < centerX + halfWidth) {
|
||||
translationX = (centerX + halfWidth) - appFrame.right;
|
||||
clipStartX = appWidth - mTmpRect.width();
|
||||
cutOff = true;
|
||||
}
|
||||
final long duration = calculateClipRevealTransitionDuration(cutOff, translationX,
|
||||
translationY, displayFrame);
|
||||
|
||||
// Clip third of the from size of launch icon, expand to full width/height
|
||||
Animation clipAnimLR = new ClipRectLRAnimation(
|
||||
centerX - halfWidth, centerX + halfWidth, 0, appWidth);
|
||||
clipStartX, clipStartX + mTmpRect.width(), 0, appWidth);
|
||||
clipAnimLR.setInterpolator(mClipHorizontalInterpolator);
|
||||
clipAnimLR.setDuration((long) (DEFAULT_APP_TRANSITION_DURATION / 2.5f));
|
||||
clipAnimLR.setDuration((long) (duration / 2.5f));
|
||||
|
||||
Animation clipAnimTB = new ClipRectTBAnimation(centerY - halfHeight - translationY,
|
||||
centerY + halfHeight/ 2 - translationY, 0, appHeight);
|
||||
clipAnimTB.setInterpolator(mTouchResponseInterpolator);
|
||||
clipAnimTB.setDuration(DEFAULT_APP_TRANSITION_DURATION);
|
||||
TranslateAnimation translate = new TranslateAnimation(translationX, 0, translationY, 0);
|
||||
translate.setInterpolator(cutOff ? TOUCH_RESPONSE_INTERPOLATOR
|
||||
: mLinearOutSlowInInterpolator);
|
||||
translate.setDuration(duration);
|
||||
|
||||
// We might be animating entrance of a docked task, so we need the translate to account
|
||||
// for the app frame in which the window will reside. Every other calculation here
|
||||
// is performed as if the window started at 0,0.
|
||||
translationY -= appFrame.top;
|
||||
TranslateAnimation translate = new TranslateAnimation(-appFrame.left, 0, translationY,
|
||||
0);
|
||||
translate.setInterpolator(mLinearOutSlowInInterpolator);
|
||||
translate.setDuration(DEFAULT_APP_TRANSITION_DURATION);
|
||||
Animation clipAnimTB = new ClipRectTBAnimation(
|
||||
clipStartY, clipStartY + mTmpRect.height(),
|
||||
0, appHeight,
|
||||
translationYCorrection, 0,
|
||||
mLinearOutSlowInInterpolator);
|
||||
clipAnimTB.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
|
||||
clipAnimTB.setDuration(duration);
|
||||
|
||||
// Quick fade-in from icon to app window
|
||||
final int alphaDuration = DEFAULT_APP_TRANSITION_DURATION / 4;
|
||||
final long alphaDuration = duration / 4;
|
||||
AlphaAnimation alpha = new AlphaAnimation(0.5f, 1);
|
||||
alpha.setDuration(alphaDuration);
|
||||
alpha.setInterpolator(mLinearOutSlowInInterpolator);
|
||||
@@ -692,6 +748,7 @@ public class AppTransition implements Dump {
|
||||
set.setZAdjustment(Animation.ZORDER_TOP);
|
||||
set.initialize(appWidth, appHeight, appWidth, appHeight);
|
||||
anim = set;
|
||||
mLastClipRevealTransitionDuration = duration;
|
||||
} else {
|
||||
final long duration;
|
||||
switch (transit) {
|
||||
@@ -798,7 +855,7 @@ public class AppTransition implements Dump {
|
||||
// Animation up from the thumbnail to the full screen
|
||||
Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
|
||||
mTmpRect.left + (thumbWidth / 2f), mTmpRect.top + (thumbHeight / 2f));
|
||||
scale.setInterpolator(mTouchResponseInterpolator);
|
||||
scale.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
|
||||
scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
|
||||
Animation alpha = new AlphaAnimation(1f, 0f);
|
||||
alpha.setInterpolator(mThumbnailFadeOutInterpolator);
|
||||
@@ -806,7 +863,7 @@ public class AppTransition implements Dump {
|
||||
final float toX = appRect.left + appRect.width() / 2 -
|
||||
(mTmpRect.left + thumbWidth / 2);
|
||||
Animation translate = new TranslateAnimation(0, toX, 0, toY);
|
||||
translate.setInterpolator(mTouchResponseInterpolator);
|
||||
translate.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
|
||||
translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
|
||||
|
||||
// This AnimationSet uses the Interpolators assigned above.
|
||||
@@ -819,7 +876,7 @@ public class AppTransition implements Dump {
|
||||
// Animation down from the full screen to the thumbnail
|
||||
Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f,
|
||||
mTmpRect.left + (thumbWidth / 2f), mTmpRect.top + (thumbHeight / 2f));
|
||||
scale.setInterpolator(mTouchResponseInterpolator);
|
||||
scale.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
|
||||
scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
|
||||
Animation alpha = new AlphaAnimation(0f, 1f);
|
||||
alpha.setInterpolator(mThumbnailFadeInInterpolator);
|
||||
@@ -827,7 +884,7 @@ public class AppTransition implements Dump {
|
||||
final float toX = appRect.left + appRect.width() / 2 -
|
||||
(mTmpRect.left + thumbWidth / 2);
|
||||
Animation translate = new TranslateAnimation(toX, 0, toY, 0);
|
||||
translate.setInterpolator(mTouchResponseInterpolator);
|
||||
translate.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
|
||||
translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
|
||||
|
||||
// This AnimationSet uses the Interpolators assigned above.
|
||||
@@ -839,7 +896,7 @@ public class AppTransition implements Dump {
|
||||
|
||||
}
|
||||
return prepareThumbnailAnimationWithDuration(a, appWidth, appRect.height(), 0,
|
||||
mTouchResponseInterpolator);
|
||||
TOUCH_RESPONSE_INTERPOLATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -971,7 +1028,7 @@ public class AppTransition implements Dump {
|
||||
int duration = Math.max(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION,
|
||||
THUMBNAIL_APP_TRANSITION_DURATION);
|
||||
return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration,
|
||||
mTouchResponseInterpolator);
|
||||
TOUCH_RESPONSE_INTERPOLATOR);
|
||||
}
|
||||
|
||||
private Animation createAspectScaledThumbnailEnterFreeformAnimationLocked(Rect frame,
|
||||
@@ -1223,8 +1280,9 @@ public class AppTransition implements Dump {
|
||||
* bigger.
|
||||
*/
|
||||
Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
|
||||
int orientation, Rect frame, Rect insets, @Nullable Rect surfaceInsets,
|
||||
boolean isVoiceInteraction, boolean freeform, int taskId) {
|
||||
int orientation, Rect frame, Rect displayFrame, Rect insets,
|
||||
@Nullable Rect surfaceInsets, boolean isVoiceInteraction, boolean freeform,
|
||||
int taskId) {
|
||||
Animation a;
|
||||
if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN
|
||||
|| transit == TRANSIT_TASK_OPEN
|
||||
@@ -1269,7 +1327,7 @@ public class AppTransition implements Dump {
|
||||
+ " transit=" + appTransitionToString(transit)
|
||||
+ " Callers=" + Debug.getCallers(3));
|
||||
} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) {
|
||||
a = createClipRevealAnimationLocked(transit, enter, frame);
|
||||
a = createClipRevealAnimationLocked(transit, enter, frame, displayFrame);
|
||||
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
|
||||
"applyAnimation:"
|
||||
+ " anim=" + a + " nextAppTransition=ANIM_CLIP_REVEAL"
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.view.IDockedStackListener;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
import com.android.server.wm.DimLayer.DimLayerUser;
|
||||
|
||||
@@ -39,6 +40,8 @@ import static android.view.WindowManager.DOCKED_BOTTOM;
|
||||
import static android.view.WindowManager.DOCKED_LEFT;
|
||||
import static android.view.WindowManager.DOCKED_RIGHT;
|
||||
import static android.view.WindowManager.DOCKED_TOP;
|
||||
import static com.android.server.wm.AppTransition.DEFAULT_APP_TRANSITION_DURATION;
|
||||
import static com.android.server.wm.AppTransition.TOUCH_RESPONSE_INTERPOLATOR;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
|
||||
@@ -49,8 +52,6 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
|
||||
private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM;
|
||||
|
||||
private static final long MINIMIZED_DOCK_ANIMATION_DURATION = 400;
|
||||
|
||||
private final WindowManagerService mService;
|
||||
private final DisplayContent mDisplayContent;
|
||||
private final int mDividerWindowWidth;
|
||||
@@ -71,6 +72,7 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
private long mAnimationStartTime;
|
||||
private float mAnimationStart;
|
||||
private float mAnimationTarget;
|
||||
private long mAnimationDuration;
|
||||
private final Interpolator mMinimizedDockInterpolator;
|
||||
|
||||
DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
|
||||
@@ -331,6 +333,10 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
notifyDockedStackMinimizedChanged(minimized, 0);
|
||||
}
|
||||
|
||||
private boolean isAnimationMaximizing() {
|
||||
return mAnimationTarget == 0f;
|
||||
}
|
||||
|
||||
public boolean animate(long now) {
|
||||
if (!mAnimating) {
|
||||
return false;
|
||||
@@ -339,12 +345,17 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
if (!mAnimationStarted) {
|
||||
mAnimationStarted = true;
|
||||
mAnimationStartTime = now;
|
||||
final long transitionDuration = isAnimationMaximizing()
|
||||
? mService.mAppTransition.getLastClipRevealTransitionDuration()
|
||||
: DEFAULT_APP_TRANSITION_DURATION;
|
||||
mAnimationDuration = (long)
|
||||
(transitionDuration * mService.getTransitionAnimationScaleLocked());
|
||||
notifyDockedStackMinimizedChanged(mMinimizedDock,
|
||||
MINIMIZED_DOCK_ANIMATION_DURATION);
|
||||
mAnimationDuration);
|
||||
}
|
||||
float t = Math.min(1f, (float) (now - mAnimationStartTime)
|
||||
/ MINIMIZED_DOCK_ANIMATION_DURATION);
|
||||
t = mMinimizedDockInterpolator.getInterpolation(t);
|
||||
float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
|
||||
t = (isAnimationMaximizing() ? TOUCH_RESPONSE_INTERPOLATOR : mMinimizedDockInterpolator)
|
||||
.getInterpolation(t);
|
||||
final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
|
||||
if (stack != null) {
|
||||
final float amount = t * mAnimationTarget + (1 - t) * mAnimationStart;
|
||||
|
||||
@@ -2968,6 +2968,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
// Determine the visible rect to calculate the thumbnail clip
|
||||
final WindowState win = atoken.findMainWindow();
|
||||
final Rect frame = new Rect(0, 0, width, height);
|
||||
final Rect displayFrame = new Rect(0, 0,
|
||||
displayInfo.logicalWidth, displayInfo.logicalHeight);
|
||||
final Rect insets = new Rect();
|
||||
Rect surfaceInsets = null;
|
||||
final boolean freeform = win != null && win.inFreeformWorkspace();
|
||||
@@ -2995,8 +2997,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
+ " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
|
||||
+ " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
|
||||
Animation a = mAppTransition.loadAnimation(lp, transit, enter,
|
||||
mCurConfiguration.orientation, frame, insets, surfaceInsets, isVoiceInteraction,
|
||||
freeform, atoken.mTask.mTaskId);
|
||||
mCurConfiguration.orientation, frame, displayFrame, insets, surfaceInsets,
|
||||
isVoiceInteraction, freeform, atoken.mTask.mTaskId);
|
||||
if (a != null) {
|
||||
if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
|
||||
final int containingWidth = frame.width();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -11,12 +11,14 @@
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package android.view.animation;
|
||||
package com.android.server.wm.animation;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.animation.ClipRectAnimation;
|
||||
import android.view.animation.Transformation;
|
||||
|
||||
/**
|
||||
* Special case of ClipRectAnimation that animates only the left/right
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.server.wm.animation;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.animation.ClipRectAnimation;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.Transformation;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
|
||||
/**
|
||||
* Special case of ClipRectAnimation that animates only the top/bottom
|
||||
* dimensions of the clip, picking up the other dimensions from whatever is
|
||||
* set on the transform already. In addition to that, information about a vertical translation
|
||||
* animation can be specified so this animation simulates as the clip would be applied after instead
|
||||
* of before applying the translation.
|
||||
*/
|
||||
public class ClipRectTBAnimation extends ClipRectAnimation {
|
||||
|
||||
private final int mFromTranslateY;
|
||||
private final int mToTranslateY;
|
||||
private final Interpolator mTranslateInterpolator;
|
||||
private float mNormalizedTime;
|
||||
|
||||
/**
|
||||
* Constructor. Passes in 0 for Left/Right parameters of ClipRectAnimation
|
||||
*/
|
||||
public ClipRectTBAnimation(int fromT, int fromB, int toT, int toB,
|
||||
int fromTranslateY, int toTranslateY, Interpolator translateInterpolator) {
|
||||
super(0, fromT, 0, fromB, 0, toT, 0, toB);
|
||||
mFromTranslateY = fromTranslateY;
|
||||
mToTranslateY = toTranslateY;
|
||||
mTranslateInterpolator = translateInterpolator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTransformation(long currentTime, Transformation outTransformation) {
|
||||
|
||||
// Hack: Because translation animation has a different interpolator, we need to duplicate
|
||||
// code from Animation here and use it to calculate/store the uninterpolated normalized
|
||||
// time.
|
||||
final long startOffset = getStartOffset();
|
||||
final long duration = getDuration();
|
||||
float normalizedTime;
|
||||
if (duration != 0) {
|
||||
normalizedTime = ((float) (currentTime - (getStartTime() + startOffset))) /
|
||||
(float) duration;
|
||||
} else {
|
||||
// time is a step-change with a zero duration
|
||||
normalizedTime = currentTime < getStartTime() ? 0.0f : 1.0f;
|
||||
}
|
||||
mNormalizedTime = normalizedTime;
|
||||
return super.getTransformation(currentTime, outTransformation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates and sets clip rect on given transformation. It uses existing values
|
||||
* on the Transformation for Left/Right clip parameters.
|
||||
*/
|
||||
@Override
|
||||
protected void applyTransformation(float it, Transformation tr) {
|
||||
float translationT = mTranslateInterpolator.getInterpolation(mNormalizedTime);
|
||||
int translation =
|
||||
(int) (mFromTranslateY + (mToTranslateY - mFromTranslateY) * translationT);
|
||||
Rect oldClipRect = tr.getClipRect();
|
||||
tr.setClipRect(oldClipRect.left,
|
||||
mFromRect.top - translation + (int) ((mToRect.top - mFromRect.top) * it),
|
||||
oldClipRect.right,
|
||||
mFromRect.bottom - translation + (int) ((mToRect.bottom - mFromRect.bottom) * it));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user