Refactor LauncherAppTransitionManager & polish for new app transitions.
* Add start delay when launcher resumes from all apps or landscape. * Track the last app transition animator and cancel it before beginning a new one, otherwise the animators can conflict with each other. ie. Opening an app from all apps and then immediately pressing back to return to all apps. * Use class overrride instead of UiFactory. Bug: 70220260 Change-Id: I4755d45d820f9d551e443d6c4a148e8789c5bc57
This commit is contained in:
parent
82d010f0d2
commit
54441f5df9
|
@ -97,6 +97,11 @@
|
||||||
# support jar.
|
# support jar.
|
||||||
-keep class android.support.v7.widget.RecyclerView { *; }
|
-keep class android.support.v7.widget.RecyclerView { *; }
|
||||||
|
|
||||||
|
# LauncherAppTransitionManager
|
||||||
|
-keep class com.android.launcher3.LauncherAppTransitionManagerImpl {
|
||||||
|
public <init>(...);
|
||||||
|
}
|
||||||
|
|
||||||
-keep interface com.android.launcher3.userevent.nano.LauncherLogProto.** {
|
-keep interface com.android.launcher3.userevent.nano.LauncherLogProto.** {
|
||||||
*;
|
*;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="app_transition_manager_class" translatable="false">com.android.launcher3.LauncherAppTransitionManagerImpl</string>
|
||||||
|
</resources>
|
||||||
|
|
|
@ -26,6 +26,8 @@ import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
|
@ -55,11 +57,15 @@ import com.android.systemui.shared.system.WindowManagerWrapper;
|
||||||
/**
|
/**
|
||||||
* Manages the opening and closing app transitions from Launcher.
|
* Manages the opening and closing app transitions from Launcher.
|
||||||
*/
|
*/
|
||||||
public class LauncherAppTransitionManager {
|
public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManager {
|
||||||
|
|
||||||
private static final String TAG = "LauncherTransition";
|
private static final String TAG = "LauncherTransition";
|
||||||
private static final int REFRESH_RATE_MS = 16;
|
private static final int REFRESH_RATE_MS = 16;
|
||||||
|
|
||||||
|
private static final String CONTROL_REMOTE_APP_TRANSITION_PERMISSION =
|
||||||
|
"android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS";
|
||||||
|
|
||||||
|
private static final int LAUNCHER_RESUME_START_DELAY = 150;
|
||||||
private static final int CLOSING_TRANSITION_DURATION_MS = 350;
|
private static final int CLOSING_TRANSITION_DURATION_MS = 350;
|
||||||
|
|
||||||
// Progress = 0: All apps is fully pulled up, Progress = 1: All apps is fully pulled down.
|
// Progress = 0: All apps is fully pulled up, Progress = 1: All apps is fully pulled down.
|
||||||
|
@ -76,60 +82,79 @@ public class LauncherAppTransitionManager {
|
||||||
private ImageView mFloatingView;
|
private ImageView mFloatingView;
|
||||||
private boolean mIsRtl;
|
private boolean mIsRtl;
|
||||||
|
|
||||||
public LauncherAppTransitionManager(Launcher launcher) {
|
private Animator mCurrentAnimator;
|
||||||
mLauncher = launcher;
|
|
||||||
mDragLayer = launcher.getDragLayer();
|
|
||||||
mDeviceProfile = launcher.getDeviceProfile();
|
|
||||||
|
|
||||||
mIsRtl = Utilities.isRtl(launcher.getResources());
|
public LauncherAppTransitionManagerImpl(Context context) {
|
||||||
|
mLauncher = Launcher.getLauncher(context);
|
||||||
|
mDragLayer = mLauncher.getDragLayer();
|
||||||
|
mDeviceProfile = mLauncher.getDeviceProfile();
|
||||||
|
|
||||||
Resources res = launcher.getResources();
|
mIsRtl = Utilities.isRtl(mLauncher.getResources());
|
||||||
|
|
||||||
|
Resources res = mLauncher.getResources();
|
||||||
mContentTransY = res.getDimensionPixelSize(R.dimen.content_trans_y);
|
mContentTransY = res.getDimensionPixelSize(R.dimen.content_trans_y);
|
||||||
mWorkspaceTransY = res.getDimensionPixelSize(R.dimen.workspace_trans_y);
|
mWorkspaceTransY = res.getDimensionPixelSize(R.dimen.workspace_trans_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setCurrentAnimator(Animator animator) {
|
||||||
|
if (mCurrentAnimator != null && mCurrentAnimator.isRunning()) {
|
||||||
|
mCurrentAnimator.cancel();
|
||||||
|
}
|
||||||
|
mCurrentAnimator = animator;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A Bundle with remote animations that controls how the window of the opening
|
* @return A Bundle with remote animations that controls how the window of the opening
|
||||||
* targets are displayed.
|
* targets are displayed.
|
||||||
*/
|
*/
|
||||||
public Bundle getActivityLauncherOptions(View v) {
|
@Override
|
||||||
RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mLauncher) {
|
public Bundle getActivityLaunchOptions(Launcher launcher, View v) {
|
||||||
@Override
|
if (hasControlRemoteAppTransitionPermission()) {
|
||||||
public void onAnimationStart(RemoteAnimationTargetCompat[] targets,
|
try {
|
||||||
Runnable finishedCallback) {
|
RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mLauncher) {
|
||||||
// Post at front of queue ignoring sync barriers to make sure it gets processed
|
@Override
|
||||||
// before the next frame.
|
public void onAnimationStart(RemoteAnimationTargetCompat[] targets,
|
||||||
postAtFrontOfQueueAsynchronously(v.getHandler(), () -> {
|
Runnable finishedCallback) {
|
||||||
mAnimator = new AnimatorSet();
|
// Post at front of queue ignoring sync barriers to make sure it gets
|
||||||
mAnimator.play(getLauncherAnimators(v));
|
// processed before the next frame.
|
||||||
mAnimator.play(getWindowAnimators(v, targets));
|
postAtFrontOfQueueAsynchronously(v.getHandler(), () -> {
|
||||||
mAnimator.addListener(new AnimatorListenerAdapter() {
|
mAnimator = new AnimatorSet();
|
||||||
@Override
|
setCurrentAnimator(mAnimator);
|
||||||
public void onAnimationEnd(Animator animation) {
|
mAnimator.play(getLauncherAnimators(v));
|
||||||
// Reset launcher to normal state
|
mAnimator.play(getWindowAnimators(v, targets));
|
||||||
v.setVisibility(View.VISIBLE);
|
mAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
((ViewGroup) mDragLayer.getParent()).removeView(mFloatingView);
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
// Reset launcher to normal state
|
||||||
|
v.setVisibility(View.VISIBLE);
|
||||||
|
((ViewGroup) mDragLayer.getParent()).removeView(mFloatingView);
|
||||||
|
|
||||||
mDragLayer.setAlpha(1f);
|
mDragLayer.setAlpha(1f);
|
||||||
mDragLayer.setTranslationY(0f);
|
mDragLayer.setTranslationY(0f);
|
||||||
|
|
||||||
View appsView = mLauncher.getAppsView();
|
View appsView = mLauncher.getAppsView();
|
||||||
appsView.setAlpha(1f);
|
appsView.setAlpha(1f);
|
||||||
appsView.setTranslationY(0f);
|
appsView.setTranslationY(0f);
|
||||||
|
|
||||||
finishedCallback.run();
|
finishedCallback.run();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mAnimator.start();
|
mAnimator.start();
|
||||||
// Because t=0 has the app icon in its original spot, we can skip the first
|
// Because t=0 has the app icon in its original spot, we can skip the
|
||||||
// frame and have the same movement one frame earlier.
|
// first frame and have the same movement one frame earlier.
|
||||||
mAnimator.setCurrentPlayTime(REFRESH_RATE_MS);
|
mAnimator.setCurrentPlayTime(REFRESH_RATE_MS);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return ActivityOptionsCompat.makeRemoteAnimation(
|
||||||
|
new RemoteAnimationAdapterCompat(runner, 500, 380)).toBundle();
|
||||||
|
} catch (NoClassDefFoundError e) {
|
||||||
|
// Gracefully fall back to default launch options if the user's platform doesn't
|
||||||
|
// have the latest changes.
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
return getDefaultActivityLaunchOptions(launcher, v);
|
||||||
return ActivityOptionsCompat.makeRemoteAnimation(
|
|
||||||
new RemoteAnimationAdapterCompat(runner, 500, 380)).toBundle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,7 +174,7 @@ public class LauncherAppTransitionManager {
|
||||||
* Else: Animate the content so that it moves downwards and fades out.
|
* Else: Animate the content so that it moves downwards and fades out.
|
||||||
*/
|
*/
|
||||||
private AnimatorSet getLauncherContentAnimator(boolean show) {
|
private AnimatorSet getLauncherContentAnimator(boolean show) {
|
||||||
AnimatorSet hideLauncher = new AnimatorSet();
|
AnimatorSet launcherAnimator = new AnimatorSet();
|
||||||
|
|
||||||
float[] alphas = show
|
float[] alphas = show
|
||||||
? new float[] {0, 1}
|
? new float[] {0, 1}
|
||||||
|
@ -161,6 +186,9 @@ public class LauncherAppTransitionManager {
|
||||||
if (mLauncher.isInState(LauncherState.ALL_APPS) && !mDeviceProfile.isVerticalBarLayout()) {
|
if (mLauncher.isInState(LauncherState.ALL_APPS) && !mDeviceProfile.isVerticalBarLayout()) {
|
||||||
// All Apps in portrait mode is full screen, so we only animate AllAppsContainerView.
|
// All Apps in portrait mode is full screen, so we only animate AllAppsContainerView.
|
||||||
View appsView = mLauncher.getAppsView();
|
View appsView = mLauncher.getAppsView();
|
||||||
|
appsView.setAlpha(alphas[0]);
|
||||||
|
appsView.setTranslationY(trans[0]);
|
||||||
|
|
||||||
ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas);
|
ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas);
|
||||||
alpha.setDuration(217);
|
alpha.setDuration(217);
|
||||||
alpha.setInterpolator(Interpolators.LINEAR);
|
alpha.setInterpolator(Interpolators.LINEAR);
|
||||||
|
@ -168,9 +196,12 @@ public class LauncherAppTransitionManager {
|
||||||
transY.setInterpolator(Interpolators.AGGRESSIVE_EASE);
|
transY.setInterpolator(Interpolators.AGGRESSIVE_EASE);
|
||||||
transY.setDuration(350);
|
transY.setDuration(350);
|
||||||
|
|
||||||
hideLauncher.play(alpha);
|
launcherAnimator.play(alpha);
|
||||||
hideLauncher.play(transY);
|
launcherAnimator.play(transY);
|
||||||
} else {
|
} else {
|
||||||
|
mDragLayer.setAlpha(alphas[0]);
|
||||||
|
mDragLayer.setTranslationY(trans[0]);
|
||||||
|
|
||||||
ObjectAnimator dragLayerAlpha = ObjectAnimator.ofFloat(mDragLayer, View.ALPHA, alphas);
|
ObjectAnimator dragLayerAlpha = ObjectAnimator.ofFloat(mDragLayer, View.ALPHA, alphas);
|
||||||
dragLayerAlpha.setDuration(217);
|
dragLayerAlpha.setDuration(217);
|
||||||
dragLayerAlpha.setInterpolator(Interpolators.LINEAR);
|
dragLayerAlpha.setInterpolator(Interpolators.LINEAR);
|
||||||
|
@ -179,10 +210,10 @@ public class LauncherAppTransitionManager {
|
||||||
dragLayerTransY.setInterpolator(Interpolators.AGGRESSIVE_EASE);
|
dragLayerTransY.setInterpolator(Interpolators.AGGRESSIVE_EASE);
|
||||||
dragLayerTransY.setDuration(350);
|
dragLayerTransY.setDuration(350);
|
||||||
|
|
||||||
hideLauncher.play(dragLayerAlpha);
|
launcherAnimator.play(dragLayerAlpha);
|
||||||
hideLauncher.play(dragLayerTransY);
|
launcherAnimator.play(dragLayerTransY);
|
||||||
}
|
}
|
||||||
return hideLauncher;
|
return launcherAnimator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -361,15 +392,22 @@ public class LauncherAppTransitionManager {
|
||||||
/**
|
/**
|
||||||
* Registers remote animations used when closing apps to home screen.
|
* Registers remote animations used when closing apps to home screen.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void registerRemoteAnimations() {
|
public void registerRemoteAnimations() {
|
||||||
RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
|
if (hasControlRemoteAppTransitionPermission()) {
|
||||||
definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
|
try {
|
||||||
new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(), 0,
|
RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
|
||||||
CLOSING_TRANSITION_DURATION_MS));
|
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
|
// TODO: App controlled transition for unlock to home TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
|
||||||
|
|
||||||
new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
|
new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
|
||||||
|
} catch (NoClassDefFoundError e) {
|
||||||
|
// Gracefully fall back if the user's platform doesn't have the latest changes
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -385,11 +423,13 @@ public class LauncherAppTransitionManager {
|
||||||
postAtFrontOfQueueAsynchronously(handler, () -> {
|
postAtFrontOfQueueAsynchronously(handler, () -> {
|
||||||
// We use a separate transition for Overview mode.
|
// We use a separate transition for Overview mode.
|
||||||
if (mLauncher.isInState(LauncherState.OVERVIEW)) {
|
if (mLauncher.isInState(LauncherState.OVERVIEW)) {
|
||||||
|
setCurrentAnimator(null);
|
||||||
finishedCallback.run();
|
finishedCallback.run();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mAnimator = new AnimatorSet();
|
mAnimator = new AnimatorSet();
|
||||||
|
setCurrentAnimator(mAnimator);
|
||||||
mAnimator.addListener(new AnimatorListenerAdapter() {
|
mAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
@ -465,7 +505,9 @@ public class LauncherAppTransitionManager {
|
||||||
private AnimatorSet getLauncherResumeAnimation() {
|
private AnimatorSet getLauncherResumeAnimation() {
|
||||||
if (mLauncher.isInState(LauncherState.ALL_APPS)
|
if (mLauncher.isInState(LauncherState.ALL_APPS)
|
||||||
|| mLauncher.getDeviceProfile().isVerticalBarLayout()) {
|
|| mLauncher.getDeviceProfile().isVerticalBarLayout()) {
|
||||||
return getLauncherContentAnimator(true /* show */);
|
AnimatorSet contentAnimator = getLauncherContentAnimator(true /* show */);
|
||||||
|
contentAnimator.setStartDelay(LAUNCHER_RESUME_START_DELAY);
|
||||||
|
return contentAnimator;
|
||||||
} else {
|
} else {
|
||||||
AnimatorSet workspaceAnimator = new AnimatorSet();
|
AnimatorSet workspaceAnimator = new AnimatorSet();
|
||||||
mLauncher.getWorkspace().setTranslationY(mWorkspaceTransY);
|
mLauncher.getWorkspace().setTranslationY(mWorkspaceTransY);
|
||||||
|
@ -474,7 +516,7 @@ public class LauncherAppTransitionManager {
|
||||||
View.TRANSLATION_Y, mWorkspaceTransY, 0));
|
View.TRANSLATION_Y, mWorkspaceTransY, 0));
|
||||||
workspaceAnimator.play(ObjectAnimator.ofFloat(mLauncher.getWorkspace(), View.ALPHA,
|
workspaceAnimator.play(ObjectAnimator.ofFloat(mLauncher.getWorkspace(), View.ALPHA,
|
||||||
0, 1f));
|
0, 1f));
|
||||||
workspaceAnimator.setStartDelay(150);
|
workspaceAnimator.setStartDelay(LAUNCHER_RESUME_START_DELAY);
|
||||||
workspaceAnimator.setDuration(333);
|
workspaceAnimator.setDuration(333);
|
||||||
workspaceAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
workspaceAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
||||||
|
|
||||||
|
@ -489,7 +531,7 @@ public class LauncherAppTransitionManager {
|
||||||
|
|
||||||
Animator allAppsSlideIn =
|
Animator allAppsSlideIn =
|
||||||
ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS, startY, slideEnd);
|
ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS, startY, slideEnd);
|
||||||
allAppsSlideIn.setStartDelay(150);
|
allAppsSlideIn.setStartDelay(LAUNCHER_RESUME_START_DELAY);
|
||||||
allAppsSlideIn.setDuration(317);
|
allAppsSlideIn.setDuration(317);
|
||||||
allAppsSlideIn.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
allAppsSlideIn.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
||||||
|
|
||||||
|
@ -505,6 +547,11 @@ public class LauncherAppTransitionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasControlRemoteAppTransitionPermission() {
|
||||||
|
return mLauncher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION)
|
||||||
|
== PackageManager.PERMISSION_GRANTED;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method that allows us to get interpolated values for embedded
|
* Helper method that allows us to get interpolated values for embedded
|
||||||
* animations with a delay and/or different duration.
|
* animations with a delay and/or different duration.
|
|
@ -25,7 +25,6 @@ import android.view.View;
|
||||||
import android.view.View.AccessibilityDelegate;
|
import android.view.View.AccessibilityDelegate;
|
||||||
|
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherAppTransitionManager;
|
|
||||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||||
import com.android.launcher3.config.FeatureFlags;
|
import com.android.launcher3.config.FeatureFlags;
|
||||||
import com.android.launcher3.graphics.BitmapRenderer;
|
import com.android.launcher3.graphics.BitmapRenderer;
|
||||||
|
@ -84,31 +83,4 @@ public class UiFactory {
|
||||||
RecentsView recents = launcher.getOverviewPanel();
|
RecentsView recents = launcher.getOverviewPanel();
|
||||||
recents.reset();
|
recents.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasControlRemoteAppTransitionPermission(Launcher launcher) {
|
|
||||||
return launcher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION)
|
|
||||||
== PackageManager.PERMISSION_GRANTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Bundle getActivityLaunchOptions(Launcher launcher, View v) {
|
|
||||||
if (hasControlRemoteAppTransitionPermission(launcher)) {
|
|
||||||
try {
|
|
||||||
return new LauncherAppTransitionManager(launcher).getActivityLauncherOptions(v);
|
|
||||||
} catch (NoClassDefFoundError e) {
|
|
||||||
// Gracefully fall back to default launch options if the user's platform doesn't
|
|
||||||
// have the latest changes.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return launcher.getDefaultActivityLaunchOptions(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void registerRemoteAnimations(Launcher launcher) {
|
|
||||||
if (hasControlRemoteAppTransitionPermission(launcher)) {
|
|
||||||
try {
|
|
||||||
new LauncherAppTransitionManager(launcher).registerRemoteAnimations();
|
|
||||||
} catch (NoClassDefFoundError e) {
|
|
||||||
// Gracefully fall back if the user's platform doesn't have the latest changes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,9 @@
|
||||||
<!-- Name of a user event dispatcher class. -->
|
<!-- Name of a user event dispatcher class. -->
|
||||||
<string name="user_event_dispatcher_class" translatable="false"></string>
|
<string name="user_event_dispatcher_class" translatable="false"></string>
|
||||||
|
|
||||||
|
<!-- Name of an app transition manager class. -->
|
||||||
|
<string name="app_transition_manager_class" translatable="false"></string>
|
||||||
|
|
||||||
<!-- Name of a color extraction implementation class. -->
|
<!-- Name of a color extraction implementation class. -->
|
||||||
<string name="color_extraction_impl_class" translatable="false"></string>
|
<string name="color_extraction_impl_class" translatable="false"></string>
|
||||||
|
|
||||||
|
|
|
@ -214,6 +214,8 @@ public class Launcher extends BaseActivity
|
||||||
private static final int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 5;
|
private static final int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 5;
|
||||||
@Thunk static final int NEW_APPS_ANIMATION_DELAY = 500;
|
@Thunk static final int NEW_APPS_ANIMATION_DELAY = 500;
|
||||||
|
|
||||||
|
private LauncherAppTransitionManager mAppTransitionManager;
|
||||||
|
|
||||||
@Thunk Workspace mWorkspace;
|
@Thunk Workspace mWorkspace;
|
||||||
private View mLauncherView;
|
private View mLauncherView;
|
||||||
@Thunk DragLayer mDragLayer;
|
@Thunk DragLayer mDragLayer;
|
||||||
|
@ -403,8 +405,11 @@ public class Launcher extends BaseActivity
|
||||||
getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
|
getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
|
||||||
Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
|
Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
|
||||||
|
|
||||||
|
mAppTransitionManager = Utilities.getOverrideObject(LauncherAppTransitionManager.class,
|
||||||
|
this, R.string.app_transition_manager_class);
|
||||||
|
|
||||||
if (!isInMultiWindowModeCompat()) {
|
if (!isInMultiWindowModeCompat()) {
|
||||||
UiFactory.registerRemoteAnimations(this);
|
mAppTransitionManager.registerRemoteAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mLauncherCallbacks != null) {
|
if (mLauncherCallbacks != null) {
|
||||||
|
@ -1918,38 +1923,11 @@ public class Launcher extends BaseActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bundle getDefaultActivityLaunchOptions(View v) {
|
|
||||||
if (Utilities.ATLEAST_MARSHMALLOW) {
|
|
||||||
int left = 0, top = 0;
|
|
||||||
int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
|
|
||||||
if (v instanceof BubbleTextView) {
|
|
||||||
// Launch from center of icon, not entire view
|
|
||||||
Drawable icon = ((BubbleTextView) v).getIcon();
|
|
||||||
if (icon != null) {
|
|
||||||
Rect bounds = icon.getBounds();
|
|
||||||
left = (width - bounds.width()) / 2;
|
|
||||||
top = v.getPaddingTop();
|
|
||||||
width = bounds.width();
|
|
||||||
height = bounds.height();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ActivityOptions.makeClipRevealAnimation(v, left, top, width, height)
|
|
||||||
.toBundle();
|
|
||||||
} else if (Utilities.ATLEAST_LOLLIPOP_MR1) {
|
|
||||||
// On L devices, we use the device default slide-up transition.
|
|
||||||
// On L MR1 devices, we use a custom version of the slide-up transition which
|
|
||||||
// doesn't have the delay present in the device default.
|
|
||||||
return ActivityOptions.makeCustomAnimation(
|
|
||||||
this, R.anim.task_open_enter, R.anim.no_anim).toBundle();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.M)
|
@TargetApi(Build.VERSION_CODES.M)
|
||||||
public Bundle getActivityLaunchOptions(View v, boolean useDefaultLaunchOptions) {
|
public Bundle getActivityLaunchOptions(View v, boolean useDefaultLaunchOptions) {
|
||||||
return useDefaultLaunchOptions
|
return useDefaultLaunchOptions
|
||||||
? getDefaultActivityLaunchOptions(v)
|
? mAppTransitionManager.getDefaultActivityLaunchOptions(this, v)
|
||||||
: UiFactory.getActivityLaunchOptions(this, v);
|
: mAppTransitionManager.getActivityLaunchOptions(this, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rect getViewBounds(View v) {
|
public Rect getViewBounds(View v) {
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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.app.ActivityOptions;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the opening and closing app transitions from Launcher.
|
||||||
|
*/
|
||||||
|
public class LauncherAppTransitionManager {
|
||||||
|
|
||||||
|
public Bundle getDefaultActivityLaunchOptions(Launcher launcher, View v) {
|
||||||
|
if (Utilities.ATLEAST_MARSHMALLOW) {
|
||||||
|
int left = 0, top = 0;
|
||||||
|
int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
|
||||||
|
if (v instanceof BubbleTextView) {
|
||||||
|
// Launch from center of icon, not entire view
|
||||||
|
Drawable icon = ((BubbleTextView) v).getIcon();
|
||||||
|
if (icon != null) {
|
||||||
|
Rect bounds = icon.getBounds();
|
||||||
|
left = (width - bounds.width()) / 2;
|
||||||
|
top = v.getPaddingTop();
|
||||||
|
width = bounds.width();
|
||||||
|
height = bounds.height();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ActivityOptions.makeClipRevealAnimation(v, left, top, width, height)
|
||||||
|
.toBundle();
|
||||||
|
} else if (Utilities.ATLEAST_LOLLIPOP_MR1) {
|
||||||
|
// On L devices, we use the device default slide-up transition.
|
||||||
|
// On L MR1 devices, we use a custom version of the slide-up transition which
|
||||||
|
// doesn't have the delay present in the device default.
|
||||||
|
return ActivityOptions.makeCustomAnimation(launcher, R.anim.task_open_enter,
|
||||||
|
R.anim.no_anim).toBundle();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bundle getActivityLaunchOptions(Launcher launcher, View v) {
|
||||||
|
return getDefaultActivityLaunchOptions(launcher, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerRemoteAnimations() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,10 +61,4 @@ public class UiFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void resetOverview(Launcher launcher) { }
|
public static void resetOverview(Launcher launcher) { }
|
||||||
|
|
||||||
public static Bundle getActivityLaunchOptions(Launcher launcher, View v) {
|
|
||||||
return launcher.getDefaultActivityLaunchOptions(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void registerRemoteAnimations(Launcher launcher) { }
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue