Merge "Launcher app close transition." into ub-launcher3-master
This commit is contained in:
commit
b57721182c
|
@ -34,6 +34,9 @@
|
|||
<!-- TODO: This can be calculated using other resource values -->
|
||||
<dimen name="all_apps_search_box_full_height">90dp</dimen>
|
||||
|
||||
<dimen name="drag_layer_trans_y">25dp</dimen>
|
||||
<!-- Launcher app transition -->
|
||||
<dimen name="content_trans_y">25dp</dimen>
|
||||
<dimen name="workspace_trans_y">80dp</dimen>
|
||||
|
||||
<dimen name="shelf_min_value">-2.857dp</dimen>
|
||||
</resources>
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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.launcher3;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.os.Handler;
|
||||
|
||||
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
||||
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
|
||||
|
||||
public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat {
|
||||
|
||||
AnimatorSet mAnimator;
|
||||
private Launcher mLauncher;
|
||||
|
||||
LauncherAnimationRunner(Launcher launcher) {
|
||||
mLauncher = launcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancelled() {
|
||||
postAtFrontOfQueueAsynchronously(mLauncher.getWindow().getDecorView().getHandler(), () -> {
|
||||
if (mAnimator != null) {
|
||||
mAnimator.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.views.AllAppsScrim.SCRIM_PROGRESS;
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber;
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities.getSurface;
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
|
||||
|
@ -25,10 +26,12 @@ import android.animation.AnimatorListenerAdapter;
|
|||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
|
@ -39,25 +42,34 @@ import android.widget.ImageView;
|
|||
import com.android.launcher3.InsettableFrameLayout.LayoutParams;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.views.AllAppsScrim;
|
||||
import com.android.systemui.shared.system.ActivityCompat;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationDefinitionCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.TransactionCompat;
|
||||
import com.android.systemui.shared.system.WindowManagerWrapper;
|
||||
|
||||
/**
|
||||
* Manages the opening app animations from Launcher.
|
||||
* Manages the opening and closing app transitions from Launcher.
|
||||
*/
|
||||
public class LauncherAppTransitionManager {
|
||||
|
||||
private static final String TAG = "LauncherTransition";
|
||||
private static final int REFRESH_RATE_MS = 16;
|
||||
|
||||
private static final int CLOSING_TRANSITION_DURATION_MS = 350;
|
||||
|
||||
private final DragLayer mDragLayer;
|
||||
private final Launcher mLauncher;
|
||||
private final DeviceProfile mDeviceProfile;
|
||||
|
||||
private final float mDragLayerTransY;
|
||||
private final float mContentTransY;
|
||||
private final float mWorkspaceTransY;
|
||||
// The smallest y-value the shelf will reach on screen, before overshooting back down to 0.
|
||||
private final float mShelfMinValue;
|
||||
|
||||
private ImageView mFloatingView;
|
||||
private boolean mIsRtl;
|
||||
|
@ -67,24 +79,30 @@ public class LauncherAppTransitionManager {
|
|||
mDragLayer = launcher.getDragLayer();
|
||||
mDeviceProfile = launcher.getDeviceProfile();
|
||||
|
||||
mDragLayerTransY =
|
||||
launcher.getResources().getDimensionPixelSize(R.dimen.drag_layer_trans_y);
|
||||
|
||||
mIsRtl = Utilities.isRtl(launcher.getResources());
|
||||
|
||||
Resources res = launcher.getResources();
|
||||
mContentTransY = res.getDimensionPixelSize(R.dimen.content_trans_y);
|
||||
mWorkspaceTransY = res.getDimensionPixelSize(R.dimen.workspace_trans_y);
|
||||
mShelfMinValue = res.getDimensionPixelSize(R.dimen.shelf_min_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A Bundle with remote animations that controls how the window of the opening
|
||||
* targets are displayed.
|
||||
*/
|
||||
public Bundle getActivityLauncherOptions(View v) {
|
||||
RemoteAnimationRunnerCompat runner = new RemoteAnimationRunnerCompat() {
|
||||
RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mLauncher) {
|
||||
@Override
|
||||
public void onAnimationStart(RemoteAnimationTargetCompat[] targets,
|
||||
Runnable finishedCallback) {
|
||||
// Post at front of queue ignoring sync barriers to make sure it gets processed
|
||||
// before the next frame.
|
||||
postAtFrontOfQueueAsynchronously(v.getHandler(), () -> {
|
||||
AnimatorSet both = new AnimatorSet();
|
||||
both.play(getLauncherAnimators(v));
|
||||
both.play(getAppWindowAnimators(v, targets));
|
||||
both.addListener(new AnimatorListenerAdapter() {
|
||||
mAnimator = new AnimatorSet();
|
||||
mAnimator.play(getLauncherAnimators(v));
|
||||
mAnimator.play(getWindowAnimators(v, targets));
|
||||
mAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
// Reset launcher to normal state
|
||||
|
@ -101,51 +119,62 @@ public class LauncherAppTransitionManager {
|
|||
finishedCallback.run();
|
||||
}
|
||||
});
|
||||
both.start();
|
||||
mAnimator.start();
|
||||
// Because t=0 has the app icon in its original spot, we can skip the first
|
||||
// frame and have the same movement one frame earlier.
|
||||
both.setCurrentPlayTime(REFRESH_RATE_MS);
|
||||
mAnimator.setCurrentPlayTime(REFRESH_RATE_MS);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancelled() {
|
||||
}
|
||||
};
|
||||
|
||||
return ActivityOptionsCompat.makeRemoteAnimation(
|
||||
new RemoteAnimationAdapterCompat(runner, 500, 380)).toBundle();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Animators that control the movements of the Launcher and icon of the opening target.
|
||||
*/
|
||||
private AnimatorSet getLauncherAnimators(View v) {
|
||||
AnimatorSet launcherAnimators = new AnimatorSet();
|
||||
launcherAnimators.play(getHideLauncherAnimator());
|
||||
launcherAnimators.play(getAppIconAnimator(v));
|
||||
launcherAnimators.play(getLauncherContentAnimator(false /* show */));
|
||||
launcherAnimators.play(getIconAnimator(v));
|
||||
return launcherAnimators;
|
||||
}
|
||||
|
||||
private AnimatorSet getHideLauncherAnimator() {
|
||||
/**
|
||||
* Content is everything on screen except the background and the floating view (if any).
|
||||
*
|
||||
* @param show If true: Animate the content so that it moves upwards and fades in.
|
||||
* Else: Animate the content so that it moves downwards and fades out.
|
||||
*/
|
||||
private AnimatorSet getLauncherContentAnimator(boolean show) {
|
||||
AnimatorSet hideLauncher = new AnimatorSet();
|
||||
|
||||
// Animate the background content so that it moves downwards and fades out.
|
||||
if (mLauncher.isInState(LauncherState.ALL_APPS)) {
|
||||
float[] alphas = show
|
||||
? new float[] {0, 1}
|
||||
: new float[] {1, 0};
|
||||
float[] trans = show
|
||||
? new float[] {mContentTransY, 0,}
|
||||
: new float[] {0, mContentTransY};
|
||||
|
||||
if (mLauncher.isInState(LauncherState.ALL_APPS) && !mDeviceProfile.isVerticalBarLayout()) {
|
||||
// All Apps in portrait mode is full screen, so we only animate AllAppsContainerView.
|
||||
View appsView = mLauncher.getAppsView();
|
||||
ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, 1f, 0f);
|
||||
ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas);
|
||||
alpha.setDuration(217);
|
||||
alpha.setInterpolator(Interpolators.LINEAR);
|
||||
ObjectAnimator transY = ObjectAnimator.ofFloat(appsView, View.TRANSLATION_Y, 0,
|
||||
mDragLayerTransY);
|
||||
ObjectAnimator transY = ObjectAnimator.ofFloat(appsView, View.TRANSLATION_Y, trans);
|
||||
transY.setInterpolator(Interpolators.AGGRESSIVE_EASE);
|
||||
transY.setDuration(350);
|
||||
|
||||
hideLauncher.play(alpha);
|
||||
hideLauncher.play(transY);
|
||||
} else {
|
||||
ObjectAnimator dragLayerAlpha = ObjectAnimator.ofFloat(mDragLayer, View.ALPHA, 1f, 0f);
|
||||
ObjectAnimator dragLayerAlpha = ObjectAnimator.ofFloat(mDragLayer, View.ALPHA, alphas);
|
||||
dragLayerAlpha.setDuration(217);
|
||||
dragLayerAlpha.setInterpolator(Interpolators.LINEAR);
|
||||
ObjectAnimator dragLayerTransY = ObjectAnimator.ofFloat(mDragLayer, View.TRANSLATION_Y,
|
||||
0, mDragLayerTransY);
|
||||
trans);
|
||||
dragLayerTransY.setInterpolator(Interpolators.AGGRESSIVE_EASE);
|
||||
dragLayerTransY.setDuration(350);
|
||||
|
||||
|
@ -155,7 +184,10 @@ public class LauncherAppTransitionManager {
|
|||
return hideLauncher;
|
||||
}
|
||||
|
||||
private AnimatorSet getAppIconAnimator(View v) {
|
||||
/**
|
||||
* @return Animator that controls the icon used to launch the target.
|
||||
*/
|
||||
private AnimatorSet getIconAnimator(View v) {
|
||||
boolean isBubbleTextView = v instanceof BubbleTextView;
|
||||
mFloatingView = new ImageView(mLauncher);
|
||||
if (isBubbleTextView) {
|
||||
|
@ -230,7 +262,10 @@ public class LauncherAppTransitionManager {
|
|||
return appIconAnimatorSet;
|
||||
}
|
||||
|
||||
private ValueAnimator getAppWindowAnimators(View v, RemoteAnimationTargetCompat[] targets) {
|
||||
/**
|
||||
* @return Animator that controls the window of the opening targets.
|
||||
*/
|
||||
private ValueAnimator getWindowAnimators(View v, RemoteAnimationTargetCompat[] targets) {
|
||||
Rect bounds = new Rect();
|
||||
if (v instanceof BubbleTextView) {
|
||||
((BubbleTextView) v).getIconBounds(bounds);
|
||||
|
@ -285,7 +320,7 @@ public class LauncherAppTransitionManager {
|
|||
// Fade in the app window.
|
||||
float alphaDelay = 0;
|
||||
float alphaDuration = 50;
|
||||
float alpha = getValue(1f, 0f, alphaDelay, alphaDuration,
|
||||
float alpha = getValue(0f, 1f, alphaDelay, alphaDuration,
|
||||
appAnimator.getDuration() * percent, Interpolators.AGGRESSIVE_EASE);
|
||||
|
||||
// Animate the window crop so that it starts off as a square, and then reveals
|
||||
|
@ -318,19 +353,168 @@ public class LauncherAppTransitionManager {
|
|||
matrix.reset();
|
||||
isFirstFrame = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that allows us to get interpolated values for embedded
|
||||
* animations with a delay and/or different duration.
|
||||
*/
|
||||
private float getValue(float start, float end, float delay, float duration,
|
||||
float currentPlayTime, Interpolator i) {
|
||||
float time = Math.max(0, currentPlayTime - delay);
|
||||
float newPercent = Math.min(1f, time / duration);
|
||||
newPercent = i.getInterpolation(newPercent);
|
||||
return start * newPercent + end * (1 - newPercent);
|
||||
}
|
||||
});
|
||||
return appAnimator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers remote animations used when closing apps to home screen.
|
||||
*/
|
||||
public void registerRemoteAnimations() {
|
||||
RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
|
||||
definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
|
||||
new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(), 0,
|
||||
CLOSING_TRANSITION_DURATION_MS));
|
||||
|
||||
// TODO: App controlled transition for unlock to home TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
|
||||
|
||||
new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Runner that plays when user goes to Launcher
|
||||
* ie. pressing home, swiping up from nav bar.
|
||||
*/
|
||||
private RemoteAnimationRunnerCompat getWallpaperOpenRunner() {
|
||||
return new LauncherAnimationRunner(mLauncher) {
|
||||
@Override
|
||||
public void onAnimationStart(RemoteAnimationTargetCompat[] targets,
|
||||
Runnable finishedCallback) {
|
||||
Handler handler = mLauncher.getWindow().getDecorView().getHandler();
|
||||
postAtFrontOfQueueAsynchronously(handler, () -> {
|
||||
// We use a separate transition for Overview mode.
|
||||
if (mLauncher.isInState(LauncherState.OVERVIEW)) {
|
||||
finishedCallback.run();
|
||||
return;
|
||||
}
|
||||
|
||||
mAnimator = new AnimatorSet();
|
||||
mAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
finishedCallback.run();
|
||||
}
|
||||
});
|
||||
mAnimator.play(getClosingWindowAnimators(targets));
|
||||
mAnimator.play(getLauncherResumeAnimation());
|
||||
mAnimator.start();
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Animator that controls the transformations of the windows the targets that are closing.
|
||||
*/
|
||||
private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] targets) {
|
||||
Matrix matrix = new Matrix();
|
||||
float height = mLauncher.getDeviceProfile().heightPx;
|
||||
float width = mLauncher.getDeviceProfile().widthPx;
|
||||
float endX = Utilities.isRtl(mLauncher.getResources()) ? -width : width;
|
||||
|
||||
ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
|
||||
closingAnimator.setDuration(CLOSING_TRANSITION_DURATION_MS);
|
||||
|
||||
closingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
boolean isFirstFrame = true;
|
||||
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
final float percent = animation.getAnimatedFraction();
|
||||
float currentPlayTime = percent * closingAnimator.getDuration();
|
||||
|
||||
float scale = getValue(1f, 0.8f, 0, 267, currentPlayTime,
|
||||
Interpolators.AGGRESSIVE_EASE);
|
||||
matrix.setScale(scale, scale);
|
||||
|
||||
float dX = getValue(0, endX, 0, 350, currentPlayTime,
|
||||
Interpolators.AGGRESSIVE_EASE_IN_OUT);
|
||||
|
||||
TransactionCompat t = new TransactionCompat();
|
||||
for (RemoteAnimationTargetCompat app : targets) {
|
||||
if (app.mode == RemoteAnimationTargetCompat.MODE_CLOSING) {
|
||||
t.setAlpha(app.leash, 1f - percent);
|
||||
|
||||
float dY = (height - (app.clipRect.height() * scale)) / 2f;
|
||||
matrix.postTranslate(dX, dY);
|
||||
t.setMatrix(app.leash, matrix);
|
||||
}
|
||||
// TODO: Layer should be set only once, but there is possibly a race condition
|
||||
// where WindowManager is also calling setLayer.
|
||||
int layer = app.mode == RemoteAnimationTargetCompat.MODE_CLOSING
|
||||
? Integer.MAX_VALUE
|
||||
: app.prefixOrderIndex;
|
||||
t.setLayer(app.leash, layer);
|
||||
if (isFirstFrame) {
|
||||
t.show(app.leash);
|
||||
}
|
||||
}
|
||||
t.apply();
|
||||
|
||||
matrix.reset();
|
||||
isFirstFrame = false;
|
||||
}
|
||||
});
|
||||
return closingAnimator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Animator that modifies Launcher as a result from {@link #getWallpaperOpenRunner}.
|
||||
*/
|
||||
private AnimatorSet getLauncherResumeAnimation() {
|
||||
if (mLauncher.isInState(LauncherState.ALL_APPS)
|
||||
|| mLauncher.getDeviceProfile().isVerticalBarLayout()) {
|
||||
return getLauncherContentAnimator(true /* show */);
|
||||
} else {
|
||||
AnimatorSet workspaceAnimator = new AnimatorSet();
|
||||
mLauncher.getWorkspace().setTranslationY(mWorkspaceTransY);
|
||||
mLauncher.getWorkspace().setAlpha(0f);
|
||||
workspaceAnimator.play(ObjectAnimator.ofFloat(mLauncher.getWorkspace(),
|
||||
View.TRANSLATION_Y, mWorkspaceTransY, 0));
|
||||
workspaceAnimator.play(ObjectAnimator.ofFloat(mLauncher.getWorkspace(), View.ALPHA,
|
||||
0, 1f));
|
||||
workspaceAnimator.setStartDelay(150);
|
||||
workspaceAnimator.setDuration(333);
|
||||
workspaceAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
||||
|
||||
// Animate the shelf
|
||||
AllAppsScrim allAppsScrim = mLauncher.findViewById(R.id.all_apps_scrim);
|
||||
View hotseat = mLauncher.getHotseat();
|
||||
final float endY = mShelfMinValue;
|
||||
int startY = hotseat.getMeasuredHeight()
|
||||
+ (allAppsScrim.getShadowBitmap().getHeight() / 2);
|
||||
hotseat.setTranslationY(startY);
|
||||
allAppsScrim.setTranslationY(startY);
|
||||
|
||||
AnimatorSet hotseatSlideIn = new AnimatorSet();
|
||||
hotseatSlideIn.play(ObjectAnimator.ofFloat(hotseat, View.TRANSLATION_Y, startY, endY));
|
||||
hotseatSlideIn.play(ObjectAnimator.ofFloat(allAppsScrim, SCRIM_PROGRESS, startY, endY));
|
||||
hotseatSlideIn.setStartDelay(150);
|
||||
hotseatSlideIn.setDuration(317);
|
||||
hotseatSlideIn.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
||||
|
||||
AnimatorSet hotseatOvershoot = new AnimatorSet();
|
||||
hotseatOvershoot.play(ObjectAnimator.ofFloat(hotseat, View.TRANSLATION_Y, endY, 0));
|
||||
hotseatOvershoot.play(ObjectAnimator.ofFloat(allAppsScrim, SCRIM_PROGRESS, endY, 0));
|
||||
hotseatOvershoot.setDuration(153);
|
||||
hotseatOvershoot.setInterpolator(Interpolators.OVERSHOOT_0);
|
||||
|
||||
AnimatorSet resumeLauncherAnimation = new AnimatorSet();
|
||||
resumeLauncherAnimation.play(workspaceAnimator);
|
||||
resumeLauncherAnimation.playSequentially(hotseatSlideIn, hotseatOvershoot);
|
||||
return resumeLauncherAnimation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that allows us to get interpolated values for embedded
|
||||
* animations with a delay and/or different duration.
|
||||
*/
|
||||
private static float getValue(float start, float end, float delay, float duration,
|
||||
float currentPlayTime, Interpolator i) {
|
||||
float time = Math.max(0, currentPlayTime - delay);
|
||||
float newPercent = Math.min(1f, time / duration);
|
||||
newPercent = i.getInterpolation(newPercent);
|
||||
return end * newPercent + start * (1 - newPercent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ import com.android.launcher3.graphics.BitmapRenderer;
|
|||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.quickstep.RecentsView;
|
||||
import com.android.systemui.shared.recents.view.RecentsTransition;
|
||||
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
|
||||
|
||||
public class UiFactory {
|
||||
|
||||
|
@ -89,4 +88,12 @@ public class UiFactory {
|
|||
return launcher.getDefaultActivityLaunchOptions(v);
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerRemoteAnimations(Launcher launcher) {
|
||||
try {
|
||||
new LauncherAppTransitionManager(launcher).registerRemoteAnimations();
|
||||
} catch (NoClassDefFoundError e) {
|
||||
// Gracefully fall back if the user's platform doesn't have the latest changes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -403,6 +403,10 @@ public class Launcher extends BaseActivity
|
|||
getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
|
||||
Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
|
||||
|
||||
if (!isInMultiWindowModeCompat()) {
|
||||
UiFactory.registerRemoteAnimations(this);
|
||||
}
|
||||
|
||||
if (mLauncherCallbacks != null) {
|
||||
mLauncherCallbacks.onCreate(savedInstanceState);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.view.animation.AccelerateInterpolator;
|
|||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.view.animation.OvershootInterpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
|
||||
|
@ -43,6 +44,9 @@ public class Interpolators {
|
|||
public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
|
||||
|
||||
public static final Interpolator AGGRESSIVE_EASE = new PathInterpolator(0.2f, 0f, 0f, 1f);
|
||||
public static final Interpolator AGGRESSIVE_EASE_IN_OUT = new PathInterpolator(0.8f,0, 0.4f, 1);
|
||||
|
||||
public static final Interpolator OVERSHOOT_0 = new OvershootInterpolator(0);
|
||||
|
||||
/**
|
||||
* Inversion of zInterpolate, compounded with an ease-out.
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.graphics.Paint;
|
|||
import android.graphics.Rect;
|
||||
import android.support.v4.graphics.ColorUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Property;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
|
@ -60,11 +61,25 @@ public class AllAppsScrim extends View implements OnChangeListener, Insettable {
|
|||
|
||||
private final NinePatchDrawHelper mShadowHelper = new NinePatchDrawHelper();
|
||||
|
||||
private float mProgress;
|
||||
private int mFillAlpha;
|
||||
|
||||
private float mDrawHeight;
|
||||
private float mDrawOffsetY;
|
||||
|
||||
public static final Property<AllAppsScrim, Float> SCRIM_PROGRESS =
|
||||
new Property<AllAppsScrim, Float>(Float.class, "allAppsScrimProgress") {
|
||||
@Override
|
||||
public Float get(AllAppsScrim allAppsScrim) {
|
||||
return allAppsScrim.getProgress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(AllAppsScrim allAppsScrim, Float progress) {
|
||||
allAppsScrim.setProgress(progress);
|
||||
}
|
||||
};
|
||||
|
||||
public AllAppsScrim(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
@ -109,6 +124,10 @@ public class AllAppsScrim extends View implements OnChangeListener, Insettable {
|
|||
return result;
|
||||
}
|
||||
|
||||
public Bitmap getShadowBitmap() {
|
||||
return mShadowBitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
@ -154,18 +173,24 @@ public class AllAppsScrim extends View implements OnChangeListener, Insettable {
|
|||
}
|
||||
|
||||
public void setProgress(float translateY, float alpha) {
|
||||
float newAlpha = Math.round(alpha * mAlphaRange + mMinAlpha);
|
||||
int newAlpha = Math.round(alpha * mAlphaRange + mMinAlpha);
|
||||
if (newAlpha != mFillAlpha) {
|
||||
mFillAlpha = newAlpha;
|
||||
mFillPaint.setAlpha(mFillAlpha);
|
||||
invalidateDrawRect();
|
||||
}
|
||||
|
||||
setProgress(translateY);
|
||||
}
|
||||
|
||||
public void setProgress(float translateY) {
|
||||
// Negative translation means the scrim is moving up. For negative translation, we change
|
||||
// draw offset as it requires redraw (since more area of the scrim needs to be shown). For
|
||||
// position translation, we simply translate the scrim down as it avoids invalidate and
|
||||
// hence could be optimized by the platform.
|
||||
float drawOffsetY = Math.min(translateY, 0);
|
||||
|
||||
if (newAlpha != mFillAlpha || drawOffsetY != mDrawOffsetY) {
|
||||
invalidateDrawRect();
|
||||
|
||||
mFillAlpha = Math.round(alpha * mAlphaRange + mMinAlpha);
|
||||
mFillPaint.setAlpha(mFillAlpha);
|
||||
if (drawOffsetY != mDrawOffsetY) {
|
||||
mDrawOffsetY = drawOffsetY;
|
||||
invalidateDrawRect();
|
||||
}
|
||||
|
@ -173,6 +198,10 @@ public class AllAppsScrim extends View implements OnChangeListener, Insettable {
|
|||
setTranslationY(Math.max(translateY, 0));
|
||||
}
|
||||
|
||||
public float getProgress() {
|
||||
return mProgress;
|
||||
}
|
||||
|
||||
private void invalidateDrawRect() {
|
||||
mDrawRect.top = (int) (getHeight()
|
||||
+ mDrawOffsetY - mDrawHeight + mPadding.top - mShadowBlur - 0.5f);
|
||||
|
|
|
@ -18,21 +18,15 @@ package com.android.launcher3.uioverrides;
|
|||
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.AccessibilityDelegate;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.graphics.BitmapRenderer;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
|
||||
|
@ -71,4 +65,6 @@ public class UiFactory {
|
|||
public static Bundle getActivityLaunchOptions(Launcher launcher, View v) {
|
||||
return launcher.getDefaultActivityLaunchOptions(v);
|
||||
}
|
||||
|
||||
public static void registerRemoteAnimations(Launcher launcher) { }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue