Merge "Merging from ub-launcher3-master @ build 6304996" into rvc-dev am: c83758f223
Change-Id: I5a6d4f5198e8aace4ad3a6c27b8d5be5893f7755
This commit is contained in:
+15
-13
@@ -20,15 +20,14 @@ import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
|||||||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||||
import static com.android.launcher3.LauncherState.NORMAL;
|
import static com.android.launcher3.LauncherState.NORMAL;
|
||||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||||
import static com.android.launcher3.LauncherStateManager.ANIM_ALL_COMPONENTS;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
|
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
|
||||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
|
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
|
||||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
|
||||||
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
|
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
|
||||||
import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator;
|
import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator;
|
||||||
|
|
||||||
@@ -47,9 +46,9 @@ import androidx.annotation.Nullable;
|
|||||||
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
||||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
|
||||||
import com.android.launcher3.anim.Interpolators;
|
import com.android.launcher3.anim.Interpolators;
|
||||||
import com.android.launcher3.anim.SpringAnimationBuilder;
|
import com.android.launcher3.anim.SpringAnimationBuilder;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||||
import com.android.quickstep.views.RecentsView;
|
import com.android.quickstep.views.RecentsView;
|
||||||
@@ -210,17 +209,20 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
|
|||||||
.setValues(values)
|
.setValues(values)
|
||||||
.build(mLauncher);
|
.build(mLauncher);
|
||||||
case INDEX_PAUSE_TO_OVERVIEW_ANIM: {
|
case INDEX_PAUSE_TO_OVERVIEW_ANIM: {
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
StateAnimationConfig config = new StateAnimationConfig();
|
||||||
builder.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
|
config.duration = ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
|
||||||
builder.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
|
|
||||||
|
config.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
|
||||||
|
config.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
|
||||||
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
||||||
builder.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
|
config.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
|
||||||
builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
|
config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LauncherStateManager stateManager = mLauncher.getStateManager();
|
LauncherStateManager stateManager = mLauncher.getStateManager();
|
||||||
return stateManager.createAtomicAnimation(
|
return stateManager.createAtomicAnimation(
|
||||||
stateManager.getCurrentStableState(), OVERVIEW, builder,
|
stateManager.getCurrentStableState(), OVERVIEW, config);
|
||||||
ANIM_ALL_COMPONENTS, ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
+10
-14
@@ -20,7 +20,6 @@ import static com.android.launcher3.anim.Interpolators.LINEAR;
|
|||||||
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
|
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
|
||||||
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
||||||
|
|
||||||
import android.animation.ValueAnimator;
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.FloatProperty;
|
import android.util.FloatProperty;
|
||||||
@@ -29,10 +28,10 @@ import androidx.annotation.NonNull;
|
|||||||
|
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
|
||||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.anim.PropertySetter;
|
import com.android.launcher3.anim.PropertySetter;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.quickstep.views.ClearAllButton;
|
import com.android.quickstep.views.ClearAllButton;
|
||||||
import com.android.quickstep.views.LauncherRecentsView;
|
import com.android.quickstep.views.LauncherRecentsView;
|
||||||
import com.android.quickstep.views.RecentsView;
|
import com.android.quickstep.views.RecentsView;
|
||||||
@@ -61,25 +60,22 @@ public final class RecentsViewStateController extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void setStateWithAnimationInternal(@NonNull final LauncherState toState,
|
void setStateWithAnimationInternal(@NonNull LauncherState toState,
|
||||||
@NonNull AnimatorSetBuilder builder, @NonNull AnimationConfig config) {
|
@NonNull StateAnimationConfig config, @NonNull PendingAnimation builder) {
|
||||||
super.setStateWithAnimationInternal(toState, builder, config);
|
super.setStateWithAnimationInternal(toState, config, builder);
|
||||||
|
|
||||||
ValueAnimator updateAnim = ValueAnimator.ofFloat(0, 1).setDuration(config.duration);
|
|
||||||
if (toState.overviewUi) {
|
if (toState.overviewUi) {
|
||||||
// While animating into recents, update the visible task data as needed
|
// While animating into recents, update the visible task data as needed
|
||||||
updateAnim.addUpdateListener(valueAnimator -> mRecentsView.loadVisibleTaskData());
|
builder.addOnFrameCallback(mRecentsView::loadVisibleTaskData);
|
||||||
mRecentsView.updateEmptyMessage();
|
mRecentsView.updateEmptyMessage();
|
||||||
} else {
|
} else {
|
||||||
updateAnim.addListener(
|
builder.getAnim().addListener(
|
||||||
AnimationSuccessListener.forRunnable(mRecentsView::resetTaskVisuals));
|
AnimationSuccessListener.forRunnable(mRecentsView::resetTaskVisuals));
|
||||||
}
|
}
|
||||||
builder.play(updateAnim);
|
|
||||||
|
|
||||||
PropertySetter propertySetter = config.getPropertySetter(builder);
|
setAlphas(builder, toState.getVisibleElements(mLauncher));
|
||||||
setAlphas(propertySetter, toState.getVisibleElements(mLauncher));
|
builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS,
|
||||||
float fullscreenProgress = toState.getOverviewFullscreenProgress();
|
toState.getOverviewFullscreenProgress(), LINEAR);
|
||||||
propertySetter.setFloat(mRecentsView, FULLSCREEN_PROGRESS, fullscreenProgress, LINEAR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAlphas(PropertySetter propertySetter, int visibleElements) {
|
private void setAlphas(PropertySetter propertySetter, int visibleElements) {
|
||||||
|
|||||||
+9
-8
@@ -14,17 +14,18 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.android.launcher3.uioverrides.states;
|
package com.android.launcher3.uioverrides.states;
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCRIM_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
|
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||||
|
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
|
|
||||||
public class OverviewPeekState extends OverviewState {
|
public class OverviewPeekState extends OverviewState {
|
||||||
public OverviewPeekState(int id) {
|
public OverviewPeekState(int id) {
|
||||||
@@ -41,11 +42,11 @@ public class OverviewPeekState extends OverviewState {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
|
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
|
||||||
AnimatorSetBuilder builder) {
|
StateAnimationConfig config) {
|
||||||
if (this == OVERVIEW_PEEK && fromState == NORMAL) {
|
if (this == OVERVIEW_PEEK && fromState == NORMAL) {
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
|
config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
|
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN);
|
config.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-17
@@ -18,13 +18,6 @@ package com.android.launcher3.uioverrides.states;
|
|||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
|
|
||||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_Y;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
|
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
|
||||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||||
@@ -32,6 +25,13 @@ import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
|
|||||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
||||||
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
|
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
|
||||||
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
|
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
|
||||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||||
|
|
||||||
@@ -48,8 +48,8 @@ import com.android.launcher3.LauncherState;
|
|||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.Workspace;
|
import com.android.launcher3.Workspace;
|
||||||
import com.android.launcher3.allapps.DiscoveryBounce;
|
import com.android.launcher3.allapps.DiscoveryBounce;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
|
||||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||||
import com.android.quickstep.SysUINavigationMode;
|
import com.android.quickstep.SysUINavigationMode;
|
||||||
@@ -225,14 +225,14 @@ public class OverviewState extends LauncherState {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
|
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
|
||||||
AnimatorSetBuilder builder) {
|
StateAnimationConfig config) {
|
||||||
if ((fromState == NORMAL || fromState == HINT_STATE) && this == OVERVIEW) {
|
if ((fromState == NORMAL || fromState == HINT_STATE) && this == OVERVIEW) {
|
||||||
if (SysUINavigationMode.getMode(launcher) == NO_BUTTON) {
|
if (SysUINavigationMode.getMode(launcher) == NO_BUTTON) {
|
||||||
builder.setInterpolator(ANIM_WORKSPACE_SCALE,
|
config.setInterpolator(ANIM_WORKSPACE_SCALE,
|
||||||
fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
|
fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
|
||||||
builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
|
config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
|
||||||
} else {
|
} else {
|
||||||
builder.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
|
config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
|
||||||
|
|
||||||
// Scale up the recents, if it is not coming from the side
|
// Scale up the recents, if it is not coming from the side
|
||||||
RecentsView overview = launcher.getOverviewPanel();
|
RecentsView overview = launcher.getOverviewPanel();
|
||||||
@@ -240,15 +240,15 @@ public class OverviewState extends LauncherState {
|
|||||||
SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
|
SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
|
config.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
|
config.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
|
||||||
Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get()
|
Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get()
|
||||||
&& removeShelfFromOverview(launcher)
|
&& removeShelfFromOverview(launcher)
|
||||||
? OVERSHOOT_1_2
|
? OVERSHOOT_1_2
|
||||||
: OVERSHOOT_1_7;
|
: OVERSHOOT_1_7;
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator);
|
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator);
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, translationInterpolator);
|
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, translationInterpolator);
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
|
config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
-19
@@ -21,16 +21,16 @@ import static com.android.launcher3.LauncherState.ALL_APPS;
|
|||||||
import static com.android.launcher3.LauncherState.NORMAL;
|
import static com.android.launcher3.LauncherState.NORMAL;
|
||||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||||
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
|
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
|
||||||
import static com.android.launcher3.LauncherStateManager.PLAY_ATOMIC_OVERVIEW_PEEK;
|
|
||||||
import static com.android.launcher3.LauncherStateManager.SKIP_OVERVIEW;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_HEADER_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
|
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_HEADER_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
|
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
|
||||||
|
|
||||||
@@ -44,10 +44,10 @@ import android.view.ViewConfiguration;
|
|||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherAppTransitionManagerImpl;
|
import com.android.launcher3.LauncherAppTransitionManagerImpl;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationFlags;
|
|
||||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
|
||||||
import com.android.launcher3.anim.Interpolators;
|
import com.android.launcher3.anim.Interpolators;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||||
import com.android.launcher3.util.VibratorWrapper;
|
import com.android.launcher3.util.VibratorWrapper;
|
||||||
import com.android.quickstep.SystemUiProxy;
|
import com.android.quickstep.SystemUiProxy;
|
||||||
@@ -105,8 +105,12 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
|||||||
LauncherState fromState = isPaused ? NORMAL : OVERVIEW_PEEK;
|
LauncherState fromState = isPaused ? NORMAL : OVERVIEW_PEEK;
|
||||||
LauncherState toState = isPaused ? OVERVIEW_PEEK : NORMAL;
|
LauncherState toState = isPaused ? OVERVIEW_PEEK : NORMAL;
|
||||||
long peekDuration = isPaused ? PEEK_IN_ANIM_DURATION : PEEK_OUT_ANIM_DURATION;
|
long peekDuration = isPaused ? PEEK_IN_ANIM_DURATION : PEEK_OUT_ANIM_DURATION;
|
||||||
mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(fromState, toState,
|
|
||||||
new AnimatorSetBuilder(), PLAY_ATOMIC_OVERVIEW_PEEK, peekDuration);
|
StateAnimationConfig config = new StateAnimationConfig();
|
||||||
|
config.duration = peekDuration;
|
||||||
|
config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
|
||||||
|
mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(
|
||||||
|
fromState, toState, config);
|
||||||
mPeekAnim.addListener(new AnimatorListenerAdapter() {
|
mPeekAnim.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
@@ -130,10 +134,10 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AnimatorSetBuilder getAnimatorSetBuilderForStates(LauncherState fromState,
|
protected StateAnimationConfig getConfigForStates(
|
||||||
LauncherState toState) {
|
LauncherState fromState, LauncherState toState) {
|
||||||
if (fromState == NORMAL && toState == ALL_APPS) {
|
if (fromState == NORMAL && toState == ALL_APPS) {
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
StateAnimationConfig builder = new StateAnimationConfig();
|
||||||
// Fade in prediction icons quickly, then rest of all apps after reaching overview.
|
// Fade in prediction icons quickly, then rest of all apps after reaching overview.
|
||||||
float progressToReachOverview = NORMAL.getVerticalProgress(mLauncher)
|
float progressToReachOverview = NORMAL.getVerticalProgress(mLauncher)
|
||||||
- OVERVIEW.getVerticalProgress(mLauncher);
|
- OVERVIEW.getVerticalProgress(mLauncher);
|
||||||
@@ -152,7 +156,7 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
|||||||
builder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_3);
|
builder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_3);
|
||||||
return builder;
|
return builder;
|
||||||
} else if (fromState == ALL_APPS && toState == NORMAL) {
|
} else if (fromState == ALL_APPS && toState == NORMAL) {
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
StateAnimationConfig builder = new StateAnimationConfig();
|
||||||
// Keep all apps/predictions opaque until the very end of the transition.
|
// Keep all apps/predictions opaque until the very end of the transition.
|
||||||
float progressToReachOverview = OVERVIEW.getVerticalProgress(mLauncher);
|
float progressToReachOverview = OVERVIEW.getVerticalProgress(mLauncher);
|
||||||
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
|
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
|
||||||
@@ -165,7 +169,7 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
|||||||
1));
|
1));
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
return super.getAnimatorSetBuilderForStates(fromState, toState);
|
return super.getConfigForStates(fromState, toState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -211,9 +215,11 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
|||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
super.onAnimationEnd(animation);
|
super.onAnimationEnd(animation);
|
||||||
if (mCancelled) {
|
if (mCancelled) {
|
||||||
mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(mFromState,
|
StateAnimationConfig config = new StateAnimationConfig();
|
||||||
mToState, new AnimatorSetBuilder(), PLAY_ATOMIC_OVERVIEW_PEEK,
|
config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
|
||||||
PEEK_OUT_ANIM_DURATION);
|
config.duration = PEEK_OUT_ANIM_DURATION;
|
||||||
|
mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(
|
||||||
|
mFromState, mToState, config);
|
||||||
mPeekAnim.start();
|
mPeekAnim.start();
|
||||||
}
|
}
|
||||||
mAtomicAnim = null;
|
mAtomicAnim = null;
|
||||||
|
|||||||
+18
-31
@@ -15,8 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.launcher3.uioverrides.touchcontrollers;
|
package com.android.launcher3.uioverrides.touchcontrollers;
|
||||||
|
|
||||||
import static android.view.View.TRANSLATION_X;
|
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||||
|
|
||||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||||
import static com.android.launcher3.LauncherState.NORMAL;
|
import static com.android.launcher3.LauncherState.NORMAL;
|
||||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||||
@@ -26,9 +25,6 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI
|
|||||||
import static com.android.launcher3.touch.AbstractStateChangeTouchController.SUCCESS_TRANSITION_PROGRESS;
|
import static com.android.launcher3.touch.AbstractStateChangeTouchController.SUCCESS_TRANSITION_PROGRESS;
|
||||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
||||||
|
|
||||||
import android.animation.Animator;
|
|
||||||
import android.animation.AnimatorSet;
|
|
||||||
import android.animation.ObjectAnimator;
|
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.animation.Interpolator;
|
import android.view.animation.Interpolator;
|
||||||
@@ -36,16 +32,16 @@ import android.view.animation.Interpolator;
|
|||||||
import com.android.launcher3.AbstractFloatingView;
|
import com.android.launcher3.AbstractFloatingView;
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
|
||||||
import com.android.launcher3.anim.Interpolators;
|
import com.android.launcher3.anim.Interpolators;
|
||||||
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||||
import com.android.launcher3.config.FeatureFlags;
|
import com.android.launcher3.config.FeatureFlags;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||||
@@ -132,46 +128,37 @@ public class NavBarToHomeTouchController implements TouchController,
|
|||||||
|
|
||||||
private void initCurrentAnimation() {
|
private void initCurrentAnimation() {
|
||||||
long accuracy = (long) (getShiftRange() * 2);
|
long accuracy = (long) (getShiftRange() * 2);
|
||||||
final AnimatorSet anim = new AnimatorSet();
|
final PendingAnimation builder = new PendingAnimation(accuracy);
|
||||||
if (mStartState == OVERVIEW) {
|
if (mStartState == OVERVIEW) {
|
||||||
RecentsView recentsView = mLauncher.getOverviewPanel();
|
RecentsView recentsView = mLauncher.getOverviewPanel();
|
||||||
float pullbackDist = mPullbackDistance;
|
float pullbackDist = mPullbackDistance;
|
||||||
if (!recentsView.isRtl()) {
|
if (!recentsView.isRtl()) {
|
||||||
pullbackDist = -pullbackDist;
|
pullbackDist = -pullbackDist;
|
||||||
}
|
}
|
||||||
ObjectAnimator pullback = ObjectAnimator.ofFloat(recentsView, TRANSLATION_X,
|
|
||||||
pullbackDist);
|
builder.setFloat(recentsView, VIEW_TRANSLATE_X, pullbackDist, PULLBACK_INTERPOLATOR);
|
||||||
pullback.setInterpolator(PULLBACK_INTERPOLATOR);
|
|
||||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||||
pullback.addUpdateListener(
|
builder.addOnFrameCallback(
|
||||||
valueAnimator -> recentsView.redrawLiveTile(false /* mightNeedToRefill */));
|
() -> recentsView.redrawLiveTile(false /* mightNeedToRefill */));
|
||||||
}
|
}
|
||||||
anim.play(pullback);
|
|
||||||
} else if (mStartState == ALL_APPS) {
|
} else if (mStartState == ALL_APPS) {
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
|
||||||
AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
|
AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
|
||||||
Animator allAppsProgress = ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS,
|
builder.setFloat(allAppsController, ALL_APPS_PROGRESS,
|
||||||
-mPullbackDistance / allAppsController.getShiftRange());
|
-mPullbackDistance / allAppsController.getShiftRange(), PULLBACK_INTERPOLATOR);
|
||||||
allAppsProgress.setInterpolator(PULLBACK_INTERPOLATOR);
|
|
||||||
builder.play(allAppsProgress);
|
|
||||||
// Slightly fade out all apps content to further distinguish from scrolling.
|
// Slightly fade out all apps content to further distinguish from scrolling.
|
||||||
builder.setInterpolator(AnimatorSetBuilder.ANIM_ALL_APPS_FADE, Interpolators
|
StateAnimationConfig config = new StateAnimationConfig();
|
||||||
.mapToProgress(PULLBACK_INTERPOLATOR, 0, 0.5f));
|
|
||||||
AnimationConfig config = new AnimationConfig();
|
|
||||||
config.duration = accuracy;
|
config.duration = accuracy;
|
||||||
allAppsController.setAlphas(mEndState.getVisibleElements(mLauncher), config, builder);
|
config.setInterpolator(StateAnimationConfig.ANIM_ALL_APPS_FADE, Interpolators
|
||||||
anim.play(builder.build());
|
.mapToProgress(PULLBACK_INTERPOLATOR, 0, 0.5f));
|
||||||
|
|
||||||
|
allAppsController.setAlphas(mEndState, config, builder);
|
||||||
}
|
}
|
||||||
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||||
if (topView != null) {
|
if (topView != null) {
|
||||||
Animator hintCloseAnim = topView.createHintCloseAnim(mPullbackDistance);
|
topView.addHintCloseAnim(mPullbackDistance, PULLBACK_INTERPOLATOR, builder);
|
||||||
if (hintCloseAnim != null) {
|
|
||||||
hintCloseAnim.setInterpolator(PULLBACK_INTERPOLATOR);
|
|
||||||
anim.play(hintCloseAnim);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
anim.setDuration(accuracy);
|
mCurrentAnimation = builder.createPlaybackController()
|
||||||
mCurrentAnimation = AnimatorPlaybackController.wrap(anim, accuracy)
|
|
||||||
.setOnCancelRunnable(this::clearState);
|
.setOnCancelRunnable(this::clearState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -19,9 +19,9 @@ package com.android.launcher3.uioverrides.touchcontrollers;
|
|||||||
import static com.android.launcher3.LauncherState.HINT_STATE;
|
import static com.android.launcher3.LauncherState.HINT_STATE;
|
||||||
import static com.android.launcher3.LauncherState.NORMAL;
|
import static com.android.launcher3.LauncherState.NORMAL;
|
||||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||||
import static com.android.launcher3.LauncherStateManager.PLAY_ATOMIC_OVERVIEW_PEEK;
|
|
||||||
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
|
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
|
||||||
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
|
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
|
||||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||||
|
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
@@ -34,7 +34,7 @@ import com.android.launcher3.LauncherState;
|
|||||||
import com.android.launcher3.LauncherStateManager;
|
import com.android.launcher3.LauncherStateManager;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||||
import com.android.launcher3.util.VibratorWrapper;
|
import com.android.launcher3.util.VibratorWrapper;
|
||||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||||
@@ -171,11 +171,11 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
|
|||||||
|
|
||||||
// StaggeredWorkspaceAnim doesn't animate overview, so we handle it here.
|
// StaggeredWorkspaceAnim doesn't animate overview, so we handle it here.
|
||||||
stateManager.cancelAnimation();
|
stateManager.cancelAnimation();
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
StateAnimationConfig config = new StateAnimationConfig();
|
||||||
long duration = OVERVIEW.getTransitionDuration(mLauncher);
|
config.duration = OVERVIEW.getTransitionDuration(mLauncher);
|
||||||
|
config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
|
||||||
AnimatorSet anim = stateManager.createAtomicAnimation(
|
AnimatorSet anim = stateManager.createAtomicAnimation(
|
||||||
stateManager.getState(), NORMAL, builder,
|
stateManager.getState(), NORMAL, config);
|
||||||
PLAY_ATOMIC_OVERVIEW_PEEK, duration);
|
|
||||||
anim.addListener(AnimationSuccessListener.forRunnable(
|
anim.addListener(AnimationSuccessListener.forRunnable(
|
||||||
() -> onSwipeInteractionCompleted(NORMAL, Touch.SWIPE)));
|
() -> onSwipeInteractionCompleted(NORMAL, Touch.SWIPE)));
|
||||||
anim.start();
|
anim.start();
|
||||||
|
|||||||
+20
-21
@@ -21,18 +21,18 @@ import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
|||||||
import static com.android.launcher3.LauncherState.NORMAL;
|
import static com.android.launcher3.LauncherState.NORMAL;
|
||||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||||
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
|
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
|
||||||
import static com.android.launcher3.LauncherStateManager.ANIM_ALL_COMPONENTS;
|
|
||||||
import static com.android.launcher3.LauncherStateManager.SKIP_OVERVIEW;
|
|
||||||
import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
|
import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
|
import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
|
||||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_5;
|
import static com.android.launcher3.anim.Interpolators.DEACCEL_5;
|
||||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||||
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
|
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
|
||||||
|
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||||
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
|
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
|
||||||
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
|
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
|
||||||
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
||||||
@@ -55,15 +55,13 @@ import android.view.animation.Interpolator;
|
|||||||
|
|
||||||
import com.android.launcher3.BaseQuickstepLauncher;
|
import com.android.launcher3.BaseQuickstepLauncher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationFlags;
|
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
|
||||||
import com.android.launcher3.config.FeatureFlags;
|
import com.android.launcher3.config.FeatureFlags;
|
||||||
import com.android.launcher3.graphics.OverviewScrim;
|
import com.android.launcher3.graphics.OverviewScrim;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.launcher3.touch.BaseSwipeDetector;
|
import com.android.launcher3.touch.BaseSwipeDetector;
|
||||||
import com.android.launcher3.touch.BothAxesSwipeDetector;
|
import com.android.launcher3.touch.BothAxesSwipeDetector;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
@@ -192,11 +190,9 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
|||||||
ShelfAnimState shelfState = isPaused ? PEEK : HIDE;
|
ShelfAnimState shelfState = isPaused ? PEEK : HIDE;
|
||||||
if (shelfState == PEEK) {
|
if (shelfState == PEEK) {
|
||||||
// Some shelf elements (e.g. qsb) were hidden, but we need them visible when peeking.
|
// Some shelf elements (e.g. qsb) were hidden, but we need them visible when peeking.
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
|
||||||
AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
|
AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
|
||||||
allAppsController.setAlphas(NORMAL.getVisibleElements(mLauncher),
|
allAppsController.setAlphas(
|
||||||
new AnimationConfig(), builder);
|
NORMAL, new StateAnimationConfig(), NO_ANIM_PROPERTY_SETTER);
|
||||||
builder.build().setDuration(0).start();
|
|
||||||
|
|
||||||
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
||||||
// Hotseat was hidden, but we need it visible when peeking.
|
// Hotseat was hidden, but we need it visible when peeking.
|
||||||
@@ -209,12 +205,12 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
|||||||
|
|
||||||
private void setupAnimators() {
|
private void setupAnimators() {
|
||||||
// Animate the non-overview components (e.g. workspace, shelf) out of the way.
|
// Animate the non-overview components (e.g. workspace, shelf) out of the way.
|
||||||
AnimatorSetBuilder nonOverviewBuilder = new AnimatorSetBuilder();
|
StateAnimationConfig nonOverviewBuilder = new StateAnimationConfig();
|
||||||
nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_FADE, FADE_OUT_INTERPOLATOR);
|
nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_FADE, FADE_OUT_INTERPOLATOR);
|
||||||
nonOverviewBuilder.setInterpolator(ANIM_ALL_APPS_FADE, FADE_OUT_INTERPOLATOR);
|
nonOverviewBuilder.setInterpolator(ANIM_ALL_APPS_FADE, FADE_OUT_INTERPOLATOR);
|
||||||
nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, TRANSLATE_OUT_INTERPOLATOR);
|
nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, TRANSLATE_OUT_INTERPOLATOR);
|
||||||
nonOverviewBuilder.setInterpolator(ANIM_VERTICAL_PROGRESS, TRANSLATE_OUT_INTERPOLATOR);
|
nonOverviewBuilder.setInterpolator(ANIM_VERTICAL_PROGRESS, TRANSLATE_OUT_INTERPOLATOR);
|
||||||
updateNonOverviewAnim(QUICK_SWITCH, nonOverviewBuilder, ANIM_ALL_COMPONENTS);
|
updateNonOverviewAnim(QUICK_SWITCH, nonOverviewBuilder);
|
||||||
mNonOverviewAnim.dispatchOnStart();
|
mNonOverviewAnim.dispatchOnStart();
|
||||||
|
|
||||||
if (mRecentsView.getTaskViewCount() == 0) {
|
if (mRecentsView.getTaskViewCount() == 0) {
|
||||||
@@ -230,11 +226,12 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Create state animation to control non-overview components. */
|
/** Create state animation to control non-overview components. */
|
||||||
private void updateNonOverviewAnim(LauncherState toState, AnimatorSetBuilder builder,
|
private void updateNonOverviewAnim(LauncherState toState, StateAnimationConfig config) {
|
||||||
@AnimationFlags int animComponents) {
|
config.duration = (long) (Math.max(mXRange, mYRange) * 2);
|
||||||
long accuracy = (long) (Math.max(mXRange, mYRange) * 2);
|
config.animFlags = config.animFlags | SKIP_OVERVIEW;
|
||||||
mNonOverviewAnim = mLauncher.getStateManager().createAnimationToNewWorkspace(toState,
|
mNonOverviewAnim = mLauncher.getStateManager()
|
||||||
builder, accuracy, this::clearState, animComponents | SKIP_OVERVIEW);
|
.createAnimationToNewWorkspace(toState, config)
|
||||||
|
.setOnCancelRunnable(this::clearState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupOverviewAnimators() {
|
private void setupOverviewAnimators() {
|
||||||
@@ -419,8 +416,10 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
|||||||
if (flingUpToNormal && !mIsHomeScreenVisible) {
|
if (flingUpToNormal && !mIsHomeScreenVisible) {
|
||||||
// We are flinging to home while workspace is invisible, run the same staggered
|
// We are flinging to home while workspace is invisible, run the same staggered
|
||||||
// animation as from an app.
|
// animation as from an app.
|
||||||
|
StateAnimationConfig config = new StateAnimationConfig();
|
||||||
// Update mNonOverviewAnim to do nothing so it doesn't interfere.
|
// Update mNonOverviewAnim to do nothing so it doesn't interfere.
|
||||||
updateNonOverviewAnim(targetState, new AnimatorSetBuilder(), 0 /* animComponents */);
|
config.animFlags = 0;
|
||||||
|
updateNonOverviewAnim(targetState, config);
|
||||||
nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer();
|
nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer();
|
||||||
|
|
||||||
new StaggeredWorkspaceAnim(mLauncher, velocity.y, false /* animateOverviewScrim */)
|
new StaggeredWorkspaceAnim(mLauncher, velocity.y, false /* animateOverviewScrim */)
|
||||||
|
|||||||
+26
-27
@@ -17,18 +17,17 @@ package com.android.launcher3.uioverrides.touchcontrollers;
|
|||||||
|
|
||||||
import static com.android.launcher3.LauncherState.NORMAL;
|
import static com.android.launcher3.LauncherState.NORMAL;
|
||||||
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
|
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
|
||||||
import static com.android.launcher3.LauncherStateManager.ANIM_ALL_COMPONENTS;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_Y;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
|
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
|
||||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
|
||||||
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
|
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
|
||||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
||||||
@@ -41,7 +40,7 @@ import androidx.annotation.Nullable;
|
|||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.launcher3.touch.AbstractStateChangeTouchController;
|
import com.android.launcher3.touch.AbstractStateChangeTouchController;
|
||||||
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
@@ -108,30 +107,30 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected float initCurrentAnimation(int animComponents) {
|
protected float initCurrentAnimation(int animComponents) {
|
||||||
AnimatorSetBuilder animatorSetBuilder = new AnimatorSetBuilder();
|
StateAnimationConfig config = new StateAnimationConfig();
|
||||||
setupInterpolators(animatorSetBuilder);
|
setupInterpolators(config);
|
||||||
long accuracy = (long) (getShiftRange() * 2);
|
config.duration = (long) (getShiftRange() * 2);
|
||||||
mCurrentAnimation = mLauncher.getStateManager().createAnimationToNewWorkspace(mToState,
|
mCurrentAnimation = mLauncher.getStateManager()
|
||||||
animatorSetBuilder, accuracy, this::clearState, ANIM_ALL_COMPONENTS);
|
.createAnimationToNewWorkspace(mToState, config)
|
||||||
mCurrentAnimation.getAnimationPlayer().addUpdateListener(valueAnimator -> {
|
.setOnCancelRunnable(this::clearState);
|
||||||
updateFullscreenProgress((Float) valueAnimator.getAnimatedValue());
|
mCurrentAnimation.getAnimationPlayer().addUpdateListener(valueAnimator ->
|
||||||
});
|
updateFullscreenProgress((Float) valueAnimator.getAnimatedValue()));
|
||||||
return 1 / getShiftRange();
|
return 1 / getShiftRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupInterpolators(AnimatorSetBuilder animatorSetBuilder) {
|
private void setupInterpolators(StateAnimationConfig stateAnimationConfig) {
|
||||||
animatorSetBuilder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_2);
|
stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_2);
|
||||||
animatorSetBuilder.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_2);
|
stateAnimationConfig.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_2);
|
||||||
if (SysUINavigationMode.getMode(mLauncher) == Mode.NO_BUTTON) {
|
if (SysUINavigationMode.getMode(mLauncher) == Mode.NO_BUTTON) {
|
||||||
// Overview lives to the left of workspace, so translate down later than over
|
// Overview lives to the left of workspace, so translate down later than over
|
||||||
animatorSetBuilder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL_2);
|
stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL_2);
|
||||||
animatorSetBuilder.setInterpolator(ANIM_VERTICAL_PROGRESS, ACCEL_2);
|
stateAnimationConfig.setInterpolator(ANIM_VERTICAL_PROGRESS, ACCEL_2);
|
||||||
animatorSetBuilder.setInterpolator(ANIM_OVERVIEW_SCALE, ACCEL_2);
|
stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_SCALE, ACCEL_2);
|
||||||
animatorSetBuilder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, ACCEL_2);
|
stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, ACCEL_2);
|
||||||
animatorSetBuilder.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
|
stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
|
||||||
} else {
|
} else {
|
||||||
animatorSetBuilder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, LINEAR);
|
stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_TRANSLATE, LINEAR);
|
||||||
animatorSetBuilder.setInterpolator(ANIM_VERTICAL_PROGRESS, LINEAR);
|
stateAnimationConfig.setInterpolator(ANIM_VERTICAL_PROGRESS, LINEAR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -214,7 +214,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||||||
if (mCurrentAnimation != null) {
|
if (mCurrentAnimation != null) {
|
||||||
mCurrentAnimation.setOnCancelRunnable(null);
|
mCurrentAnimation.setOnCancelRunnable(null);
|
||||||
}
|
}
|
||||||
mCurrentAnimation = AnimatorPlaybackController.wrap(mPendingAnimation, maxDuration)
|
mCurrentAnimation = mPendingAnimation.createPlaybackController()
|
||||||
.setOnCancelRunnable(this::clearState);
|
.setOnCancelRunnable(this::clearState);
|
||||||
onUserControlledAnimationCreated(mCurrentAnimation);
|
onUserControlledAnimationCreated(mCurrentAnimation);
|
||||||
mCurrentAnimation.getTarget().addListener(this);
|
mCurrentAnimation.getTarget().addListener(this);
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ import com.android.systemui.shared.system.TransactionCompat;
|
|||||||
*
|
*
|
||||||
* @param <T> activity that contains the overview
|
* @param <T> activity that contains the overview
|
||||||
*/
|
*/
|
||||||
final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> implements
|
final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> extends
|
||||||
RemoteAnimationProvider {
|
RemoteAnimationProvider {
|
||||||
|
|
||||||
private static final long RECENTS_LAUNCH_DURATION = 250;
|
private static final long RECENTS_LAUNCH_DURATION = 250;
|
||||||
|
|||||||
+1
-1
@@ -213,7 +213,7 @@ public final class FallbackActivityInterface implements
|
|||||||
@Override
|
@Override
|
||||||
public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) {
|
public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) {
|
||||||
// TODO: Remove this once b/77875376 is fixed
|
// TODO: Remove this once b/77875376 is fixed
|
||||||
return target.sourceContainerBounds;
|
return target.screenSpaceBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+10
-1
@@ -33,6 +33,7 @@ import com.android.launcher3.appprediction.PredictionUiStateManager;
|
|||||||
import com.android.launcher3.logging.UserEventDispatcher;
|
import com.android.launcher3.logging.UserEventDispatcher;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
import com.android.quickstep.util.ActivityInitListener;
|
import com.android.quickstep.util.ActivityInitListener;
|
||||||
|
import com.android.quickstep.util.RemoteAnimationProvider;
|
||||||
import com.android.quickstep.views.RecentsView;
|
import com.android.quickstep.views.RecentsView;
|
||||||
import com.android.quickstep.views.TaskView;
|
import com.android.quickstep.views.TaskView;
|
||||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||||
@@ -187,7 +188,15 @@ public class OverviewCommandHelper {
|
|||||||
// Otherwise, start overview.
|
// Otherwise, start overview.
|
||||||
mListener = mActivityInterface.createActivityInitListener(this::onActivityReady);
|
mListener = mActivityInterface.createActivityInitListener(this::onActivityReady);
|
||||||
mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
|
mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
|
||||||
this::createWindowAnimation, mContext, MAIN_EXECUTOR.getHandler(),
|
new RemoteAnimationProvider() {
|
||||||
|
@Override
|
||||||
|
public AnimatorSet createWindowAnimation(
|
||||||
|
RemoteAnimationTargetCompat[] appTargets,
|
||||||
|
RemoteAnimationTargetCompat[] wallpaperTargets) {
|
||||||
|
return RecentsActivityCommand.this.createWindowAnimation(appTargets,
|
||||||
|
wallpaperTargets);
|
||||||
|
}
|
||||||
|
}, mContext, MAIN_EXECUTOR.getHandler(),
|
||||||
mAnimationProvider.getRecentsLaunchDuration());
|
mAnimationProvider.getRecentsLaunchDuration());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-4
@@ -50,6 +50,7 @@ import com.android.systemui.shared.system.WindowManagerWrapper;
|
|||||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||||
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
|
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
|
||||||
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
|
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
|
||||||
|
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
|
||||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
|
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
|
||||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
|
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ public class AppWindowAnimationHelper {
|
|||||||
|
|
||||||
private void updateSourceStack(RemoteAnimationTargetCompat target) {
|
private void updateSourceStack(RemoteAnimationTargetCompat target) {
|
||||||
mSourceInsets.set(target.contentInsets);
|
mSourceInsets.set(target.contentInsets);
|
||||||
mSourceStackBounds.set(target.sourceContainerBounds);
|
mSourceStackBounds.set(target.screenSpaceBounds);
|
||||||
|
|
||||||
// TODO: Should sourceContainerBounds already have this offset?
|
// TODO: Should sourceContainerBounds already have this offset?
|
||||||
mSourceStackBounds.offsetTo(target.position.x, target.position.y);
|
mSourceStackBounds.offsetTo(target.position.x, target.position.y);
|
||||||
@@ -199,9 +200,17 @@ public class AppWindowAnimationHelper {
|
|||||||
for (int i = 0; i < params.mTargetSet.unfilteredApps.length; i++) {
|
for (int i = 0; i < params.mTargetSet.unfilteredApps.length; i++) {
|
||||||
RemoteAnimationTargetCompat app = params.mTargetSet.unfilteredApps[i];
|
RemoteAnimationTargetCompat app = params.mTargetSet.unfilteredApps[i];
|
||||||
SurfaceParams.Builder builder = new SurfaceParams.Builder(app.leash);
|
SurfaceParams.Builder builder = new SurfaceParams.Builder(app.leash);
|
||||||
mTmpMatrix.setTranslate(app.position.x, app.position.y);
|
if (app.localBounds != null) {
|
||||||
|
mTmpMatrix.setTranslate(0, 0);
|
||||||
|
if (app.activityType == ACTIVITY_TYPE_HOME && app.mode == MODE_CLOSING) {
|
||||||
|
mTmpMatrix.setTranslate(app.localBounds.left, app.localBounds.top);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mTmpMatrix.setTranslate(app.position.x, app.position.y);
|
||||||
|
}
|
||||||
|
|
||||||
Rect crop = mTmpRect;
|
Rect crop = mTmpRect;
|
||||||
crop.set(app.sourceContainerBounds);
|
crop.set(app.screenSpaceBounds);
|
||||||
crop.offsetTo(0, 0);
|
crop.offsetTo(0, 0);
|
||||||
float alpha;
|
float alpha;
|
||||||
float cornerRadius = 0f;
|
float cornerRadius = 0f;
|
||||||
@@ -211,7 +220,11 @@ public class AppWindowAnimationHelper {
|
|||||||
alpha = mTaskAlphaCallback.getAlpha(app, params.mTargetAlpha);
|
alpha = mTaskAlphaCallback.getAlpha(app, params.mTargetAlpha);
|
||||||
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
|
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
|
||||||
mTmpMatrix.setRectToRect(mSourceRect, mCurrentRect, ScaleToFit.FILL);
|
mTmpMatrix.setRectToRect(mSourceRect, mCurrentRect, ScaleToFit.FILL);
|
||||||
mTmpMatrix.postTranslate(app.position.x, app.position.y);
|
if (app.localBounds != null) {
|
||||||
|
mTmpMatrix.postTranslate(app.localBounds.left, app.localBounds.top);
|
||||||
|
} else {
|
||||||
|
mTmpMatrix.postTranslate(app.position.x, app.position.y);
|
||||||
|
}
|
||||||
mCurrentClipRectF.roundOut(crop);
|
mCurrentClipRectF.roundOut(crop);
|
||||||
if (mSupportsRoundedCornersOnWindows) {
|
if (mSupportsRoundedCornersOnWindows) {
|
||||||
if (params.mCornerRadius > -1) {
|
if (params.mCornerRadius > -1) {
|
||||||
|
|||||||
+16
-20
@@ -18,9 +18,10 @@ package com.android.quickstep.util;
|
|||||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||||
import static com.android.launcher3.LauncherState.NORMAL;
|
import static com.android.launcher3.LauncherState.NORMAL;
|
||||||
import static com.android.launcher3.LauncherStateManager.ANIM_ALL_COMPONENTS;
|
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
|
||||||
import static com.android.launcher3.LauncherStateManager.SKIP_OVERVIEW;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
@@ -33,14 +34,13 @@ import com.android.launcher3.CellLayout;
|
|||||||
import com.android.launcher3.DeviceProfile;
|
import com.android.launcher3.DeviceProfile;
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.ShortcutAndWidgetContainer;
|
import com.android.launcher3.ShortcutAndWidgetContainer;
|
||||||
import com.android.launcher3.Workspace;
|
import com.android.launcher3.Workspace;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.anim.PropertySetter;
|
|
||||||
import com.android.launcher3.anim.SpringAnimationBuilder;
|
import com.android.launcher3.anim.SpringAnimationBuilder;
|
||||||
import com.android.launcher3.graphics.OverviewScrim;
|
import com.android.launcher3.graphics.OverviewScrim;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.launcher3.util.DynamicResource;
|
import com.android.launcher3.util.DynamicResource;
|
||||||
import com.android.quickstep.views.RecentsView;
|
import com.android.quickstep.views.RecentsView;
|
||||||
import com.android.systemui.plugins.ResourceProvider;
|
import com.android.systemui.plugins.ResourceProvider;
|
||||||
@@ -143,11 +143,11 @@ public class StaggeredWorkspaceAnim {
|
|||||||
* Setup workspace with 0 duration to prepare for our staggered animation.
|
* Setup workspace with 0 duration to prepare for our staggered animation.
|
||||||
*/
|
*/
|
||||||
private void prepareToAnimate(Launcher launcher) {
|
private void prepareToAnimate(Launcher launcher) {
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
StateAnimationConfig config = new StateAnimationConfig();
|
||||||
|
config.animFlags = ANIM_ALL_COMPONENTS | SKIP_OVERVIEW;
|
||||||
|
config.duration = 0;
|
||||||
// setRecentsAttachedToAppWindow() will animate recents out.
|
// setRecentsAttachedToAppWindow() will animate recents out.
|
||||||
launcher.getStateManager().createAtomicAnimation(
|
launcher.getStateManager().createAtomicAnimation(BACKGROUND_APP, NORMAL, config).start();
|
||||||
BACKGROUND_APP, NORMAL, builder, ANIM_ALL_COMPONENTS | SKIP_OVERVIEW, 0);
|
|
||||||
builder.build().start();
|
|
||||||
|
|
||||||
// Stop scrolling so that it doesn't interfere with the translation offscreen.
|
// Stop scrolling so that it doesn't interfere with the translation offscreen.
|
||||||
launcher.<RecentsView>getOverviewPanel().getScroller().forceFinished(true);
|
launcher.<RecentsView>getOverviewPanel().getScroller().forceFinished(true);
|
||||||
@@ -197,16 +197,12 @@ public class StaggeredWorkspaceAnim {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addScrimAnimationForState(Launcher launcher, LauncherState state, long duration) {
|
private void addScrimAnimationForState(Launcher launcher, LauncherState state, long duration) {
|
||||||
AnimatorSetBuilder scrimAnimBuilder = new AnimatorSetBuilder();
|
PendingAnimation builder = new PendingAnimation(duration, mAnimators);
|
||||||
AnimationConfig scrimAnimConfig = new AnimationConfig();
|
launcher.getWorkspace().getStateTransitionAnimation().setScrim(builder, state);
|
||||||
scrimAnimConfig.duration = duration;
|
builder.setFloat(
|
||||||
PropertySetter scrimPropertySetter = scrimAnimConfig.getPropertySetter(scrimAnimBuilder);
|
launcher.getDragLayer().getOverviewScrim(),
|
||||||
launcher.getWorkspace().getStateTransitionAnimation().setScrim(scrimPropertySetter, state);
|
OverviewScrim.SCRIM_PROGRESS,
|
||||||
mAnimators.play(scrimAnimBuilder.build());
|
state.getOverviewScrimAlpha(launcher),
|
||||||
Animator fadeOverviewScrim = ObjectAnimator.ofFloat(
|
ACCEL_DEACCEL);
|
||||||
launcher.getDragLayer().getOverviewScrim(), OverviewScrim.SCRIM_PROGRESS,
|
|
||||||
state.getOverviewScrimAlpha(launcher));
|
|
||||||
fadeOverviewScrim.setDuration(duration);
|
|
||||||
mAnimators.play(fadeOverviewScrim);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1195,7 +1195,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||||||
if (mPendingAnimation != null) {
|
if (mPendingAnimation != null) {
|
||||||
mPendingAnimation.finish(false, Touch.SWIPE);
|
mPendingAnimation.finish(false, Touch.SWIPE);
|
||||||
}
|
}
|
||||||
PendingAnimation anim = new PendingAnimation();
|
PendingAnimation anim = new PendingAnimation(duration);
|
||||||
|
|
||||||
int count = getPageCount();
|
int count = getPageCount();
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
@@ -1311,7 +1311,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||||||
if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
|
if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
|
||||||
throw new IllegalStateException("Another pending animation is still running");
|
throw new IllegalStateException("Another pending animation is still running");
|
||||||
}
|
}
|
||||||
PendingAnimation anim = new PendingAnimation();
|
PendingAnimation anim = new PendingAnimation(duration);
|
||||||
|
|
||||||
int count = getTaskViewCount();
|
int count = getTaskViewCount();
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
@@ -1345,8 +1345,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void runDismissAnimation(PendingAnimation pendingAnim) {
|
private void runDismissAnimation(PendingAnimation pendingAnim) {
|
||||||
AnimatorPlaybackController controller =
|
AnimatorPlaybackController controller = pendingAnim.createPlaybackController();
|
||||||
AnimatorPlaybackController.wrap(pendingAnim, DISMISS_TASK_DURATION);
|
|
||||||
controller.dispatchOnStart();
|
controller.dispatchOnStart();
|
||||||
controller.setEndAction(() -> pendingAnim.finish(true, Touch.SWIPE));
|
controller.setEndAction(() -> pendingAnim.finish(true, Touch.SWIPE));
|
||||||
controller.getAnimationPlayer().setInterpolator(FAST_OUT_SLOW_IN);
|
controller.getAnimationPlayer().setInterpolator(FAST_OUT_SLOW_IN);
|
||||||
@@ -1671,7 +1670,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||||||
|
|
||||||
int count = getTaskViewCount();
|
int count = getTaskViewCount();
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
return new PendingAnimation();
|
return new PendingAnimation(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
int targetSysUiFlags = tv.getThumbnail().getSysUiStatusNavFlags();
|
int targetSysUiFlags = tv.getThumbnail().getSysUiStatusNavFlags();
|
||||||
@@ -1710,10 +1709,9 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||||||
anim.play(backgroundBlur);
|
anim.play(backgroundBlur);
|
||||||
}
|
}
|
||||||
anim.play(progressAnim);
|
anim.play(progressAnim);
|
||||||
anim.setDuration(duration)
|
anim.setDuration(duration).setInterpolator(interpolator);
|
||||||
.setInterpolator(interpolator);
|
|
||||||
|
|
||||||
mPendingAnimation = new PendingAnimation();
|
mPendingAnimation = new PendingAnimation(duration);
|
||||||
mPendingAnimation.add(anim);
|
mPendingAnimation.add(anim);
|
||||||
mPendingAnimation.addEndListener((endState) -> {
|
mPendingAnimation.addEndListener((endState) -> {
|
||||||
if (endState.isSuccess) {
|
if (endState.isSuccess) {
|
||||||
|
|||||||
@@ -285,8 +285,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
|||||||
public AnimatorPlaybackController createLaunchAnimationForRunningTask() {
|
public AnimatorPlaybackController createLaunchAnimationForRunningTask() {
|
||||||
final PendingAnimation pendingAnimation = getRecentsView().createTaskLaunchAnimation(
|
final PendingAnimation pendingAnimation = getRecentsView().createTaskLaunchAnimation(
|
||||||
this, RECENTS_LAUNCH_DURATION, TOUCH_RESPONSE_INTERPOLATOR);
|
this, RECENTS_LAUNCH_DURATION, TOUCH_RESPONSE_INTERPOLATOR);
|
||||||
AnimatorPlaybackController currentAnimation =
|
AnimatorPlaybackController currentAnimation = pendingAnimation.createPlaybackController();
|
||||||
AnimatorPlaybackController.wrap(pendingAnimation, RECENTS_LAUNCH_DURATION);
|
|
||||||
currentAnimation.setEndAction(() -> {
|
currentAnimation.setEndAction(() -> {
|
||||||
pendingAnimation.finish(true, Touch.SWIPE);
|
pendingAnimation.finish(true, Touch.SWIPE);
|
||||||
launchTask(false);
|
launchTask(false);
|
||||||
|
|||||||
@@ -52,10 +52,12 @@ import com.android.quickstep.SysUINavigationMode;
|
|||||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||||
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
|
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
|
||||||
import com.android.quickstep.SystemUiProxy;
|
import com.android.quickstep.SystemUiProxy;
|
||||||
|
import com.android.quickstep.util.RemoteAnimationProvider;
|
||||||
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
|
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
|
||||||
import com.android.quickstep.util.ShelfPeekAnim;
|
import com.android.quickstep.util.ShelfPeekAnim;
|
||||||
import com.android.quickstep.views.RecentsView;
|
import com.android.quickstep.views.RecentsView;
|
||||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||||
|
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||||
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@@ -262,17 +264,21 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
|||||||
public void useFadeOutAnimationForLauncherStart(CancellationSignal signal) {
|
public void useFadeOutAnimationForLauncherStart(CancellationSignal signal) {
|
||||||
QuickstepAppTransitionManagerImpl appTransitionManager =
|
QuickstepAppTransitionManagerImpl appTransitionManager =
|
||||||
(QuickstepAppTransitionManagerImpl) getAppTransitionManager();
|
(QuickstepAppTransitionManagerImpl) getAppTransitionManager();
|
||||||
appTransitionManager.setRemoteAnimationProvider((appTargets, wallpaperTargets) -> {
|
appTransitionManager.setRemoteAnimationProvider(new RemoteAnimationProvider() {
|
||||||
|
@Override
|
||||||
|
public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
|
||||||
|
RemoteAnimationTargetCompat[] wallpaperTargets) {
|
||||||
|
|
||||||
// On the first call clear the reference.
|
// On the first call clear the reference.
|
||||||
signal.cancel();
|
signal.cancel();
|
||||||
|
|
||||||
ValueAnimator fadeAnimation = ValueAnimator.ofFloat(1, 0);
|
ValueAnimator fadeAnimation = ValueAnimator.ofFloat(1, 0);
|
||||||
fadeAnimation.addUpdateListener(new RemoteFadeOutAnimationListener(appTargets,
|
fadeAnimation.addUpdateListener(new RemoteFadeOutAnimationListener(appTargets,
|
||||||
wallpaperTargets));
|
wallpaperTargets));
|
||||||
AnimatorSet anim = new AnimatorSet();
|
AnimatorSet anim = new AnimatorSet();
|
||||||
anim.play(fadeAnimation);
|
anim.play(fadeAnimation);
|
||||||
return anim;
|
return anim;
|
||||||
|
}
|
||||||
}, signal);
|
}, signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
|||||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.P)
|
@TargetApi(Build.VERSION_CODES.P)
|
||||||
public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat {
|
public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat,
|
||||||
|
WrappedAnimationRunnerImpl {
|
||||||
|
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final boolean mStartAtFrontOfQueue;
|
private final boolean mStartAtFrontOfQueue;
|
||||||
@@ -49,6 +50,10 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
|
|||||||
mStartAtFrontOfQueue = startAtFrontOfQueue;
|
mStartAtFrontOfQueue = startAtFrontOfQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Handler getHandler() {
|
||||||
|
return mHandler;
|
||||||
|
}
|
||||||
|
|
||||||
// Called only in R+ platform
|
// Called only in R+ platform
|
||||||
@BinderThread
|
@BinderThread
|
||||||
public void onAnimationStart(RemoteAnimationTargetCompat[] appTargets,
|
public void onAnimationStart(RemoteAnimationTargetCompat[] appTargets,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.launcher3;
|
package com.android.launcher3;
|
||||||
|
|
||||||
|
import android.animation.AnimatorSet;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -25,6 +26,7 @@ import android.os.Handler;
|
|||||||
import com.android.launcher3.util.ActivityTracker;
|
import com.android.launcher3.util.ActivityTracker;
|
||||||
import com.android.quickstep.util.ActivityInitListener;
|
import com.android.quickstep.util.ActivityInitListener;
|
||||||
import com.android.quickstep.util.RemoteAnimationProvider;
|
import com.android.quickstep.util.RemoteAnimationProvider;
|
||||||
|
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||||
|
|
||||||
import java.util.function.BiPredicate;
|
import java.util.function.BiPredicate;
|
||||||
|
|
||||||
@@ -51,17 +53,21 @@ public class LauncherInitListener extends ActivityInitListener<Launcher> {
|
|||||||
// Set a one-time animation provider. After the first call, this will get cleared.
|
// Set a one-time animation provider. After the first call, this will get cleared.
|
||||||
// TODO: Probably also check the intended target id.
|
// TODO: Probably also check the intended target id.
|
||||||
CancellationSignal cancellationSignal = new CancellationSignal();
|
CancellationSignal cancellationSignal = new CancellationSignal();
|
||||||
appTransitionManager.setRemoteAnimationProvider((appTargets, wallpaperTargets) -> {
|
appTransitionManager.setRemoteAnimationProvider(new RemoteAnimationProvider() {
|
||||||
|
@Override
|
||||||
|
public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
|
||||||
|
RemoteAnimationTargetCompat[] wallpaperTargets) {
|
||||||
|
|
||||||
// On the first call clear the reference.
|
// On the first call clear the reference.
|
||||||
cancellationSignal.cancel();
|
cancellationSignal.cancel();
|
||||||
RemoteAnimationProvider provider = mRemoteAnimationProvider;
|
RemoteAnimationProvider provider = mRemoteAnimationProvider;
|
||||||
mRemoteAnimationProvider = null;
|
mRemoteAnimationProvider = null;
|
||||||
|
|
||||||
if (provider != null && launcher.getStateManager().getState().overviewUi) {
|
if (provider != null && launcher.getStateManager().getState().overviewUi) {
|
||||||
return provider.createWindowAnimation(appTargets, wallpaperTargets);
|
return provider.createWindowAnimation(appTargets, wallpaperTargets);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}, cancellationSignal);
|
}, cancellationSignal);
|
||||||
}
|
}
|
||||||
launcher.deferOverlayCallbacksUntilNextResumeOrStop();
|
launcher.deferOverlayCallbacksUntilNextResumeOrStop();
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import android.content.Context;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
@@ -86,8 +87,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
|||||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
|
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
|
||||||
import com.android.systemui.shared.system.WindowManagerWrapper;
|
import com.android.systemui.shared.system.WindowManagerWrapper;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link LauncherAppTransitionManager} with Quickstep-specific app transitions for launching from
|
* {@link LauncherAppTransitionManager} with Quickstep-specific app transitions for launching from
|
||||||
* home and/or all-apps. Not used for 3p launchers.
|
* home and/or all-apps. Not used for 3p launchers.
|
||||||
@@ -299,8 +298,12 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||||||
if (mLauncher.isInMultiWindowMode()) {
|
if (mLauncher.isInMultiWindowMode()) {
|
||||||
for (RemoteAnimationTargetCompat target : appTargets) {
|
for (RemoteAnimationTargetCompat target : appTargets) {
|
||||||
if (target.mode == MODE_OPENING) {
|
if (target.mode == MODE_OPENING) {
|
||||||
bounds.set(target.sourceContainerBounds);
|
bounds.set(target.screenSpaceBounds);
|
||||||
bounds.offsetTo(target.position.x, target.position.y);
|
if (target.localBounds != null) {
|
||||||
|
bounds.set(target.localBounds);
|
||||||
|
} else {
|
||||||
|
bounds.offsetTo(target.position.x, target.position.y);
|
||||||
|
}
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -460,6 +463,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||||||
RectF targetBounds = new RectF(windowTargetBounds);
|
RectF targetBounds = new RectF(windowTargetBounds);
|
||||||
RectF currentBounds = new RectF();
|
RectF currentBounds = new RectF();
|
||||||
RectF temp = new RectF();
|
RectF temp = new RectF();
|
||||||
|
Point tmpPos = new Point();
|
||||||
|
|
||||||
AnimatorSet animatorSet = new AnimatorSet();
|
AnimatorSet animatorSet = new AnimatorSet();
|
||||||
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
|
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
|
||||||
@@ -547,6 +551,13 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||||||
for (int i = appTargets.length - 1; i >= 0; i--) {
|
for (int i = appTargets.length - 1; i >= 0; i--) {
|
||||||
RemoteAnimationTargetCompat target = appTargets[i];
|
RemoteAnimationTargetCompat target = appTargets[i];
|
||||||
SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
|
SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
|
||||||
|
|
||||||
|
tmpPos.set(target.position.x, target.position.y);
|
||||||
|
if (target.localBounds != null) {
|
||||||
|
final Rect localBounds = target.localBounds;
|
||||||
|
tmpPos.set(target.localBounds.left, target.localBounds.top);
|
||||||
|
}
|
||||||
|
|
||||||
if (target.mode == MODE_OPENING) {
|
if (target.mode == MODE_OPENING) {
|
||||||
matrix.setScale(scale, scale);
|
matrix.setScale(scale, scale);
|
||||||
matrix.postTranslate(transX0, transY0);
|
matrix.postTranslate(transX0, transY0);
|
||||||
@@ -563,9 +574,9 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||||||
.withAlpha(1f - mIconAlpha.value)
|
.withAlpha(1f - mIconAlpha.value)
|
||||||
.withCornerRadius(mWindowRadius.value);
|
.withCornerRadius(mWindowRadius.value);
|
||||||
} else {
|
} else {
|
||||||
matrix.setTranslate(target.position.x, target.position.y);
|
matrix.setTranslate(tmpPos.x, tmpPos.y);
|
||||||
builder.withMatrix(matrix)
|
builder.withMatrix(matrix)
|
||||||
.withWindowCrop(target.sourceContainerBounds)
|
.withWindowCrop(target.screenSpaceBounds)
|
||||||
.withAlpha(1f);
|
.withAlpha(1f);
|
||||||
}
|
}
|
||||||
builder.withLayer(RemoteAnimationProvider.getLayer(target, MODE_OPENING));
|
builder.withLayer(RemoteAnimationProvider.getLayer(target, MODE_OPENING));
|
||||||
@@ -662,7 +673,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||||||
RemoteAnimationTargetCompat target = appTargets[i];
|
RemoteAnimationTargetCompat target = appTargets[i];
|
||||||
params[i] = new SurfaceParams.Builder(target.leash)
|
params[i] = new SurfaceParams.Builder(target.leash)
|
||||||
.withAlpha(1f)
|
.withAlpha(1f)
|
||||||
.withWindowCrop(target.sourceContainerBounds)
|
.withWindowCrop(target.screenSpaceBounds)
|
||||||
.withLayer(RemoteAnimationProvider.getLayer(target, MODE_OPENING))
|
.withLayer(RemoteAnimationProvider.getLayer(target, MODE_OPENING))
|
||||||
.withCornerRadius(cornerRadius)
|
.withCornerRadius(cornerRadius)
|
||||||
.build();
|
.build();
|
||||||
@@ -681,6 +692,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||||||
SyncRtSurfaceTransactionApplierCompat surfaceApplier =
|
SyncRtSurfaceTransactionApplierCompat surfaceApplier =
|
||||||
new SyncRtSurfaceTransactionApplierCompat(mDragLayer);
|
new SyncRtSurfaceTransactionApplierCompat(mDragLayer);
|
||||||
Matrix matrix = new Matrix();
|
Matrix matrix = new Matrix();
|
||||||
|
Point tmpPos = new Point();
|
||||||
ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
|
ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
|
||||||
int duration = CLOSING_TRANSITION_DURATION_MS;
|
int duration = CLOSING_TRANSITION_DURATION_MS;
|
||||||
float windowCornerRadius = mDeviceProfile.isMultiWindowMode
|
float windowCornerRadius = mDeviceProfile.isMultiWindowMode
|
||||||
@@ -697,22 +709,28 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||||||
for (int i = appTargets.length - 1; i >= 0; i--) {
|
for (int i = appTargets.length - 1; i >= 0; i--) {
|
||||||
RemoteAnimationTargetCompat target = appTargets[i];
|
RemoteAnimationTargetCompat target = appTargets[i];
|
||||||
SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
|
SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
|
||||||
|
|
||||||
|
tmpPos.set(target.position.x, target.position.y);
|
||||||
|
if (target.localBounds != null) {
|
||||||
|
tmpPos.set(target.localBounds.left, target.localBounds.top);
|
||||||
|
}
|
||||||
|
|
||||||
if (target.mode == MODE_CLOSING) {
|
if (target.mode == MODE_CLOSING) {
|
||||||
matrix.setScale(mScale.value, mScale.value,
|
matrix.setScale(mScale.value, mScale.value,
|
||||||
target.sourceContainerBounds.centerX(),
|
target.screenSpaceBounds.centerX(),
|
||||||
target.sourceContainerBounds.centerY());
|
target.screenSpaceBounds.centerY());
|
||||||
matrix.postTranslate(0, mDy.value);
|
matrix.postTranslate(0, mDy.value);
|
||||||
matrix.postTranslate(target.position.x, target.position.y);
|
matrix.postTranslate(tmpPos.x, tmpPos.y);
|
||||||
builder.withMatrix(matrix)
|
builder.withMatrix(matrix)
|
||||||
.withAlpha(mAlpha.value)
|
.withAlpha(mAlpha.value)
|
||||||
.withCornerRadius(windowCornerRadius);
|
.withCornerRadius(windowCornerRadius);
|
||||||
} else {
|
} else {
|
||||||
matrix.setTranslate(target.position.x, target.position.y);
|
matrix.setTranslate(tmpPos.x, tmpPos.y);
|
||||||
builder.withMatrix(matrix)
|
builder.withMatrix(matrix)
|
||||||
.withAlpha(1f);
|
.withAlpha(1f);
|
||||||
}
|
}
|
||||||
params[i] = builder
|
params[i] = builder
|
||||||
.withWindowCrop(target.sourceContainerBounds)
|
.withWindowCrop(target.screenSpaceBounds)
|
||||||
.withLayer(RemoteAnimationProvider.getLayer(target, MODE_CLOSING))
|
.withLayer(RemoteAnimationProvider.getLayer(target, MODE_CLOSING))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
@@ -784,52 +802,6 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
|||||||
== PackageManager.PERMISSION_GRANTED;
|
== PackageManager.PERMISSION_GRANTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used with WrappedLauncherAnimationRunner as an interface for the runner to call back to the
|
|
||||||
* implementation.
|
|
||||||
*/
|
|
||||||
protected interface WrappedAnimationRunnerImpl {
|
|
||||||
Handler getHandler();
|
|
||||||
void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets,
|
|
||||||
RemoteAnimationTargetCompat[] wallpaperTargets,
|
|
||||||
LauncherAnimationRunner.AnimationResult result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is needed to wrap any animation runner that is a part of the
|
|
||||||
* RemoteAnimationDefinition:
|
|
||||||
* - Launcher creates a new instance of the LauncherAppTransitionManagerImpl whenever it is
|
|
||||||
* created, which in turn registers a new definition
|
|
||||||
* - When the definition is registered, window manager retains a strong binder reference to the
|
|
||||||
* runner passed in
|
|
||||||
* - If the Launcher activity is recreated, the new definition registered will replace the old
|
|
||||||
* reference in the system's activity record, but until the system server is GC'd, the binder
|
|
||||||
* reference will still exist, which references the runner in the Launcher process, which
|
|
||||||
* references the (old) Launcher activity through this class
|
|
||||||
*
|
|
||||||
* Instead we make the runner provided to the definition static only holding a weak reference to
|
|
||||||
* the runner implementation. When this animation manager is destroyed, we remove the Launcher
|
|
||||||
* reference to the runner, leaving only the weak ref from the runner.
|
|
||||||
*/
|
|
||||||
protected static class WrappedLauncherAnimationRunner<R extends WrappedAnimationRunnerImpl>
|
|
||||||
extends LauncherAnimationRunner {
|
|
||||||
private WeakReference<R> mImpl;
|
|
||||||
|
|
||||||
public WrappedLauncherAnimationRunner(R animationRunnerImpl, boolean startAtFrontOfQueue) {
|
|
||||||
super(animationRunnerImpl.getHandler(), startAtFrontOfQueue);
|
|
||||||
mImpl = new WeakReference<>(animationRunnerImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets,
|
|
||||||
RemoteAnimationTargetCompat[] wallpaperTargets, AnimationResult result) {
|
|
||||||
R animationRunnerImpl = mImpl.get();
|
|
||||||
if (animationRunnerImpl != null) {
|
|
||||||
animationRunnerImpl.onCreateAnimation(appTargets, wallpaperTargets, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote animation runner for animation from the app to Launcher, including recents.
|
* Remote animation runner for animation from the app to Launcher, including recents.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.os.Handler;
|
||||||
|
|
||||||
|
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used with WrappedLauncherAnimationRunner as an interface for the runner to call back to the
|
||||||
|
* implementation.
|
||||||
|
*/
|
||||||
|
public interface WrappedAnimationRunnerImpl {
|
||||||
|
Handler getHandler();
|
||||||
|
void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets,
|
||||||
|
RemoteAnimationTargetCompat[] wallpaperTargets,
|
||||||
|
LauncherAnimationRunner.AnimationResult result);
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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 com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is needed to wrap any animation runner that is a part of the
|
||||||
|
* RemoteAnimationDefinition:
|
||||||
|
* - Launcher creates a new instance of the LauncherAppTransitionManagerImpl whenever it is
|
||||||
|
* created, which in turn registers a new definition
|
||||||
|
* - When the definition is registered, window manager retains a strong binder reference to the
|
||||||
|
* runner passed in
|
||||||
|
* - If the Launcher activity is recreated, the new definition registered will replace the old
|
||||||
|
* reference in the system's activity record, but until the system server is GC'd, the binder
|
||||||
|
* reference will still exist, which references the runner in the Launcher process, which
|
||||||
|
* references the (old) Launcher activity through this class
|
||||||
|
*
|
||||||
|
* Instead we make the runner provided to the definition static only holding a weak reference to
|
||||||
|
* the runner implementation. When this animation manager is destroyed, we remove the Launcher
|
||||||
|
* reference to the runner, leaving only the weak ref from the runner.
|
||||||
|
*/
|
||||||
|
public class WrappedLauncherAnimationRunner<R extends WrappedAnimationRunnerImpl>
|
||||||
|
extends LauncherAnimationRunner {
|
||||||
|
private WeakReference<R> mImpl;
|
||||||
|
|
||||||
|
public WrappedLauncherAnimationRunner(R animationRunnerImpl, boolean startAtFrontOfQueue) {
|
||||||
|
super(animationRunnerImpl.getHandler(), startAtFrontOfQueue);
|
||||||
|
mImpl = new WeakReference<>(animationRunnerImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets,
|
||||||
|
RemoteAnimationTargetCompat[] wallpaperTargets, AnimationResult result) {
|
||||||
|
R animationRunnerImpl = mImpl.get();
|
||||||
|
if (animationRunnerImpl != null) {
|
||||||
|
animationRunnerImpl.onCreateAnimation(appTargets, wallpaperTargets, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,19 +16,23 @@
|
|||||||
|
|
||||||
package com.android.launcher3.uioverrides;
|
package com.android.launcher3.uioverrides;
|
||||||
|
|
||||||
import android.animation.ValueAnimator;
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||||
|
import static com.android.quickstep.AnimatedFloat.VALUE;
|
||||||
|
|
||||||
import com.android.launcher3.BaseQuickstepLauncher;
|
import com.android.launcher3.BaseQuickstepLauncher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager;
|
import com.android.launcher3.LauncherStateManager;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.launcher3.util.UiThreadHelper;
|
import com.android.launcher3.util.UiThreadHelper;
|
||||||
|
import com.android.quickstep.AnimatedFloat;
|
||||||
import com.android.quickstep.SysUINavigationMode;
|
import com.android.quickstep.SysUINavigationMode;
|
||||||
import com.android.quickstep.SystemUiProxy;
|
import com.android.quickstep.SystemUiProxy;
|
||||||
|
|
||||||
public class BackButtonAlphaHandler implements LauncherStateManager.StateHandler {
|
public class BackButtonAlphaHandler implements LauncherStateManager.StateHandler {
|
||||||
|
|
||||||
private final BaseQuickstepLauncher mLauncher;
|
private final BaseQuickstepLauncher mLauncher;
|
||||||
|
private final AnimatedFloat mBackAlpha = new AnimatedFloat(this::updateBackAlpha);
|
||||||
|
|
||||||
public BackButtonAlphaHandler(BaseQuickstepLauncher launcher) {
|
public BackButtonAlphaHandler(BaseQuickstepLauncher launcher) {
|
||||||
mLauncher = launcher;
|
mLauncher = launcher;
|
||||||
@@ -38,8 +42,8 @@ public class BackButtonAlphaHandler implements LauncherStateManager.StateHandler
|
|||||||
public void setState(LauncherState state) { }
|
public void setState(LauncherState state) { }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStateWithAnimation(LauncherState toState,
|
public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
|
||||||
AnimatorSetBuilder builder, LauncherStateManager.AnimationConfig config) {
|
PendingAnimation animation) {
|
||||||
if (config.onlyPlayAtomicComponent()) {
|
if (config.onlyPlayAtomicComponent()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -51,17 +55,12 @@ public class BackButtonAlphaHandler implements LauncherStateManager.StateHandler
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float fromAlpha = SystemUiProxy.INSTANCE.get(mLauncher).getLastBackButtonAlpha();
|
mBackAlpha.value = SystemUiProxy.INSTANCE.get(mLauncher).getLastBackButtonAlpha();
|
||||||
float toAlpha = toState.hideBackButton ? 0 : 1;
|
animation.setFloat(mBackAlpha, VALUE, toState.hideBackButton ? 0 : 1, LINEAR);
|
||||||
if (Float.compare(fromAlpha, toAlpha) != 0) {
|
}
|
||||||
ValueAnimator anim = ValueAnimator.ofFloat(fromAlpha, toAlpha);
|
|
||||||
anim.setDuration(config.duration);
|
private void updateBackAlpha() {
|
||||||
anim.addUpdateListener(valueAnimator -> {
|
UiThreadHelper.setBackButtonAlphaAsync(mLauncher,
|
||||||
final float alpha = (float) valueAnimator.getAnimatedValue();
|
BaseQuickstepLauncher.SET_BACK_BUTTON_ALPHA, mBackAlpha.value, false /* animate */);
|
||||||
UiThreadHelper.setBackButtonAlphaAsync(mLauncher,
|
|
||||||
BaseQuickstepLauncher.SET_BACK_BUTTON_ALPHA, alpha, false /* animate */);
|
|
||||||
});
|
|
||||||
builder.play(anim);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ import com.android.launcher3.LauncherState;
|
|||||||
import com.android.launcher3.LauncherStateManager;
|
import com.android.launcher3.LauncherStateManager;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.anim.PropertySetter;
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||||
import com.android.systemui.shared.system.SurfaceControlCompat;
|
import com.android.systemui.shared.system.SurfaceControlCompat;
|
||||||
import com.android.systemui.shared.system.TransactionCompat;
|
import com.android.systemui.shared.system.TransactionCompat;
|
||||||
@@ -133,16 +133,15 @@ public class BackgroundBlurController implements LauncherStateManager.StateHandl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStateWithAnimation(LauncherState toState, AnimatorSetBuilder builder,
|
public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
|
||||||
LauncherStateManager.AnimationConfig config) {
|
PendingAnimation animation) {
|
||||||
if (mSurface == null || config.onlyPlayAtomicComponent()) {
|
if (mSurface == null || config.onlyPlayAtomicComponent()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int toBackgroundBlurRadius = toState.getBackgroundBlurRadius(mLauncher);
|
int toBackgroundBlurRadius = toState.getBackgroundBlurRadius(mLauncher);
|
||||||
if (mBackgroundBlurRadius != toBackgroundBlurRadius) {
|
if (mBackgroundBlurRadius != toBackgroundBlurRadius) {
|
||||||
PropertySetter propertySetter = config.getPropertySetter(builder);
|
animation.setInt(this, BACKGROUND_BLUR, toBackgroundBlurRadius, LINEAR);
|
||||||
propertySetter.setInt(this, BACKGROUND_BLUR, toBackgroundBlurRadius, LINEAR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+21
-23
@@ -20,17 +20,17 @@ import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
|||||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
|
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
|
||||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||||
import static com.android.launcher3.LauncherStateManager.PLAY_ATOMIC_OVERVIEW_PEEK;
|
|
||||||
import static com.android.launcher3.LauncherStateManager.PLAY_ATOMIC_OVERVIEW_SCALE;
|
|
||||||
import static com.android.launcher3.LauncherStateManager.SKIP_OVERVIEW;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCRIM_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_Y;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
|
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
|
||||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||||
import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
|
import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||||
|
|
||||||
import android.util.FloatProperty;
|
import android.util.FloatProperty;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -41,11 +41,10 @@ import androidx.annotation.NonNull;
|
|||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
|
||||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.anim.PropertySetter;
|
|
||||||
import com.android.launcher3.graphics.OverviewScrim;
|
import com.android.launcher3.graphics.OverviewScrim;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State handler for recents view. Manages UI changes and animations for recents view based off the
|
* State handler for recents view. Manages UI changes and animations for recents view based off the
|
||||||
@@ -86,8 +85,8 @@ public abstract class BaseRecentsViewStateController<T extends View>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void setStateWithAnimation(@NonNull final LauncherState toState,
|
public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
|
||||||
@NonNull AnimatorSetBuilder builder, @NonNull AnimationConfig config) {
|
PendingAnimation builder) {
|
||||||
if (!config.hasAnimationFlag(PLAY_ATOMIC_OVERVIEW_PEEK | PLAY_ATOMIC_OVERVIEW_SCALE)) {
|
if (!config.hasAnimationFlag(PLAY_ATOMIC_OVERVIEW_PEEK | PLAY_ATOMIC_OVERVIEW_SCALE)) {
|
||||||
// The entire recents animation is played atomically.
|
// The entire recents animation is played atomically.
|
||||||
return;
|
return;
|
||||||
@@ -95,25 +94,24 @@ public abstract class BaseRecentsViewStateController<T extends View>
|
|||||||
if (config.hasAnimationFlag(SKIP_OVERVIEW)) {
|
if (config.hasAnimationFlag(SKIP_OVERVIEW)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setStateWithAnimationInternal(toState, builder, config);
|
setStateWithAnimationInternal(toState, config, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Core logic for animating the recents view UI.
|
* Core logic for animating the recents view UI.
|
||||||
*
|
*
|
||||||
* @param toState state to animate to
|
* @param toState state to animate to
|
||||||
* @param builder animator set builder
|
|
||||||
* @param config current animation config
|
* @param config current animation config
|
||||||
|
* @param setter animator set builder
|
||||||
*/
|
*/
|
||||||
void setStateWithAnimationInternal(@NonNull final LauncherState toState,
|
void setStateWithAnimationInternal(@NonNull final LauncherState toState,
|
||||||
@NonNull AnimatorSetBuilder builder, @NonNull AnimationConfig config) {
|
@NonNull StateAnimationConfig config, @NonNull PendingAnimation setter) {
|
||||||
PropertySetter setter = config.getPropertySetter(builder);
|
|
||||||
ScaleAndTranslation scaleAndTranslation = toState.getOverviewScaleAndTranslation(mLauncher);
|
ScaleAndTranslation scaleAndTranslation = toState.getOverviewScaleAndTranslation(mLauncher);
|
||||||
Interpolator scaleInterpolator = builder.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR);
|
Interpolator scaleInterpolator = config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR);
|
||||||
setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleAndTranslation.scale, scaleInterpolator);
|
setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleAndTranslation.scale, scaleInterpolator);
|
||||||
Interpolator translateXInterpolator = builder.getInterpolator(
|
Interpolator translateXInterpolator = config.getInterpolator(
|
||||||
ANIM_OVERVIEW_TRANSLATE_X, LINEAR);
|
ANIM_OVERVIEW_TRANSLATE_X, LINEAR);
|
||||||
Interpolator translateYInterpolator = builder.getInterpolator(
|
Interpolator translateYInterpolator = config.getInterpolator(
|
||||||
ANIM_OVERVIEW_TRANSLATE_Y, LINEAR);
|
ANIM_OVERVIEW_TRANSLATE_Y, LINEAR);
|
||||||
float translationX = scaleAndTranslation.translationX;
|
float translationX = scaleAndTranslation.translationX;
|
||||||
if (mRecentsView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
|
if (mRecentsView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
|
||||||
@@ -123,14 +121,14 @@ public abstract class BaseRecentsViewStateController<T extends View>
|
|||||||
setter.setFloat(mRecentsView, VIEW_TRANSLATE_Y, scaleAndTranslation.translationY,
|
setter.setFloat(mRecentsView, VIEW_TRANSLATE_Y, scaleAndTranslation.translationY,
|
||||||
translateYInterpolator);
|
translateYInterpolator);
|
||||||
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
|
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
|
||||||
builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
|
config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
|
||||||
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
|
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
|
||||||
setter.setFloat(scrim, SCRIM_PROGRESS, toState.getOverviewScrimAlpha(mLauncher),
|
setter.setFloat(scrim, SCRIM_PROGRESS, toState.getOverviewScrimAlpha(mLauncher),
|
||||||
builder.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
|
config.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
|
||||||
if (mActionsView != null) {
|
if (mActionsView != null) {
|
||||||
setter.setFloat(mActionsView, VIEW_TRANSLATE_X, translationX, translateXInterpolator);
|
setter.setFloat(mActionsView, VIEW_TRANSLATE_X, translationX, translateXInterpolator);
|
||||||
setter.setFloat(mActionsView, VIEW_ALPHA, toState.overviewUi ? 1 : 0,
|
setter.setFloat(mActionsView, VIEW_ALPHA, toState.overviewUi ? 1 : 0,
|
||||||
builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
|
config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.uioverrides;
|
||||||
|
|
||||||
|
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Size;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.android.launcher3.InvariantDeviceProfile;
|
||||||
|
import com.android.launcher3.graphics.LauncherPreviewRenderer;
|
||||||
|
import com.android.systemui.shared.system.SurfaceViewRequestReceiver;
|
||||||
|
|
||||||
|
/** Render preview using surface view. */
|
||||||
|
public class PreviewSurfaceRenderer {
|
||||||
|
|
||||||
|
/** Handle a received surface view request. */
|
||||||
|
public static void render(Context context, Bundle bundle) {
|
||||||
|
final String gridName = bundle.getString("name");
|
||||||
|
bundle.remove("name");
|
||||||
|
final InvariantDeviceProfile idp = new InvariantDeviceProfile(context, gridName);
|
||||||
|
|
||||||
|
MAIN_EXECUTOR.execute(() -> {
|
||||||
|
View view = new LauncherPreviewRenderer(context, idp).getRenderedView();
|
||||||
|
new SurfaceViewRequestReceiver().onReceive(context, bundle, view,
|
||||||
|
new Size(view.getMeasuredWidth(), view.getMeasuredHeight()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -9,7 +9,7 @@ import android.view.MotionEvent;
|
|||||||
import com.android.launcher3.AbstractFloatingView;
|
import com.android.launcher3.AbstractFloatingView;
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationFlags;
|
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
|
||||||
import com.android.launcher3.touch.AbstractStateChangeTouchController;
|
import com.android.launcher3.touch.AbstractStateChangeTouchController;
|
||||||
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
|
|||||||
+34
-32
@@ -19,13 +19,13 @@ import static com.android.launcher3.AbstractFloatingView.TYPE_ACCESSIBLE;
|
|||||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||||
import static com.android.launcher3.LauncherState.NORMAL;
|
import static com.android.launcher3.LauncherState.NORMAL;
|
||||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||||
import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
|
import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
|
||||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
|
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
|
||||||
|
|
||||||
import android.animation.TimeInterpolator;
|
import android.animation.TimeInterpolator;
|
||||||
@@ -37,11 +37,10 @@ import com.android.launcher3.AbstractFloatingView;
|
|||||||
import com.android.launcher3.DeviceProfile;
|
import com.android.launcher3.DeviceProfile;
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationFlags;
|
|
||||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
|
||||||
import com.android.launcher3.anim.Interpolators;
|
import com.android.launcher3.anim.Interpolators;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
|
||||||
import com.android.launcher3.touch.AbstractStateChangeTouchController;
|
import com.android.launcher3.touch.AbstractStateChangeTouchController;
|
||||||
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
||||||
import com.android.launcher3.uioverrides.states.OverviewState;
|
import com.android.launcher3.uioverrides.states.OverviewState;
|
||||||
@@ -148,16 +147,16 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
|||||||
return isTouchOverHotseat(mLauncher, ev) ? ContainerType.HOTSEAT : ContainerType.WORKSPACE;
|
return isTouchOverHotseat(mLauncher, ev) ? ContainerType.HOTSEAT : ContainerType.WORKSPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnimatorSetBuilder getNormalToOverviewAnimation() {
|
private StateAnimationConfig getNormalToOverviewAnimation() {
|
||||||
mAllAppsInterpolatorWrapper.baseInterpolator = LINEAR;
|
mAllAppsInterpolatorWrapper.baseInterpolator = LINEAR;
|
||||||
|
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
StateAnimationConfig builder = new StateAnimationConfig();
|
||||||
builder.setInterpolator(ANIM_VERTICAL_PROGRESS, mAllAppsInterpolatorWrapper);
|
builder.setInterpolator(ANIM_VERTICAL_PROGRESS, mAllAppsInterpolatorWrapper);
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AnimatorSetBuilder getOverviewToAllAppsAnimation() {
|
private static StateAnimationConfig getOverviewToAllAppsAnimation() {
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
StateAnimationConfig builder = new StateAnimationConfig();
|
||||||
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL,
|
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL,
|
||||||
0, ALL_APPS_CONTENT_FADE_THRESHOLD));
|
0, ALL_APPS_CONTENT_FADE_THRESHOLD));
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_FADE, Interpolators.clampToProgress(DEACCEL,
|
builder.setInterpolator(ANIM_OVERVIEW_FADE, Interpolators.clampToProgress(DEACCEL,
|
||||||
@@ -165,8 +164,8 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
|||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnimatorSetBuilder getAllAppsToOverviewAnimation() {
|
private StateAnimationConfig getAllAppsToOverviewAnimation() {
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
StateAnimationConfig builder = new StateAnimationConfig();
|
||||||
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
|
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
|
||||||
1 - ALL_APPS_CONTENT_FADE_THRESHOLD, 1));
|
1 - ALL_APPS_CONTENT_FADE_THRESHOLD, 1));
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_FADE, Interpolators.clampToProgress(ACCEL,
|
builder.setInterpolator(ANIM_OVERVIEW_FADE, Interpolators.clampToProgress(ACCEL,
|
||||||
@@ -174,41 +173,42 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
|||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnimatorSetBuilder getNormalToAllAppsAnimation() {
|
private StateAnimationConfig getNormalToAllAppsAnimation() {
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
StateAnimationConfig builder = new StateAnimationConfig();
|
||||||
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL,
|
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL,
|
||||||
0, ALL_APPS_CONTENT_FADE_THRESHOLD));
|
0, ALL_APPS_CONTENT_FADE_THRESHOLD));
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnimatorSetBuilder getAllAppsToNormalAnimation() {
|
private StateAnimationConfig getAllAppsToNormalAnimation() {
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
StateAnimationConfig builder = new StateAnimationConfig();
|
||||||
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
|
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
|
||||||
1 - ALL_APPS_CONTENT_FADE_THRESHOLD, 1));
|
1 - ALL_APPS_CONTENT_FADE_THRESHOLD, 1));
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AnimatorSetBuilder getAnimatorSetBuilderForStates(LauncherState fromState,
|
protected StateAnimationConfig getConfigForStates(
|
||||||
LauncherState toState) {
|
LauncherState fromState, LauncherState toState) {
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
final StateAnimationConfig config;
|
||||||
if (fromState == NORMAL && toState == OVERVIEW) {
|
if (fromState == NORMAL && toState == OVERVIEW) {
|
||||||
builder = getNormalToOverviewAnimation();
|
config = getNormalToOverviewAnimation();
|
||||||
} else if (fromState == OVERVIEW && toState == ALL_APPS) {
|
} else if (fromState == OVERVIEW && toState == ALL_APPS) {
|
||||||
builder = getOverviewToAllAppsAnimation();
|
config = getOverviewToAllAppsAnimation();
|
||||||
} else if (fromState == ALL_APPS && toState == OVERVIEW) {
|
} else if (fromState == ALL_APPS && toState == OVERVIEW) {
|
||||||
builder = getAllAppsToOverviewAnimation();
|
config = getAllAppsToOverviewAnimation();
|
||||||
} else if (fromState == NORMAL && toState == ALL_APPS) {
|
} else if (fromState == NORMAL && toState == ALL_APPS) {
|
||||||
builder = getNormalToAllAppsAnimation();
|
config = getNormalToAllAppsAnimation();
|
||||||
} else if (fromState == ALL_APPS && toState == NORMAL) {
|
} else if (fromState == ALL_APPS && toState == NORMAL) {
|
||||||
builder = getAllAppsToNormalAnimation();
|
config = getAllAppsToNormalAnimation();
|
||||||
|
} else {
|
||||||
|
config = new StateAnimationConfig();
|
||||||
}
|
}
|
||||||
return builder;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected float initCurrentAnimation(@AnimationFlags int animComponents) {
|
protected float initCurrentAnimation(@AnimationFlags int animFlags) {
|
||||||
animComponents = updateAnimComponentsOnReinit(animComponents);
|
|
||||||
float range = getShiftRange();
|
float range = getShiftRange();
|
||||||
long maxAccuracy = (long) (2 * range);
|
long maxAccuracy = (long) (2 * range);
|
||||||
|
|
||||||
@@ -217,8 +217,10 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
|||||||
|
|
||||||
float totalShift = endVerticalShift - startVerticalShift;
|
float totalShift = endVerticalShift - startVerticalShift;
|
||||||
|
|
||||||
final AnimatorSetBuilder builder = totalShift == 0 ? new AnimatorSetBuilder()
|
final StateAnimationConfig config = totalShift == 0 ? new StateAnimationConfig()
|
||||||
: getAnimatorSetBuilderForStates(mFromState, mToState);
|
: getConfigForStates(mFromState, mToState);
|
||||||
|
config.animFlags = updateAnimComponentsOnReinit(animFlags);
|
||||||
|
config.duration = maxAccuracy;
|
||||||
|
|
||||||
cancelPendingAnim();
|
cancelPendingAnim();
|
||||||
|
|
||||||
@@ -232,15 +234,15 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
|||||||
cancelPendingAnim();
|
cancelPendingAnim();
|
||||||
clearState();
|
clearState();
|
||||||
};
|
};
|
||||||
mCurrentAnimation = AnimatorPlaybackController.wrap(mPendingAnimation, maxAccuracy)
|
mCurrentAnimation = mPendingAnimation.createPlaybackController()
|
||||||
.setOnCancelRunnable(onCancelRunnable);
|
.setOnCancelRunnable(onCancelRunnable);
|
||||||
mLauncher.getStateManager().setCurrentUserControlledAnimation(mCurrentAnimation);
|
mLauncher.getStateManager().setCurrentUserControlledAnimation(mCurrentAnimation);
|
||||||
totalShift = LayoutUtils.getShelfTrackingDistance(mLauncher,
|
totalShift = LayoutUtils.getShelfTrackingDistance(mLauncher,
|
||||||
mLauncher.getDeviceProfile());
|
mLauncher.getDeviceProfile());
|
||||||
} else {
|
} else {
|
||||||
mCurrentAnimation = mLauncher.getStateManager()
|
mCurrentAnimation = mLauncher.getStateManager()
|
||||||
.createAnimationToNewWorkspace(mToState, builder, maxAccuracy, this::clearState,
|
.createAnimationToNewWorkspace(mToState, config)
|
||||||
animComponents);
|
.setOnCancelRunnable(this::clearState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalShift == 0) {
|
if (totalShift == 0) {
|
||||||
|
|||||||
@@ -21,21 +21,22 @@ import android.content.Context;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
|
||||||
import com.android.launcher3.LauncherAnimationRunner;
|
import com.android.launcher3.LauncherAnimationRunner;
|
||||||
|
import com.android.launcher3.WrappedLauncherAnimationRunner;
|
||||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||||
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
|
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
|
||||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||||
import com.android.systemui.shared.system.TransactionCompat;
|
import com.android.systemui.shared.system.TransactionCompat;
|
||||||
|
|
||||||
@FunctionalInterface
|
public abstract class RemoteAnimationProvider {
|
||||||
public interface RemoteAnimationProvider {
|
|
||||||
|
|
||||||
|
LauncherAnimationRunner mAnimationRunner;
|
||||||
static final int Z_BOOST_BASE = 800570000;
|
static final int Z_BOOST_BASE = 800570000;
|
||||||
|
|
||||||
AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
|
public abstract AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
|
||||||
RemoteAnimationTargetCompat[] wallpaperTargets);
|
RemoteAnimationTargetCompat[] wallpaperTargets);
|
||||||
|
|
||||||
default ActivityOptions toActivityOptions(Handler handler, long duration, Context context) {
|
ActivityOptions toActivityOptions(Handler handler, long duration, Context context) {
|
||||||
LauncherAnimationRunner runner = new LauncherAnimationRunner(handler,
|
mAnimationRunner = new LauncherAnimationRunner(handler,
|
||||||
false /* startAtFrontOfQueue */) {
|
false /* startAtFrontOfQueue */) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -44,8 +45,11 @@ public interface RemoteAnimationProvider {
|
|||||||
result.setAnimation(createWindowAnimation(appTargets, wallpaperTargets), context);
|
result.setAnimation(createWindowAnimation(appTargets, wallpaperTargets), context);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner(
|
||||||
|
mAnimationRunner, false /* startAtFrontOfQueue */);
|
||||||
|
|
||||||
return ActivityOptionsCompat.makeRemoteAnimation(
|
return ActivityOptionsCompat.makeRemoteAnimation(
|
||||||
new RemoteAnimationAdapterCompat(runner, duration, 0));
|
new RemoteAnimationAdapterCompat(wrapper, duration, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,7 +67,7 @@ public interface RemoteAnimationProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getLayer(RemoteAnimationTargetCompat target, int boostModeTarget) {
|
public static int getLayer(RemoteAnimationTargetCompat target, int boostModeTarget) {
|
||||||
return target.mode == boostModeTarget
|
return target.mode == boostModeTarget
|
||||||
? Z_BOOST_BASE + target.prefixOrderIndex
|
? Z_BOOST_BASE + target.prefixOrderIndex
|
||||||
: target.prefixOrderIndex;
|
: target.prefixOrderIndex;
|
||||||
@@ -72,7 +76,7 @@ public interface RemoteAnimationProvider {
|
|||||||
/**
|
/**
|
||||||
* @return the target with the lowest opaque layer for a certain app animation, or null.
|
* @return the target with the lowest opaque layer for a certain app animation, or null.
|
||||||
*/
|
*/
|
||||||
static RemoteAnimationTargetCompat findLowestOpaqueLayerTarget(
|
public static RemoteAnimationTargetCompat findLowestOpaqueLayerTarget(
|
||||||
RemoteAnimationTargetCompat[] appTargets, int mode) {
|
RemoteAnimationTargetCompat[] appTargets, int mode) {
|
||||||
int lowestLayer = Integer.MAX_VALUE;
|
int lowestLayer = Integer.MAX_VALUE;
|
||||||
int lowestLayerIndex = -1;
|
int lowestLayerIndex = -1;
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
<string name="notification_dots_service_title">Show notification dots</string>
|
<string name="notification_dots_service_title">Show notification dots</string>
|
||||||
|
|
||||||
<!-- Label for the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=40] -->
|
<!-- Label for the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=40] -->
|
||||||
<string name="auto_add_shortcuts_label">Add icon to Home screen</string>
|
<string name="auto_add_shortcuts_label">Add app icons to Home screen</string>
|
||||||
<!-- Text description of the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=NONE] -->
|
<!-- Text description of the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=NONE] -->
|
||||||
<string name="auto_add_shortcuts_description">For new apps</string>
|
<string name="auto_add_shortcuts_description">For new apps</string>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.model;
|
||||||
|
|
||||||
|
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
|
||||||
|
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
|
||||||
|
import static com.android.launcher3.LauncherSettings.Favorites.TMP_CONTENT_URI;
|
||||||
|
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
|
||||||
|
import static com.android.launcher3.util.LauncherModelHelper.APP_ICON;
|
||||||
|
import static com.android.launcher3.util.LauncherModelHelper.DESKTOP;
|
||||||
|
import static com.android.launcher3.util.LauncherModelHelper.HOTSEAT;
|
||||||
|
import static com.android.launcher3.util.LauncherModelHelper.SHORTCUT;
|
||||||
|
import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.os.Process;
|
||||||
|
|
||||||
|
import com.android.launcher3.InvariantDeviceProfile;
|
||||||
|
import com.android.launcher3.LauncherSettings;
|
||||||
|
import com.android.launcher3.pm.UserCache;
|
||||||
|
import com.android.launcher3.util.LauncherModelHelper;
|
||||||
|
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
/** Unit tests for {@link GridSizeMigrationTaskV2} */
|
||||||
|
@RunWith(LauncherRoboTestRunner.class)
|
||||||
|
public class GridSizeMigrationTaskV2Test {
|
||||||
|
|
||||||
|
private LauncherModelHelper mModelHelper;
|
||||||
|
private Context mContext;
|
||||||
|
private SQLiteDatabase mDb;
|
||||||
|
|
||||||
|
private HashSet<String> mValidPackages;
|
||||||
|
private InvariantDeviceProfile mIdp;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mModelHelper = new LauncherModelHelper();
|
||||||
|
mContext = RuntimeEnvironment.application;
|
||||||
|
mDb = mModelHelper.provider.getDb();
|
||||||
|
|
||||||
|
mValidPackages = new HashSet<>();
|
||||||
|
mValidPackages.add(TEST_PACKAGE);
|
||||||
|
mIdp = InvariantDeviceProfile.INSTANCE.get(mContext);
|
||||||
|
|
||||||
|
long userSerial = UserCache.INSTANCE.get(mContext).getSerialNumberForUser(
|
||||||
|
Process.myUserHandle());
|
||||||
|
dropTable(mDb, LauncherSettings.Favorites.TMP_TABLE);
|
||||||
|
LauncherSettings.Favorites.addTableToDb(mDb, userSerial, false,
|
||||||
|
LauncherSettings.Favorites.TMP_TABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigration() {
|
||||||
|
final String testPackage1 = "com.android.launcher3.validpackage1";
|
||||||
|
final String testPackage2 = "com.android.launcher3.validpackage2";
|
||||||
|
final String testPackage3 = "com.android.launcher3.validpackage3";
|
||||||
|
final String testPackage4 = "com.android.launcher3.validpackage4";
|
||||||
|
final String testPackage5 = "com.android.launcher3.validpackage5";
|
||||||
|
final String testPackage7 = "com.android.launcher3.validpackage7";
|
||||||
|
|
||||||
|
mValidPackages.add(testPackage1);
|
||||||
|
mValidPackages.add(testPackage2);
|
||||||
|
mValidPackages.add(testPackage3);
|
||||||
|
mValidPackages.add(testPackage4);
|
||||||
|
mValidPackages.add(testPackage5);
|
||||||
|
mValidPackages.add(testPackage7);
|
||||||
|
|
||||||
|
int[] srcHotseatItems = {
|
||||||
|
mModelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
|
||||||
|
mModelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
|
||||||
|
-1,
|
||||||
|
mModelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
|
||||||
|
mModelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI),
|
||||||
|
};
|
||||||
|
mModelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage5, 5, TMP_CONTENT_URI);
|
||||||
|
|
||||||
|
int[] destHotseatItems = {
|
||||||
|
-1,
|
||||||
|
mModelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2),
|
||||||
|
-1,
|
||||||
|
};
|
||||||
|
mModelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage7);
|
||||||
|
|
||||||
|
mIdp.numHotseatIcons = 3;
|
||||||
|
mIdp.numColumns = 3;
|
||||||
|
mIdp.numRows = 3;
|
||||||
|
GridSizeMigrationTaskV2.DbReader srcReader = new GridSizeMigrationTaskV2.DbReader(mDb,
|
||||||
|
LauncherSettings.Favorites.TMP_TABLE, mContext, mValidPackages, 5);
|
||||||
|
GridSizeMigrationTaskV2.DbReader destReader = new GridSizeMigrationTaskV2.DbReader(mDb,
|
||||||
|
LauncherSettings.Favorites.TABLE_NAME, mContext, mValidPackages, 3);
|
||||||
|
GridSizeMigrationTaskV2 task = new GridSizeMigrationTaskV2(mContext, mDb, srcReader,
|
||||||
|
destReader, 3, new Point(mIdp.numColumns, mIdp.numRows));
|
||||||
|
task.migrate();
|
||||||
|
|
||||||
|
Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
|
||||||
|
new String[]{LauncherSettings.Favorites.SCREEN, LauncherSettings.Favorites.INTENT},
|
||||||
|
"container=" + CONTAINER_HOTSEAT, null, null, null);
|
||||||
|
assertEquals(c.getCount(), 3);
|
||||||
|
int screenIndex = c.getColumnIndex(LauncherSettings.Favorites.SCREEN);
|
||||||
|
int intentIndex = c.getColumnIndex(LauncherSettings.Favorites.INTENT);
|
||||||
|
c.moveToNext();
|
||||||
|
assertEquals(c.getInt(screenIndex), 1);
|
||||||
|
assertTrue(c.getString(intentIndex).contains(testPackage2));
|
||||||
|
c.moveToNext();
|
||||||
|
assertEquals(c.getInt(screenIndex), 0);
|
||||||
|
assertTrue(c.getString(intentIndex).contains(testPackage1));
|
||||||
|
c.moveToNext();
|
||||||
|
assertEquals(c.getInt(screenIndex), 2);
|
||||||
|
assertTrue(c.getString(intentIndex).contains(testPackage3));
|
||||||
|
c.close();
|
||||||
|
|
||||||
|
c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
|
||||||
|
new String[]{LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,
|
||||||
|
LauncherSettings.Favorites.INTENT},
|
||||||
|
"container=" + CONTAINER_DESKTOP, null, null, null);
|
||||||
|
assertEquals(c.getCount(), 2);
|
||||||
|
intentIndex = c.getColumnIndex(LauncherSettings.Favorites.INTENT);
|
||||||
|
int cellXIndex = c.getColumnIndex(LauncherSettings.Favorites.CELLX);
|
||||||
|
int cellYIndex = c.getColumnIndex(LauncherSettings.Favorites.CELLY);
|
||||||
|
|
||||||
|
c.moveToNext();
|
||||||
|
assertTrue(c.getString(intentIndex).contains(testPackage7));
|
||||||
|
c.moveToNext();
|
||||||
|
assertTrue(c.getString(intentIndex).contains(testPackage5));
|
||||||
|
assertEquals(c.getInt(cellXIndex), 0);
|
||||||
|
assertEquals(c.getInt(cellYIndex), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -230,7 +230,21 @@ public class LauncherModelHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int addItem(int type, int screen, int container, int x, int y) {
|
public int addItem(int type, int screen, int container, int x, int y) {
|
||||||
return addItem(type, screen, container, x, y, mDefaultProfileId);
|
return addItem(type, screen, container, x, y, mDefaultProfileId, TEST_PACKAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int addItem(int type, int screen, int container, int x, int y, long profileId) {
|
||||||
|
return addItem(type, screen, container, x, y, profileId, TEST_PACKAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int addItem(int type, int screen, int container, int x, int y, String packageName) {
|
||||||
|
return addItem(type, screen, container, x, y, mDefaultProfileId, packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int addItem(int type, int screen, int container, int x, int y, String packageName,
|
||||||
|
int id, Uri contentUri) {
|
||||||
|
addItem(type, screen, container, x, y, mDefaultProfileId, packageName, id, contentUri);
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -238,11 +252,19 @@ public class LauncherModelHelper {
|
|||||||
* @param type {@link #APP_ICON} or {@link #SHORTCUT} or >= 2 for
|
* @param type {@link #APP_ICON} or {@link #SHORTCUT} or >= 2 for
|
||||||
* folder (where the type represents the number of items in the folder).
|
* folder (where the type represents the number of items in the folder).
|
||||||
*/
|
*/
|
||||||
public int addItem(int type, int screen, int container, int x, int y, long profileId) {
|
public int addItem(int type, int screen, int container, int x, int y, long profileId,
|
||||||
|
String packageName) {
|
||||||
Context context = RuntimeEnvironment.application;
|
Context context = RuntimeEnvironment.application;
|
||||||
int id = LauncherSettings.Settings.call(context.getContentResolver(),
|
int id = LauncherSettings.Settings.call(context.getContentResolver(),
|
||||||
LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
|
LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
|
||||||
.getInt(LauncherSettings.Settings.EXTRA_VALUE);
|
.getInt(LauncherSettings.Settings.EXTRA_VALUE);
|
||||||
|
addItem(type, screen, container, x, y, profileId, packageName, id, CONTENT_URI);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItem(int type, int screen, int container, int x, int y, long profileId,
|
||||||
|
String packageName, int id, Uri contentUri) {
|
||||||
|
Context context = RuntimeEnvironment.application;
|
||||||
|
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(LauncherSettings.Favorites._ID, id);
|
values.put(LauncherSettings.Favorites._ID, id);
|
||||||
@@ -257,7 +279,7 @@ public class LauncherModelHelper {
|
|||||||
if (type == APP_ICON || type == SHORTCUT) {
|
if (type == APP_ICON || type == SHORTCUT) {
|
||||||
values.put(LauncherSettings.Favorites.ITEM_TYPE, type);
|
values.put(LauncherSettings.Favorites.ITEM_TYPE, type);
|
||||||
values.put(LauncherSettings.Favorites.INTENT,
|
values.put(LauncherSettings.Favorites.INTENT,
|
||||||
new Intent(Intent.ACTION_MAIN).setPackage(TEST_PACKAGE).toUri(0));
|
new Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0));
|
||||||
} else {
|
} else {
|
||||||
values.put(LauncherSettings.Favorites.ITEM_TYPE,
|
values.put(LauncherSettings.Favorites.ITEM_TYPE,
|
||||||
LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
|
LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
|
||||||
@@ -267,8 +289,7 @@ public class LauncherModelHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.getContentResolver().insert(CONTENT_URI, values);
|
context.getContentResolver().insert(contentUri, values);
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[][][] createGrid(int[][][] typeArray) {
|
public int[][][] createGrid(int[][][] typeArray) {
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CH
|
|||||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
|
import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
|
||||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
|
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
|
||||||
|
|
||||||
import android.animation.Animator;
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@@ -30,11 +29,12 @@ import android.util.Pair;
|
|||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.accessibility.AccessibilityNodeInfo;
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
|
import android.view.animation.Interpolator;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||||
import com.android.launcher3.util.TouchController;
|
import com.android.launcher3.util.TouchController;
|
||||||
@@ -134,9 +134,8 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
|
|||||||
* Creates a user-controlled animation to hint that the view will be closed if completed.
|
* Creates a user-controlled animation to hint that the view will be closed if completed.
|
||||||
* @param distanceToMove The max distance that elements should move from their starting point.
|
* @param distanceToMove The max distance that elements should move from their starting point.
|
||||||
*/
|
*/
|
||||||
public @Nullable Animator createHintCloseAnim(float distanceToMove) {
|
public void addHintCloseAnim(
|
||||||
return null;
|
float distanceToMove, Interpolator interpolator, PendingAnimation target) { }
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void logActionCommand(int command);
|
public abstract void logActionCommand(int command);
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.launcher3;
|
package com.android.launcher3;
|
||||||
|
|
||||||
import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_ALGO;
|
import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_ALGO;
|
||||||
|
import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
|
||||||
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
|
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
|
||||||
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
|
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
|
||||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||||
@@ -164,8 +165,11 @@ public class LauncherProvider extends ContentProvider {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mOpenHelper.close();
|
DatabaseHelper oldHelper = mOpenHelper;
|
||||||
mOpenHelper = new DatabaseHelper(getContext());
|
mOpenHelper = new DatabaseHelper(getContext());
|
||||||
|
copyTable(oldHelper.getReadableDatabase(), Favorites.TABLE_NAME,
|
||||||
|
mOpenHelper.getWritableDatabase(), Favorites.TMP_TABLE, getContext());
|
||||||
|
oldHelper.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,11 @@ public class LauncherSettings {
|
|||||||
*/
|
*/
|
||||||
public static final String PREVIEW_TABLE_NAME = "favorites_preview";
|
public static final String PREVIEW_TABLE_NAME = "favorites_preview";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary table used specifically for multi-db grid migrations
|
||||||
|
*/
|
||||||
|
public static final String TMP_TABLE = "favorites_tmp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The content:// style URL for "favorites" table
|
* The content:// style URL for "favorites" table
|
||||||
*/
|
*/
|
||||||
@@ -114,6 +119,12 @@ public class LauncherSettings {
|
|||||||
public static final Uri PREVIEW_CONTENT_URI = Uri.parse("content://"
|
public static final Uri PREVIEW_CONTENT_URI = Uri.parse("content://"
|
||||||
+ LauncherProvider.AUTHORITY + "/" + PREVIEW_TABLE_NAME);
|
+ LauncherProvider.AUTHORITY + "/" + PREVIEW_TABLE_NAME);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The content:// style URL for "favorites_tmp" table
|
||||||
|
*/
|
||||||
|
public static final Uri TMP_CONTENT_URI = Uri.parse("content://"
|
||||||
|
+ LauncherProvider.AUTHORITY + "/" + TMP_TABLE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The content:// style URL for a given row, identified by its id.
|
* The content:// style URL for a given row, identified by its id.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -20,11 +20,6 @@ import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
|
|||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
|
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
|
||||||
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||||
@@ -32,6 +27,11 @@ import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
|
|||||||
import static com.android.launcher3.anim.Interpolators.clampToProgress;
|
import static com.android.launcher3.anim.Interpolators.clampToProgress;
|
||||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
||||||
import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
|
import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
|
||||||
import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
|
import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
|
||||||
import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
|
import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
|
||||||
import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL;
|
import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL;
|
||||||
@@ -46,9 +46,9 @@ import android.view.View;
|
|||||||
import android.view.animation.Interpolator;
|
import android.view.animation.Interpolator;
|
||||||
|
|
||||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
|
||||||
import com.android.launcher3.states.HintState;
|
import com.android.launcher3.states.HintState;
|
||||||
import com.android.launcher3.states.SpringLoadedState;
|
import com.android.launcher3.states.SpringLoadedState;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.launcher3.uioverrides.states.AllAppsState;
|
import com.android.launcher3.uioverrides.states.AllAppsState;
|
||||||
import com.android.launcher3.uioverrides.states.OverviewState;
|
import com.android.launcher3.uioverrides.states.OverviewState;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||||
@@ -325,13 +325,13 @@ public abstract class LauncherState {
|
|||||||
* - Setting some start values (e.g. scale) for views that are hidden but about to be shown.
|
* - Setting some start values (e.g. scale) for views that are hidden but about to be shown.
|
||||||
*/
|
*/
|
||||||
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
|
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
|
||||||
AnimatorSetBuilder builder) {
|
StateAnimationConfig config) {
|
||||||
if (this == NORMAL && fromState == OVERVIEW) {
|
if (this == NORMAL && fromState == OVERVIEW) {
|
||||||
builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
|
config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
|
||||||
builder.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
|
config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
|
config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL);
|
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL);
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
|
config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
|
||||||
Workspace workspace = launcher.getWorkspace();
|
Workspace workspace = launcher.getWorkspace();
|
||||||
|
|
||||||
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
|
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
|
||||||
@@ -363,7 +363,7 @@ public abstract class LauncherState {
|
|||||||
}
|
}
|
||||||
} else if (this == NORMAL && fromState == OVERVIEW_PEEK) {
|
} else if (this == NORMAL && fromState == OVERVIEW_PEEK) {
|
||||||
// Keep fully visible until the very end (when overview is offscreen) to make invisible.
|
// Keep fully visible until the very end (when overview is offscreen) to make invisible.
|
||||||
builder.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1);
|
config.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,26 +17,23 @@
|
|||||||
package com.android.launcher3;
|
package com.android.launcher3;
|
||||||
|
|
||||||
import static com.android.launcher3.LauncherState.NORMAL;
|
import static com.android.launcher3.LauncherState.NORMAL;
|
||||||
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
|
import android.animation.Animator.AnimatorListener;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
|
||||||
import androidx.annotation.IntDef;
|
|
||||||
|
|
||||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.anim.PropertySetter;
|
|
||||||
import com.android.launcher3.anim.PropertySetter.AnimatedPropertySetter;
|
|
||||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,28 +81,7 @@ public class LauncherStateManager {
|
|||||||
|
|
||||||
public static final String TAG = "StateManager";
|
public static final String TAG = "StateManager";
|
||||||
|
|
||||||
// We separate the state animations into "atomic" and "non-atomic" components. The atomic
|
private final AnimationState mConfig = new AnimationState();
|
||||||
// components may be run atomically - that is, all at once, instead of user-controlled. However,
|
|
||||||
// atomic components are not restricted to this purpose; they can be user-controlled alongside
|
|
||||||
// non atomic components as well. Note that each gesture model has exactly one atomic component,
|
|
||||||
// PLAY_ATOMIC_OVERVIEW_SCALE *or* PLAY_ATOMIC_OVERVIEW_PEEK.
|
|
||||||
@IntDef(flag = true, value = {
|
|
||||||
PLAY_NON_ATOMIC,
|
|
||||||
PLAY_ATOMIC_OVERVIEW_SCALE,
|
|
||||||
PLAY_ATOMIC_OVERVIEW_PEEK,
|
|
||||||
SKIP_OVERVIEW,
|
|
||||||
})
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
|
||||||
public @interface AnimationFlags {}
|
|
||||||
public static final int PLAY_NON_ATOMIC = 1 << 0;
|
|
||||||
public static final int PLAY_ATOMIC_OVERVIEW_SCALE = 1 << 1;
|
|
||||||
public static final int PLAY_ATOMIC_OVERVIEW_PEEK = 1 << 2;
|
|
||||||
public static final int SKIP_OVERVIEW = 1 << 3;
|
|
||||||
|
|
||||||
public static final int ANIM_ALL_COMPONENTS = PLAY_NON_ATOMIC | PLAY_ATOMIC_OVERVIEW_SCALE
|
|
||||||
| PLAY_ATOMIC_OVERVIEW_PEEK;
|
|
||||||
|
|
||||||
private final AnimationConfig mConfig = new AnimationConfig();
|
|
||||||
private final Handler mUiHandler;
|
private final Handler mUiHandler;
|
||||||
private final Launcher mLauncher;
|
private final Launcher mLauncher;
|
||||||
private final ArrayList<StateListener> mListeners = new ArrayList<>();
|
private final ArrayList<StateListener> mListeners = new ArrayList<>();
|
||||||
@@ -140,7 +116,7 @@ public class LauncherStateManager {
|
|||||||
writer.println(prefix + "\tmCurrentStableState:" + mCurrentStableState);
|
writer.println(prefix + "\tmCurrentStableState:" + mCurrentStableState);
|
||||||
writer.println(prefix + "\tmState:" + mState);
|
writer.println(prefix + "\tmState:" + mState);
|
||||||
writer.println(prefix + "\tmRestState:" + mRestState);
|
writer.println(prefix + "\tmRestState:" + mRestState);
|
||||||
writer.println(prefix + "\tisInTransition:" + (mConfig.mCurrentAnimation != null));
|
writer.println(prefix + "\tisInTransition:" + (mConfig.currentAnimation != null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public StateHandler[] getStateHandlers() {
|
public StateHandler[] getStateHandlers() {
|
||||||
@@ -171,7 +147,7 @@ public class LauncherStateManager {
|
|||||||
*/
|
*/
|
||||||
public boolean isInStableState(LauncherState state) {
|
public boolean isInStableState(LauncherState state) {
|
||||||
return mState == state && mCurrentStableState == state
|
return mState == state && mCurrentStableState == state
|
||||||
&& (mConfig.mTargetState == null || mConfig.mTargetState == state);
|
&& (mConfig.targetState == null || mConfig.targetState == state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -218,12 +194,12 @@ public class LauncherStateManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void reapplyState(boolean cancelCurrentAnimation) {
|
public void reapplyState(boolean cancelCurrentAnimation) {
|
||||||
boolean wasInAnimation = mConfig.mCurrentAnimation != null;
|
boolean wasInAnimation = mConfig.currentAnimation != null;
|
||||||
if (cancelCurrentAnimation) {
|
if (cancelCurrentAnimation) {
|
||||||
cancelAllStateElementAnimation();
|
cancelAllStateElementAnimation();
|
||||||
cancelAnimation();
|
cancelAnimation();
|
||||||
}
|
}
|
||||||
if (mConfig.mCurrentAnimation == null) {
|
if (mConfig.currentAnimation == null) {
|
||||||
for (StateHandler handler : getStateHandlers()) {
|
for (StateHandler handler : getStateHandlers()) {
|
||||||
handler.setState(mState);
|
handler.setState(mState);
|
||||||
}
|
}
|
||||||
@@ -237,16 +213,16 @@ public class LauncherStateManager {
|
|||||||
final Runnable onCompleteRunnable) {
|
final Runnable onCompleteRunnable) {
|
||||||
animated &= Utilities.areAnimationsEnabled(mLauncher);
|
animated &= Utilities.areAnimationsEnabled(mLauncher);
|
||||||
if (mLauncher.isInState(state)) {
|
if (mLauncher.isInState(state)) {
|
||||||
if (mConfig.mCurrentAnimation == null) {
|
if (mConfig.currentAnimation == null) {
|
||||||
// Run any queued runnable
|
// Run any queued runnable
|
||||||
if (onCompleteRunnable != null) {
|
if (onCompleteRunnable != null) {
|
||||||
onCompleteRunnable.run();
|
onCompleteRunnable.run();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (!mConfig.userControlled && animated && mConfig.mTargetState == state) {
|
} else if (!mConfig.userControlled && animated && mConfig.targetState == state) {
|
||||||
// We are running the same animation as requested
|
// We are running the same animation as requested
|
||||||
if (onCompleteRunnable != null) {
|
if (onCompleteRunnable != null) {
|
||||||
mConfig.mCurrentAnimation.addListener(
|
mConfig.currentAnimation.addListener(
|
||||||
AnimationSuccessListener.forRunnable(onCompleteRunnable));
|
AnimationSuccessListener.forRunnable(onCompleteRunnable));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -276,9 +252,9 @@ public class LauncherStateManager {
|
|||||||
if (delay > 0) {
|
if (delay > 0) {
|
||||||
// Create the animation after the delay as some properties can change between preparing
|
// Create the animation after the delay as some properties can change between preparing
|
||||||
// the animation and running the animation.
|
// the animation and running the animation.
|
||||||
int startChangeId = mConfig.mChangeId;
|
int startChangeId = mConfig.changeId;
|
||||||
mUiHandler.postDelayed(() -> {
|
mUiHandler.postDelayed(() -> {
|
||||||
if (mConfig.mChangeId == startChangeId) {
|
if (mConfig.changeId == startChangeId) {
|
||||||
goToStateAnimated(state, fromState, onCompleteRunnable);
|
goToStateAnimated(state, fromState, onCompleteRunnable);
|
||||||
}
|
}
|
||||||
}, delay);
|
}, delay);
|
||||||
@@ -294,11 +270,11 @@ public class LauncherStateManager {
|
|||||||
mConfig.duration = state == NORMAL
|
mConfig.duration = state == NORMAL
|
||||||
? fromState.getTransitionDuration(mLauncher)
|
? fromState.getTransitionDuration(mLauncher)
|
||||||
: state.getTransitionDuration(mLauncher);
|
: state.getTransitionDuration(mLauncher);
|
||||||
|
prepareForAtomicAnimation(fromState, state, mConfig);
|
||||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
AnimatorSet animation = createAnimationToNewWorkspaceInternal(state).getAnim();
|
||||||
prepareForAtomicAnimation(fromState, state, builder);
|
if (onCompleteRunnable != null) {
|
||||||
AnimatorSet animation = createAnimationToNewWorkspaceInternal(
|
animation.addListener(AnimationSuccessListener.forRunnable(onCompleteRunnable));
|
||||||
state, builder, onCompleteRunnable);
|
}
|
||||||
mUiHandler.post(new StartAnimRunnable(animation));
|
mUiHandler.post(new StartAnimRunnable(animation));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,44 +284,22 @@ public class LauncherStateManager {
|
|||||||
* - Setting some start values (e.g. scale) for views that are hidden but about to be shown.
|
* - Setting some start values (e.g. scale) for views that are hidden but about to be shown.
|
||||||
*/
|
*/
|
||||||
public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState,
|
public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState,
|
||||||
AnimatorSetBuilder builder) {
|
StateAnimationConfig config) {
|
||||||
toState.prepareForAtomicAnimation(mLauncher, fromState, builder);
|
toState.prepareForAtomicAnimation(mLauncher, fromState, config);
|
||||||
}
|
|
||||||
|
|
||||||
public AnimatorSet createAtomicAnimation(LauncherState fromState, LauncherState toState,
|
|
||||||
AnimatorSetBuilder builder, @AnimationFlags int animFlags, long duration) {
|
|
||||||
prepareForAtomicAnimation(fromState, toState, builder);
|
|
||||||
AnimationConfig config = new AnimationConfig();
|
|
||||||
config.mAnimFlags = animFlags;
|
|
||||||
config.duration = duration;
|
|
||||||
for (StateHandler handler : mLauncher.getStateManager().getStateHandlers()) {
|
|
||||||
handler.setStateWithAnimation(toState, builder, config);
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link AnimatorPlaybackController} that can be used for a controlled
|
* Creates an animation representing atomic transitions between the provided states
|
||||||
* state transition. The UI is force-set to fromState before creating the controller.
|
|
||||||
* @param fromState the initial state for the transition.
|
|
||||||
* @param state the final state for the transition.
|
|
||||||
* @param duration intended duration for normal playback. Use higher duration for better
|
|
||||||
* accuracy.
|
|
||||||
*/
|
*/
|
||||||
public AnimatorPlaybackController createAnimationToNewWorkspace(
|
public AnimatorSet createAtomicAnimation(
|
||||||
LauncherState fromState, LauncherState state, long duration) {
|
LauncherState fromState, LauncherState toState, StateAnimationConfig config) {
|
||||||
// Since we are creating a state animation to a different state, temporarily prevent state
|
PendingAnimation builder = new PendingAnimation(config.duration);
|
||||||
// change as part of config reset.
|
prepareForAtomicAnimation(fromState, toState, config);
|
||||||
LauncherState originalRestState = mRestState;
|
|
||||||
mRestState = state;
|
|
||||||
mConfig.reset();
|
|
||||||
mRestState = originalRestState;
|
|
||||||
|
|
||||||
for (StateHandler handler : getStateHandlers()) {
|
for (StateHandler handler : mLauncher.getStateManager().getStateHandlers()) {
|
||||||
handler.setState(fromState);
|
handler.setStateWithAnimation(toState, config, builder);
|
||||||
}
|
}
|
||||||
|
return builder.getAnim();
|
||||||
return createAnimationToNewWorkspace(state, duration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -362,32 +316,27 @@ public class LauncherStateManager {
|
|||||||
|
|
||||||
public AnimatorPlaybackController createAnimationToNewWorkspace(
|
public AnimatorPlaybackController createAnimationToNewWorkspace(
|
||||||
LauncherState state, long duration, @AnimationFlags int animComponents) {
|
LauncherState state, long duration, @AnimationFlags int animComponents) {
|
||||||
return createAnimationToNewWorkspace(state, new AnimatorSetBuilder(), duration, null,
|
StateAnimationConfig config = new StateAnimationConfig();
|
||||||
animComponents);
|
config.duration = duration;
|
||||||
|
config.animFlags = animComponents;
|
||||||
|
return createAnimationToNewWorkspace(state, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AnimatorPlaybackController createAnimationToNewWorkspace(LauncherState state,
|
public AnimatorPlaybackController createAnimationToNewWorkspace(LauncherState state,
|
||||||
AnimatorSetBuilder builder, long duration, Runnable onCancelRunnable,
|
StateAnimationConfig config) {
|
||||||
@AnimationFlags int animComponents) {
|
|
||||||
mConfig.reset();
|
mConfig.reset();
|
||||||
mConfig.userControlled = true;
|
config.copyTo(mConfig);
|
||||||
mConfig.mAnimFlags = animComponents;
|
mConfig.playbackController = createAnimationToNewWorkspaceInternal(state)
|
||||||
mConfig.duration = duration;
|
.createPlaybackController();
|
||||||
mConfig.playbackController = AnimatorPlaybackController.wrap(
|
|
||||||
createAnimationToNewWorkspaceInternal(state, builder, null), duration)
|
|
||||||
.setOnCancelRunnable(onCancelRunnable);
|
|
||||||
return mConfig.playbackController;
|
return mConfig.playbackController;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AnimatorSet createAnimationToNewWorkspaceInternal(final LauncherState state,
|
private PendingAnimation createAnimationToNewWorkspaceInternal(final LauncherState state) {
|
||||||
AnimatorSetBuilder builder, final Runnable onCompleteRunnable) {
|
PendingAnimation builder = new PendingAnimation(mConfig.duration);
|
||||||
|
|
||||||
for (StateHandler handler : getStateHandlers()) {
|
for (StateHandler handler : getStateHandlers()) {
|
||||||
handler.setStateWithAnimation(state, builder, mConfig);
|
handler.setStateWithAnimation(state, mConfig, builder);
|
||||||
}
|
}
|
||||||
|
builder.getAnim().addListener(new AnimationSuccessListener() {
|
||||||
final AnimatorSet animation = builder.build();
|
|
||||||
animation.addListener(new AnimationSuccessListener() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationStart(Animator animation) {
|
public void onAnimationStart(Animator animation) {
|
||||||
@@ -397,15 +346,11 @@ public class LauncherStateManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationSuccess(Animator animator) {
|
public void onAnimationSuccess(Animator animator) {
|
||||||
// Run any queued runnables
|
|
||||||
if (onCompleteRunnable != null) {
|
|
||||||
onCompleteRunnable.run();
|
|
||||||
}
|
|
||||||
onStateTransitionEnd(state);
|
onStateTransitionEnd(state);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mConfig.setAnimation(animation, state);
|
mConfig.setAnimation(builder.getAnim(), state);
|
||||||
return mConfig.mCurrentAnimation;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onStateTransitionStart(LauncherState state) {
|
private void onStateTransitionStart(LauncherState state) {
|
||||||
@@ -452,7 +397,7 @@ public class LauncherStateManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void moveToRestState() {
|
public void moveToRestState() {
|
||||||
if (mConfig.mCurrentAnimation != null && mConfig.userControlled) {
|
if (mConfig.currentAnimation != null && mConfig.userControlled) {
|
||||||
// The user is doing something. Lets not mess it up
|
// The user is doing something. Lets not mess it up
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -500,12 +445,12 @@ public class LauncherStateManager {
|
|||||||
&& mConfig.playbackController.getTarget() == childAnim) {
|
&& mConfig.playbackController.getTarget() == childAnim) {
|
||||||
clearCurrentAnimation();
|
clearCurrentAnimation();
|
||||||
break;
|
break;
|
||||||
} else if (mConfig.mCurrentAnimation == childAnim) {
|
} else if (mConfig.currentAnimation == childAnim) {
|
||||||
clearCurrentAnimation();
|
clearCurrentAnimation();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean reapplyNeeded = mConfig.mCurrentAnimation != null;
|
boolean reapplyNeeded = mConfig.currentAnimation != null;
|
||||||
cancelAnimation();
|
cancelAnimation();
|
||||||
if (reapplyNeeded) {
|
if (reapplyNeeded) {
|
||||||
reapplyState();
|
reapplyState();
|
||||||
@@ -557,9 +502,9 @@ public class LauncherStateManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void clearCurrentAnimation() {
|
private void clearCurrentAnimation() {
|
||||||
if (mConfig.mCurrentAnimation != null) {
|
if (mConfig.currentAnimation != null) {
|
||||||
mConfig.mCurrentAnimation.removeListener(mConfig);
|
mConfig.currentAnimation.removeListener(mConfig);
|
||||||
mConfig.mCurrentAnimation = null;
|
mConfig.currentAnimation = null;
|
||||||
}
|
}
|
||||||
mConfig.playbackController = null;
|
mConfig.playbackController = null;
|
||||||
}
|
}
|
||||||
@@ -574,54 +519,42 @@ public class LauncherStateManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mConfig.mCurrentAnimation != mAnim) {
|
if (mConfig.currentAnimation != mAnim) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mAnim.start();
|
mAnim.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AnimationConfig extends AnimatorListenerAdapter {
|
private static class AnimationState extends StateAnimationConfig implements AnimatorListener {
|
||||||
public long duration;
|
|
||||||
public boolean userControlled;
|
private static final StateAnimationConfig DEFAULT = new StateAnimationConfig();
|
||||||
public AnimatorPlaybackController playbackController;
|
|
||||||
private @AnimationFlags int mAnimFlags = ANIM_ALL_COMPONENTS;
|
public AnimatorPlaybackController playbackController;
|
||||||
private PropertySetter mPropertySetter;
|
public AnimatorSet currentAnimation;
|
||||||
|
public LauncherState targetState;
|
||||||
|
|
||||||
private AnimatorSet mCurrentAnimation;
|
|
||||||
private LauncherState mTargetState;
|
|
||||||
// Id to keep track of config changes, to tie an animation with the corresponding request
|
// Id to keep track of config changes, to tie an animation with the corresponding request
|
||||||
private int mChangeId = 0;
|
public int changeId = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancels the current animation and resets config variables.
|
* Cancels the current animation and resets config variables.
|
||||||
*/
|
*/
|
||||||
public void reset() {
|
public void reset() {
|
||||||
duration = 0;
|
DEFAULT.copyTo(this);
|
||||||
userControlled = false;
|
targetState = null;
|
||||||
mAnimFlags = ANIM_ALL_COMPONENTS;
|
|
||||||
mPropertySetter = null;
|
|
||||||
mTargetState = null;
|
|
||||||
|
|
||||||
if (playbackController != null) {
|
if (playbackController != null) {
|
||||||
playbackController.getAnimationPlayer().cancel();
|
playbackController.getAnimationPlayer().cancel();
|
||||||
playbackController.dispatchOnCancel();
|
playbackController.dispatchOnCancel();
|
||||||
} else if (mCurrentAnimation != null) {
|
} else if (currentAnimation != null) {
|
||||||
mCurrentAnimation.setDuration(0);
|
currentAnimation.setDuration(0);
|
||||||
mCurrentAnimation.cancel();
|
currentAnimation.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentAnimation = null;
|
currentAnimation = null;
|
||||||
playbackController = null;
|
playbackController = null;
|
||||||
mChangeId ++;
|
changeId++;
|
||||||
}
|
|
||||||
|
|
||||||
public PropertySetter getPropertySetter(AnimatorSetBuilder builder) {
|
|
||||||
if (mPropertySetter == null) {
|
|
||||||
mPropertySetter = duration == 0 ? NO_ANIM_PROPERTY_SETTER
|
|
||||||
: new AnimatedPropertySetter(duration, builder);
|
|
||||||
}
|
|
||||||
return mPropertySetter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -629,51 +562,25 @@ public class LauncherStateManager {
|
|||||||
if (playbackController != null && playbackController.getTarget() == animation) {
|
if (playbackController != null && playbackController.getTarget() == animation) {
|
||||||
playbackController = null;
|
playbackController = null;
|
||||||
}
|
}
|
||||||
if (mCurrentAnimation == animation) {
|
if (currentAnimation == animation) {
|
||||||
mCurrentAnimation = null;
|
currentAnimation = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAnimation(AnimatorSet animation, LauncherState targetState) {
|
public void setAnimation(AnimatorSet animation, LauncherState targetState) {
|
||||||
mCurrentAnimation = animation;
|
currentAnimation = animation;
|
||||||
mTargetState = targetState;
|
this.targetState = targetState;
|
||||||
mCurrentAnimation.addListener(this);
|
currentAnimation.addListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @return Whether Overview is scaling as part of this animation. If this is the only
|
public void onAnimationStart(Animator animator) { }
|
||||||
* component (i.e. NON_ATOMIC_COMPONENT isn't included), then this scaling is happening
|
|
||||||
* atomically, rather than being part of a normal state animation. StateHandlers can use
|
|
||||||
* this to designate part of their animation that should scale with Overview.
|
|
||||||
*/
|
|
||||||
public boolean playAtomicOverviewScaleComponent() {
|
|
||||||
return hasAnimationFlag(PLAY_ATOMIC_OVERVIEW_SCALE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @return Whether this animation will play atomically at the same time as a different,
|
public void onAnimationCancel(Animator animator) { }
|
||||||
* user-controlled state transition. StateHandlers, which contribute to both animations, can
|
|
||||||
* use this to avoid animating the same properties in both animations, since they'd conflict
|
|
||||||
* with one another.
|
|
||||||
*/
|
|
||||||
public boolean onlyPlayAtomicComponent() {
|
|
||||||
return getAnimComponents() == PLAY_ATOMIC_OVERVIEW_SCALE
|
|
||||||
|| getAnimComponents() == PLAY_ATOMIC_OVERVIEW_PEEK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns true if the config and any of the provided component flags
|
public void onAnimationRepeat(Animator animator) { }
|
||||||
*/
|
|
||||||
public boolean hasAnimationFlag(@AnimationFlags int a) {
|
|
||||||
return (mAnimFlags & a) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Only the flags that determine which animation components to play.
|
|
||||||
*/
|
|
||||||
public @AnimationFlags int getAnimComponents() {
|
|
||||||
return mAnimFlags & ANIM_ALL_COMPONENTS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface StateHandler {
|
public interface StateHandler {
|
||||||
@@ -686,8 +593,8 @@ public class LauncherStateManager {
|
|||||||
/**
|
/**
|
||||||
* Sets the UI to {@param state} by animating any changes.
|
* Sets the UI to {@param state} by animating any changes.
|
||||||
*/
|
*/
|
||||||
void setStateWithAnimation(LauncherState toState,
|
void setStateWithAnimation(
|
||||||
AnimatorSetBuilder builder, AnimationConfig config);
|
LauncherState toState, StateAnimationConfig config, PendingAnimation animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface StateListener {
|
public interface StateListener {
|
||||||
|
|||||||
@@ -60,11 +60,10 @@ import android.view.accessibility.AccessibilityNodeInfo;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
|
import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
|
||||||
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
|
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
|
||||||
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
|
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
|
||||||
import com.android.launcher3.anim.Interpolators;
|
import com.android.launcher3.anim.Interpolators;
|
||||||
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.config.FeatureFlags;
|
import com.android.launcher3.config.FeatureFlags;
|
||||||
import com.android.launcher3.dot.FolderDotInfo;
|
import com.android.launcher3.dot.FolderDotInfo;
|
||||||
import com.android.launcher3.dragndrop.DragController;
|
import com.android.launcher3.dragndrop.DragController;
|
||||||
@@ -83,6 +82,7 @@ import com.android.launcher3.logging.UserEventDispatcher;
|
|||||||
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
|
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
|
||||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||||
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
|
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.launcher3.touch.WorkspaceTouchListener;
|
import com.android.launcher3.touch.WorkspaceTouchListener;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||||
@@ -1383,10 +1383,10 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||||||
* Sets the current workspace {@link LauncherState}, then animates the UI
|
* Sets the current workspace {@link LauncherState}, then animates the UI
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setStateWithAnimation(LauncherState toState,
|
public void setStateWithAnimation(
|
||||||
AnimatorSetBuilder builder, AnimationConfig config) {
|
LauncherState toState, StateAnimationConfig config, PendingAnimation animation) {
|
||||||
StateTransitionListener listener = new StateTransitionListener(toState);
|
StateTransitionListener listener = new StateTransitionListener(toState);
|
||||||
mStateTransitionAnimation.setStateWithAnimation(toState, builder, config);
|
mStateTransitionAnimation.setStateWithAnimation(toState, config, animation);
|
||||||
|
|
||||||
// Invalidate the pages now, so that we have the visible pages before the
|
// Invalidate the pages now, so that we have the visible pages before the
|
||||||
// animation is started
|
// animation is started
|
||||||
@@ -1399,7 +1399,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||||||
stepAnimator.addUpdateListener(listener);
|
stepAnimator.addUpdateListener(listener);
|
||||||
stepAnimator.setDuration(config.duration);
|
stepAnimator.setDuration(config.duration);
|
||||||
stepAnimator.addListener(listener);
|
stepAnimator.addListener(listener);
|
||||||
builder.play(stepAnimator);
|
animation.add(stepAnimator);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorkspaceStateTransitionAnimation getStateTransitionAnimation() {
|
public WorkspaceStateTransitionAnimation getStateTransitionAnimation() {
|
||||||
|
|||||||
@@ -22,27 +22,27 @@ import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
|
|||||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||||
import static com.android.launcher3.anim.Interpolators.ZOOM_OUT;
|
import static com.android.launcher3.anim.Interpolators.ZOOM_OUT;
|
||||||
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
|
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
|
||||||
import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SCRIM_PROGRESS;
|
import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SCRIM_PROGRESS;
|
||||||
import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SYSUI_PROGRESS;
|
import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SYSUI_PROGRESS;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.animation.Interpolator;
|
import android.view.animation.Interpolator;
|
||||||
|
|
||||||
import com.android.launcher3.LauncherState.PageAlphaProvider;
|
import com.android.launcher3.LauncherState.PageAlphaProvider;
|
||||||
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
|
||||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.anim.PropertySetter;
|
import com.android.launcher3.anim.PropertySetter;
|
||||||
import com.android.launcher3.graphics.WorkspaceAndHotseatScrim;
|
import com.android.launcher3.graphics.WorkspaceAndHotseatScrim;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the animations between each of the workspace states.
|
* Manages the animations between each of the workspace states.
|
||||||
@@ -60,13 +60,15 @@ public class WorkspaceStateTransitionAnimation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setState(LauncherState toState) {
|
public void setState(LauncherState toState) {
|
||||||
setWorkspaceProperty(toState, NO_ANIM_PROPERTY_SETTER, new AnimatorSetBuilder(),
|
setWorkspaceProperty(toState, NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig());
|
||||||
new AnimationConfig());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStateWithAnimation(LauncherState toState, AnimatorSetBuilder builder,
|
/**
|
||||||
AnimationConfig config) {
|
* @see com.android.launcher3.LauncherStateManager.StateHandler#setStateWithAnimation
|
||||||
setWorkspaceProperty(toState, config.getPropertySetter(builder), builder, config);
|
*/
|
||||||
|
public void setStateWithAnimation(
|
||||||
|
LauncherState toState, StateAnimationConfig config, PendingAnimation animation) {
|
||||||
|
setWorkspaceProperty(toState, animation, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getFinalScale() {
|
public float getFinalScale() {
|
||||||
@@ -77,7 +79,7 @@ public class WorkspaceStateTransitionAnimation {
|
|||||||
* Starts a transition animation for the workspace.
|
* Starts a transition animation for the workspace.
|
||||||
*/
|
*/
|
||||||
private void setWorkspaceProperty(LauncherState state, PropertySetter propertySetter,
|
private void setWorkspaceProperty(LauncherState state, PropertySetter propertySetter,
|
||||||
AnimatorSetBuilder builder, AnimationConfig config) {
|
StateAnimationConfig config) {
|
||||||
ScaleAndTranslation scaleAndTranslation = state.getWorkspaceScaleAndTranslation(mLauncher);
|
ScaleAndTranslation scaleAndTranslation = state.getWorkspaceScaleAndTranslation(mLauncher);
|
||||||
ScaleAndTranslation hotseatScaleAndTranslation = state.getHotseatScaleAndTranslation(
|
ScaleAndTranslation hotseatScaleAndTranslation = state.getHotseatScaleAndTranslation(
|
||||||
mLauncher);
|
mLauncher);
|
||||||
@@ -87,11 +89,11 @@ public class WorkspaceStateTransitionAnimation {
|
|||||||
final int childCount = mWorkspace.getChildCount();
|
final int childCount = mWorkspace.getChildCount();
|
||||||
for (int i = 0; i < childCount; i++) {
|
for (int i = 0; i < childCount; i++) {
|
||||||
applyChildState(state, (CellLayout) mWorkspace.getChildAt(i), i, pageAlphaProvider,
|
applyChildState(state, (CellLayout) mWorkspace.getChildAt(i), i, pageAlphaProvider,
|
||||||
propertySetter, builder, config);
|
propertySetter, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
int elements = state.getVisibleElements(mLauncher);
|
int elements = state.getVisibleElements(mLauncher);
|
||||||
Interpolator fadeInterpolator = builder.getInterpolator(ANIM_WORKSPACE_FADE,
|
Interpolator fadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
|
||||||
pageAlphaProvider.interpolator);
|
pageAlphaProvider.interpolator);
|
||||||
boolean playAtomicComponent = config.playAtomicOverviewScaleComponent();
|
boolean playAtomicComponent = config.playAtomicOverviewScaleComponent();
|
||||||
Hotseat hotseat = mWorkspace.getHotseat();
|
Hotseat hotseat = mWorkspace.getHotseat();
|
||||||
@@ -99,7 +101,7 @@ public class WorkspaceStateTransitionAnimation {
|
|||||||
AllAppsContainerView qsbScaleView = mLauncher.getAppsView();
|
AllAppsContainerView qsbScaleView = mLauncher.getAppsView();
|
||||||
View qsbView = qsbScaleView.getSearchView();
|
View qsbView = qsbScaleView.getSearchView();
|
||||||
if (playAtomicComponent) {
|
if (playAtomicComponent) {
|
||||||
Interpolator scaleInterpolator = builder.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
|
Interpolator scaleInterpolator = config.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
|
||||||
propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, scaleInterpolator);
|
propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, scaleInterpolator);
|
||||||
|
|
||||||
if (!hotseat.getRotationMode().isTransposed) {
|
if (!hotseat.getRotationMode().isTransposed) {
|
||||||
@@ -107,7 +109,7 @@ public class WorkspaceStateTransitionAnimation {
|
|||||||
setPivotToScaleWithWorkspace(qsbScaleView);
|
setPivotToScaleWithWorkspace(qsbScaleView);
|
||||||
}
|
}
|
||||||
float hotseatScale = hotseatScaleAndTranslation.scale;
|
float hotseatScale = hotseatScaleAndTranslation.scale;
|
||||||
Interpolator hotseatScaleInterpolator = builder.getInterpolator(ANIM_HOTSEAT_SCALE,
|
Interpolator hotseatScaleInterpolator = config.getInterpolator(ANIM_HOTSEAT_SCALE,
|
||||||
scaleInterpolator);
|
scaleInterpolator);
|
||||||
propertySetter.setFloat(hotseat, SCALE_PROPERTY, hotseatScale,
|
propertySetter.setFloat(hotseat, SCALE_PROPERTY, hotseatScale,
|
||||||
hotseatScaleInterpolator);
|
hotseatScaleInterpolator);
|
||||||
@@ -127,13 +129,13 @@ public class WorkspaceStateTransitionAnimation {
|
|||||||
|
|
||||||
Interpolator translationInterpolator = !playAtomicComponent
|
Interpolator translationInterpolator = !playAtomicComponent
|
||||||
? LINEAR
|
? LINEAR
|
||||||
: builder.getInterpolator(ANIM_WORKSPACE_TRANSLATE, ZOOM_OUT);
|
: config.getInterpolator(ANIM_WORKSPACE_TRANSLATE, ZOOM_OUT);
|
||||||
propertySetter.setFloat(mWorkspace, VIEW_TRANSLATE_X,
|
propertySetter.setFloat(mWorkspace, VIEW_TRANSLATE_X,
|
||||||
scaleAndTranslation.translationX, translationInterpolator);
|
scaleAndTranslation.translationX, translationInterpolator);
|
||||||
propertySetter.setFloat(mWorkspace, VIEW_TRANSLATE_Y,
|
propertySetter.setFloat(mWorkspace, VIEW_TRANSLATE_Y,
|
||||||
scaleAndTranslation.translationY, translationInterpolator);
|
scaleAndTranslation.translationY, translationInterpolator);
|
||||||
|
|
||||||
Interpolator hotseatTranslationInterpolator = builder.getInterpolator(
|
Interpolator hotseatTranslationInterpolator = config.getInterpolator(
|
||||||
ANIM_HOTSEAT_TRANSLATE, translationInterpolator);
|
ANIM_HOTSEAT_TRANSLATE, translationInterpolator);
|
||||||
propertySetter.setFloat(hotseat, VIEW_TRANSLATE_Y,
|
propertySetter.setFloat(hotseat, VIEW_TRANSLATE_Y,
|
||||||
hotseatScaleAndTranslation.translationY, hotseatTranslationInterpolator);
|
hotseatScaleAndTranslation.translationY, hotseatTranslationInterpolator);
|
||||||
@@ -166,12 +168,12 @@ public class WorkspaceStateTransitionAnimation {
|
|||||||
|
|
||||||
public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
|
public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
|
||||||
applyChildState(state, cl, childIndex, state.getWorkspacePageAlphaProvider(mLauncher),
|
applyChildState(state, cl, childIndex, state.getWorkspacePageAlphaProvider(mLauncher),
|
||||||
NO_ANIM_PROPERTY_SETTER, new AnimatorSetBuilder(), new AnimationConfig());
|
NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyChildState(LauncherState state, CellLayout cl, int childIndex,
|
private void applyChildState(LauncherState state, CellLayout cl, int childIndex,
|
||||||
PageAlphaProvider pageAlphaProvider, PropertySetter propertySetter,
|
PageAlphaProvider pageAlphaProvider, PropertySetter propertySetter,
|
||||||
AnimatorSetBuilder builder, AnimationConfig config) {
|
StateAnimationConfig config) {
|
||||||
float pageAlpha = pageAlphaProvider.getPageAlpha(childIndex);
|
float pageAlpha = pageAlphaProvider.getPageAlpha(childIndex);
|
||||||
int drawableAlpha = Math.round(pageAlpha * (state.hasWorkspacePageBackground ? 255 : 0));
|
int drawableAlpha = Math.round(pageAlpha * (state.hasWorkspacePageBackground ? 255 : 0));
|
||||||
|
|
||||||
@@ -181,7 +183,7 @@ public class WorkspaceStateTransitionAnimation {
|
|||||||
DRAWABLE_ALPHA, drawableAlpha, ZOOM_OUT);
|
DRAWABLE_ALPHA, drawableAlpha, ZOOM_OUT);
|
||||||
}
|
}
|
||||||
if (config.playAtomicOverviewScaleComponent()) {
|
if (config.playAtomicOverviewScaleComponent()) {
|
||||||
Interpolator fadeInterpolator = builder.getInterpolator(ANIM_WORKSPACE_FADE,
|
Interpolator fadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
|
||||||
pageAlphaProvider.interpolator);
|
pageAlphaProvider.interpolator);
|
||||||
propertySetter.setFloat(cl.getShortcutsAndWidgets(), VIEW_ALPHA,
|
propertySetter.setFloat(cl.getShortcutsAndWidgets(), VIEW_ALPHA,
|
||||||
pageAlpha, fadeInterpolator);
|
pageAlpha, fadeInterpolator);
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
|
|||||||
import static com.android.launcher3.LauncherState.APPS_VIEW_ITEM_MASK;
|
import static com.android.launcher3.LauncherState.APPS_VIEW_ITEM_MASK;
|
||||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||||
import static com.android.launcher3.LauncherState.VERTICAL_SWIPE_INDICATOR;
|
import static com.android.launcher3.LauncherState.VERTICAL_SWIPE_INDICATOR;
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_HEADER_FADE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
|
|
||||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||||
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
|
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_HEADER_FADE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
|
||||||
import static com.android.launcher3.util.SystemUiController.UI_STATE_ALL_APPS;
|
import static com.android.launcher3.util.SystemUiController.UI_STATE_ALL_APPS;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
@@ -24,12 +24,12 @@ import com.android.launcher3.DeviceProfile;
|
|||||||
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
|
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
|
||||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.anim.PropertySetter;
|
import com.android.launcher3.anim.PropertySetter;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
import com.android.launcher3.util.Themes;
|
import com.android.launcher3.util.Themes;
|
||||||
import com.android.launcher3.views.ScrimView;
|
import com.android.launcher3.views.ScrimView;
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ public class AllAppsTransitionController implements StateHandler, OnDeviceProfil
|
|||||||
* @param progress value between 0 and 1, 0 shows all apps and 1 shows workspace
|
* @param progress value between 0 and 1, 0 shows all apps and 1 shows workspace
|
||||||
*
|
*
|
||||||
* @see #setState(LauncherState)
|
* @see #setState(LauncherState)
|
||||||
* @see #setStateWithAnimation(LauncherState, AnimatorSetBuilder, AnimationConfig)
|
* @see #setStateWithAnimation(LauncherState, StateAnimationConfig, PendingAnimation)
|
||||||
*/
|
*/
|
||||||
public void setProgress(float progress) {
|
public void setProgress(float progress) {
|
||||||
mProgress = progress;
|
mProgress = progress;
|
||||||
@@ -143,7 +143,7 @@ public class AllAppsTransitionController implements StateHandler, OnDeviceProfil
|
|||||||
@Override
|
@Override
|
||||||
public void setState(LauncherState state) {
|
public void setState(LauncherState state) {
|
||||||
setProgress(state.getVerticalProgress(mLauncher));
|
setProgress(state.getVerticalProgress(mLauncher));
|
||||||
setAlphas(state, null, new AnimatorSetBuilder());
|
setAlphas(state, new StateAnimationConfig(), NO_ANIM_PROPERTY_SETTER);
|
||||||
onProgressAnimationEnd();
|
onProgressAnimationEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ public class AllAppsTransitionController implements StateHandler, OnDeviceProfil
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setStateWithAnimation(LauncherState toState,
|
public void setStateWithAnimation(LauncherState toState,
|
||||||
AnimatorSetBuilder builder, AnimationConfig config) {
|
StateAnimationConfig config, PendingAnimation builder) {
|
||||||
float targetProgress = toState.getVerticalProgress(mLauncher);
|
float targetProgress = toState.getVerticalProgress(mLauncher);
|
||||||
if (Float.compare(mProgress, targetProgress) == 0) {
|
if (Float.compare(mProgress, targetProgress) == 0) {
|
||||||
setAlphas(toState, config, builder);
|
setAlphas(toState, config, builder);
|
||||||
@@ -168,14 +168,14 @@ public class AllAppsTransitionController implements StateHandler, OnDeviceProfil
|
|||||||
}
|
}
|
||||||
|
|
||||||
Interpolator interpolator = config.userControlled ? LINEAR : toState == OVERVIEW
|
Interpolator interpolator = config.userControlled ? LINEAR : toState == OVERVIEW
|
||||||
? builder.getInterpolator(ANIM_OVERVIEW_SCALE, FAST_OUT_SLOW_IN)
|
? config.getInterpolator(ANIM_OVERVIEW_SCALE, FAST_OUT_SLOW_IN)
|
||||||
: FAST_OUT_SLOW_IN;
|
: FAST_OUT_SLOW_IN;
|
||||||
|
|
||||||
Animator anim = createSpringAnimation(mProgress, targetProgress);
|
Animator anim = createSpringAnimation(mProgress, targetProgress);
|
||||||
anim.setDuration(config.duration);
|
anim.setDuration(config.duration);
|
||||||
anim.setInterpolator(builder.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
|
anim.setInterpolator(config.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
|
||||||
anim.addListener(getProgressAnimatorListener());
|
anim.addListener(getProgressAnimatorListener());
|
||||||
|
builder.add(anim);
|
||||||
builder.play(anim);
|
|
||||||
|
|
||||||
setAlphas(toState, config, builder);
|
setAlphas(toState, config, builder);
|
||||||
}
|
}
|
||||||
@@ -184,21 +184,18 @@ public class AllAppsTransitionController implements StateHandler, OnDeviceProfil
|
|||||||
return ObjectAnimator.ofFloat(this, ALL_APPS_PROGRESS, progressValues);
|
return ObjectAnimator.ofFloat(this, ALL_APPS_PROGRESS, progressValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAlphas(LauncherState toState, AnimationConfig config,
|
/**
|
||||||
AnimatorSetBuilder builder) {
|
* Updates the property for the provided state
|
||||||
setAlphas(toState.getVisibleElements(mLauncher), config, builder);
|
*/
|
||||||
}
|
public void setAlphas(LauncherState state, StateAnimationConfig config, PropertySetter setter) {
|
||||||
|
int visibleElements = state.getVisibleElements(mLauncher);
|
||||||
public void setAlphas(int visibleElements, AnimationConfig config, AnimatorSetBuilder builder) {
|
|
||||||
PropertySetter setter = config == null ? NO_ANIM_PROPERTY_SETTER
|
|
||||||
: config.getPropertySetter(builder);
|
|
||||||
boolean hasHeaderExtra = (visibleElements & ALL_APPS_HEADER_EXTRA) != 0;
|
boolean hasHeaderExtra = (visibleElements & ALL_APPS_HEADER_EXTRA) != 0;
|
||||||
boolean hasAllAppsContent = (visibleElements & ALL_APPS_CONTENT) != 0;
|
boolean hasAllAppsContent = (visibleElements & ALL_APPS_CONTENT) != 0;
|
||||||
|
|
||||||
boolean hasAnyVisibleItem = (visibleElements & APPS_VIEW_ITEM_MASK) != 0;
|
boolean hasAnyVisibleItem = (visibleElements & APPS_VIEW_ITEM_MASK) != 0;
|
||||||
|
|
||||||
Interpolator allAppsFade = builder.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR);
|
Interpolator allAppsFade = config.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR);
|
||||||
Interpolator headerFade = builder.getInterpolator(ANIM_ALL_APPS_HEADER_FADE, allAppsFade);
|
Interpolator headerFade = config.getInterpolator(ANIM_ALL_APPS_HEADER_FADE, allAppsFade);
|
||||||
setter.setViewAlpha(mAppsView.getContentView(), hasAllAppsContent ? 1 : 0, allAppsFade);
|
setter.setViewAlpha(mAppsView.getContentView(), hasAllAppsContent ? 1 : 0, allAppsFade);
|
||||||
setter.setViewAlpha(mAppsView.getScrollBar(), hasAllAppsContent ? 1 : 0, allAppsFade);
|
setter.setViewAlpha(mAppsView.getScrollBar(), hasAllAppsContent ? 1 : 0, allAppsFade);
|
||||||
mAppsView.getFloatingHeaderView().setContentVisibility(hasHeaderExtra, hasAllAppsContent,
|
mAppsView.getFloatingHeaderView().setContentVisibility(hasHeaderExtra, hasAllAppsContent,
|
||||||
|
|||||||
@@ -64,13 +64,6 @@ public class AnimatorPlaybackController implements ValueAnimator.AnimatorUpdateL
|
|||||||
return new AnimatorPlaybackController(anim, duration, childAnims);
|
return new AnimatorPlaybackController(anim, duration, childAnims);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AnimatorPlaybackController wrap(PendingAnimation anim, long duration) {
|
|
||||||
/**
|
|
||||||
* TODO: use {@link AnimatorSet#setCurrentPlayTime(long)} once b/68382377 is fixed.
|
|
||||||
*/
|
|
||||||
return new AnimatorPlaybackController(anim.anim, duration, anim.animHolders);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final FloatProperty<ValueAnimator> CURRENT_PLAY_TIME =
|
private static final FloatProperty<ValueAnimator> CURRENT_PLAY_TIME =
|
||||||
new FloatProperty<ValueAnimator>("current-play-time") {
|
new FloatProperty<ValueAnimator>("current-play-time") {
|
||||||
@Override
|
@Override
|
||||||
@@ -96,8 +89,8 @@ public class AnimatorPlaybackController implements ValueAnimator.AnimatorUpdateL
|
|||||||
protected boolean mTargetCancelled = false;
|
protected boolean mTargetCancelled = false;
|
||||||
protected Runnable mOnCancelRunnable;
|
protected Runnable mOnCancelRunnable;
|
||||||
|
|
||||||
private AnimatorPlaybackController(
|
/** package private */
|
||||||
AnimatorSet anim, long duration, ArrayList<Holder> childAnims) {
|
AnimatorPlaybackController(AnimatorSet anim, long duration, ArrayList<Holder> childAnims) {
|
||||||
mAnim = anim;
|
mAnim = anim;
|
||||||
mDuration = duration;
|
mDuration = duration;
|
||||||
|
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2017 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.anim;
|
|
||||||
|
|
||||||
import android.animation.Animator;
|
|
||||||
import android.animation.AnimatorSet;
|
|
||||||
import android.util.SparseArray;
|
|
||||||
import android.view.animation.Interpolator;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class for building animator set
|
|
||||||
*/
|
|
||||||
public class AnimatorSetBuilder {
|
|
||||||
|
|
||||||
public static final int ANIM_VERTICAL_PROGRESS = 0;
|
|
||||||
public static final int ANIM_WORKSPACE_SCALE = 1;
|
|
||||||
public static final int ANIM_WORKSPACE_TRANSLATE = 2;
|
|
||||||
public static final int ANIM_WORKSPACE_FADE = 3;
|
|
||||||
public static final int ANIM_HOTSEAT_SCALE = 4;
|
|
||||||
public static final int ANIM_HOTSEAT_TRANSLATE = 5;
|
|
||||||
public static final int ANIM_OVERVIEW_SCALE = 6;
|
|
||||||
public static final int ANIM_OVERVIEW_TRANSLATE_X = 7;
|
|
||||||
public static final int ANIM_OVERVIEW_TRANSLATE_Y = 8;
|
|
||||||
public static final int ANIM_OVERVIEW_FADE = 9;
|
|
||||||
public static final int ANIM_ALL_APPS_FADE = 10;
|
|
||||||
public static final int ANIM_OVERVIEW_SCRIM_FADE = 11;
|
|
||||||
public static final int ANIM_ALL_APPS_HEADER_FADE = 12; // e.g. predictions
|
|
||||||
|
|
||||||
protected final ArrayList<Animator> mAnims = new ArrayList<>();
|
|
||||||
|
|
||||||
private final SparseArray<Interpolator> mInterpolators = new SparseArray<>();
|
|
||||||
|
|
||||||
public void play(Animator anim) {
|
|
||||||
mAnims.add(anim);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AnimatorSet build() {
|
|
||||||
AnimatorSet anim = new AnimatorSet();
|
|
||||||
anim.playTogether(mAnims);
|
|
||||||
return anim;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Interpolator getInterpolator(int animId, Interpolator fallback) {
|
|
||||||
return mInterpolators.get(animId, fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInterpolator(int animId, Interpolator interpolator) {
|
|
||||||
mInterpolators.put(animId, interpolator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,9 +19,12 @@ import static com.android.launcher3.anim.AnimatorPlaybackController.addAnimation
|
|||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
import android.animation.TimeInterpolator;
|
import android.animation.TimeInterpolator;
|
||||||
import android.annotation.TargetApi;
|
import android.animation.ValueAnimator;
|
||||||
import android.os.Build;
|
import android.util.FloatProperty;
|
||||||
|
import android.util.IntProperty;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import com.android.launcher3.anim.AnimatorPlaybackController.Holder;
|
import com.android.launcher3.anim.AnimatorPlaybackController.Holder;
|
||||||
|
|
||||||
@@ -37,14 +40,24 @@ import java.util.function.Consumer;
|
|||||||
*
|
*
|
||||||
* TODO: Find a better name
|
* TODO: Find a better name
|
||||||
*/
|
*/
|
||||||
@TargetApi(Build.VERSION_CODES.O)
|
public class PendingAnimation implements PropertySetter {
|
||||||
public class PendingAnimation {
|
|
||||||
|
|
||||||
private final ArrayList<Consumer<EndState>> mEndListeners = new ArrayList<>();
|
private final ArrayList<Consumer<EndState>> mEndListeners = new ArrayList<>();
|
||||||
|
|
||||||
/** package private **/
|
private final ArrayList<Holder> mAnimHolders = new ArrayList<>();
|
||||||
final AnimatorSet anim = new AnimatorSet();
|
private final AnimatorSet mAnim;
|
||||||
final ArrayList<Holder> animHolders = new ArrayList<>();
|
private final long mDuration;
|
||||||
|
|
||||||
|
private ValueAnimator mProgressAnimator;
|
||||||
|
|
||||||
|
public PendingAnimation(long duration) {
|
||||||
|
this(duration, new AnimatorSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PendingAnimation(long duration, AnimatorSet targetSet) {
|
||||||
|
mDuration = duration;
|
||||||
|
mAnim = targetSet;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility method to sent an interpolator on an animation and add it to the list
|
* Utility method to sent an interpolator on an animation and add it to the list
|
||||||
@@ -63,8 +76,8 @@ public class PendingAnimation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void add(Animator a, SpringProperty springProperty) {
|
public void add(Animator a, SpringProperty springProperty) {
|
||||||
anim.play(a);
|
mAnim.play(a);
|
||||||
addAnimationHoldersRecur(a, springProperty, animHolders);
|
addAnimationHoldersRecur(a, springProperty, mAnimHolders);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish(boolean isSuccess, int logAction) {
|
public void finish(boolean isSuccess, int logAction) {
|
||||||
@@ -74,6 +87,67 @@ public class PendingAnimation {
|
|||||||
mEndListeners.clear();
|
mEndListeners.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
|
||||||
|
if (view == null || view.getAlpha() == alpha) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, alpha);
|
||||||
|
anim.addListener(new AlphaUpdateListener(view));
|
||||||
|
anim.setDuration(mDuration).setInterpolator(interpolator);
|
||||||
|
add(anim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> void setFloat(T target, FloatProperty<T> property, float value,
|
||||||
|
TimeInterpolator interpolator) {
|
||||||
|
if (property.get(target) == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Animator anim = ObjectAnimator.ofFloat(target, property, value);
|
||||||
|
anim.setDuration(mDuration).setInterpolator(interpolator);
|
||||||
|
add(anim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> void setInt(T target, IntProperty<T> property, int value,
|
||||||
|
TimeInterpolator interpolator) {
|
||||||
|
if (property.get(target) == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Animator anim = ObjectAnimator.ofInt(target, property, value);
|
||||||
|
anim.setDuration(mDuration).setInterpolator(interpolator);
|
||||||
|
add(anim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a callback to be run on every frame of the animation
|
||||||
|
*/
|
||||||
|
public void addOnFrameCallback(Runnable runnable) {
|
||||||
|
if (mProgressAnimator == null) {
|
||||||
|
mProgressAnimator = ValueAnimator.ofFloat(0, 1).setDuration(mDuration);
|
||||||
|
add(mProgressAnimator);
|
||||||
|
}
|
||||||
|
|
||||||
|
mProgressAnimator.addUpdateListener(anim -> runnable.run());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnimatorSet getAnim() {
|
||||||
|
return mAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a controller for this animation
|
||||||
|
*/
|
||||||
|
public AnimatorPlaybackController createPlaybackController() {
|
||||||
|
return new AnimatorPlaybackController(mAnim, mDuration, mAnimHolders);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a listener of receiving the end state.
|
||||||
|
* Note that the listeners are called as a result of calling {@link #finish(boolean, int)}
|
||||||
|
* and not automatically
|
||||||
|
*/
|
||||||
public void addEndListener(Consumer<EndState> listener) {
|
public void addEndListener(Consumer<EndState> listener) {
|
||||||
mEndListeners.add(listener);
|
mEndListeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package com.android.launcher3.anim;
|
package com.android.launcher3.anim;
|
||||||
|
|
||||||
import android.animation.Animator;
|
|
||||||
import android.animation.ObjectAnimator;
|
|
||||||
import android.animation.TimeInterpolator;
|
import android.animation.TimeInterpolator;
|
||||||
import android.util.FloatProperty;
|
import android.util.FloatProperty;
|
||||||
import android.util.IntProperty;
|
import android.util.IntProperty;
|
||||||
@@ -26,68 +24,35 @@ import android.view.View;
|
|||||||
/**
|
/**
|
||||||
* Utility class for setting a property with or without animation
|
* Utility class for setting a property with or without animation
|
||||||
*/
|
*/
|
||||||
public class PropertySetter {
|
public interface PropertySetter {
|
||||||
|
|
||||||
public static final PropertySetter NO_ANIM_PROPERTY_SETTER = new PropertySetter();
|
PropertySetter NO_ANIM_PROPERTY_SETTER = new PropertySetter() { };
|
||||||
|
|
||||||
public void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
|
/**
|
||||||
|
* Sets the view alpha using the provided interpolator.
|
||||||
|
* Unlike {@link #setFloat}, this also updates the visibility of the view as alpha changes
|
||||||
|
* between zero and non-zero.
|
||||||
|
*/
|
||||||
|
default void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
|
||||||
if (view != null) {
|
if (view != null) {
|
||||||
view.setAlpha(alpha);
|
view.setAlpha(alpha);
|
||||||
AlphaUpdateListener.updateVisibility(view);
|
AlphaUpdateListener.updateVisibility(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void setFloat(T target, FloatProperty<T> property, float value,
|
/**
|
||||||
|
* Updates the float property of the target using the provided interpolator
|
||||||
|
*/
|
||||||
|
default <T> void setFloat(T target, FloatProperty<T> property, float value,
|
||||||
TimeInterpolator interpolator) {
|
TimeInterpolator interpolator) {
|
||||||
property.setValue(target, value);
|
property.setValue(target, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void setInt(T target, IntProperty<T> property, int value,
|
/**
|
||||||
|
* Updates the int property of the target using the provided interpolator
|
||||||
|
*/
|
||||||
|
default <T> void setInt(T target, IntProperty<T> property, int value,
|
||||||
TimeInterpolator interpolator) {
|
TimeInterpolator interpolator) {
|
||||||
property.setValue(target, value);
|
property.setValue(target, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AnimatedPropertySetter extends PropertySetter {
|
|
||||||
|
|
||||||
private final long mDuration;
|
|
||||||
private final AnimatorSetBuilder mStateAnimator;
|
|
||||||
|
|
||||||
public AnimatedPropertySetter(long duration, AnimatorSetBuilder builder) {
|
|
||||||
mDuration = duration;
|
|
||||||
mStateAnimator = builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
|
|
||||||
if (view == null || view.getAlpha() == alpha) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, alpha);
|
|
||||||
anim.addListener(new AlphaUpdateListener(view));
|
|
||||||
anim.setDuration(mDuration).setInterpolator(interpolator);
|
|
||||||
mStateAnimator.play(anim);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> void setFloat(T target, FloatProperty<T> property, float value,
|
|
||||||
TimeInterpolator interpolator) {
|
|
||||||
if (property.get(target) == value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Animator anim = ObjectAnimator.ofFloat(target, property, value);
|
|
||||||
anim.setDuration(mDuration).setInterpolator(interpolator);
|
|
||||||
mStateAnimator.play(anim);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> void setInt(T target, IntProperty<T> property, int value,
|
|
||||||
TimeInterpolator interpolator) {
|
|
||||||
if (property.get(target) == value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Animator anim = ObjectAnimator.ofInt(target, property, value);
|
|
||||||
anim.setDuration(mDuration).setInterpolator(interpolator);
|
|
||||||
mStateAnimator.play(anim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,11 +100,11 @@ public final class FeatureFlags {
|
|||||||
"Suggests folder names instead of blank text.");
|
"Suggests folder names instead of blank text.");
|
||||||
|
|
||||||
public static final BooleanFlag APP_SEARCH_IMPROVEMENTS = new DeviceFlag(
|
public static final BooleanFlag APP_SEARCH_IMPROVEMENTS = new DeviceFlag(
|
||||||
"APP_SEARCH_IMPROVEMENTS", false,
|
"APP_SEARCH_IMPROVEMENTS", true,
|
||||||
"Adds localized title and keyword search and ranking");
|
"Adds localized title and keyword search and ranking");
|
||||||
|
|
||||||
public static final BooleanFlag ENABLE_PREDICTION_DISMISS = new DeviceFlag(
|
public static final BooleanFlag ENABLE_PREDICTION_DISMISS = getDebugFlag(
|
||||||
"ENABLE_PREDICTION_DISMISS", true, "Allow option to dimiss apps from predicted list");
|
"ENABLE_PREDICTION_DISMISS", false, "Allow option to dimiss apps from predicted list");
|
||||||
|
|
||||||
public static final BooleanFlag ENABLE_QUICK_CAPTURE_GESTURE = getDebugFlag(
|
public static final BooleanFlag ENABLE_QUICK_CAPTURE_GESTURE = getDebugFlag(
|
||||||
"ENABLE_QUICK_CAPTURE_GESTURE", true, "Swipe from right to left to quick capture");
|
"ENABLE_QUICK_CAPTURE_GESTURE", true, "Swipe from right to left to quick capture");
|
||||||
@@ -117,11 +117,11 @@ public final class FeatureFlags {
|
|||||||
"ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
|
"ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
|
||||||
"Allow Launcher to handle nav bar gestures while Assistant is running over it");
|
"Allow Launcher to handle nav bar gestures while Assistant is running over it");
|
||||||
|
|
||||||
public static final BooleanFlag ENABLE_HYBRID_HOTSEAT = new DeviceFlag(
|
public static final BooleanFlag ENABLE_HYBRID_HOTSEAT = getDebugFlag(
|
||||||
"ENABLE_HYBRID_HOTSEAT", false, "Fill gaps in hotseat with predicted apps");
|
"ENABLE_HYBRID_HOTSEAT", false, "Fill gaps in hotseat with predicted apps");
|
||||||
|
|
||||||
public static final BooleanFlag HOTSEAT_MIGRATE_NEW_PAGE = new DeviceFlag(
|
public static final BooleanFlag HOTSEAT_MIGRATE_NEW_PAGE = getDebugFlag(
|
||||||
"HOTSEAT_MIGRATE_NEW_PAGE", true,
|
"HOTSEAT_MIGRATE_NEW_PAGE", false,
|
||||||
"Migrates hotseat to a new workspace page instead of same page");
|
"Migrates hotseat to a new workspace page instead of same page");
|
||||||
|
|
||||||
public static final BooleanFlag ENABLE_DEEP_SHORTCUT_ICON_CACHE = getDebugFlag(
|
public static final BooleanFlag ENABLE_DEEP_SHORTCUT_ICON_CACHE = getDebugFlag(
|
||||||
@@ -131,13 +131,18 @@ public final class FeatureFlags {
|
|||||||
"MULTI_DB_GRID_MIRATION_ALGO", false, "Use the multi-db grid migration algorithm");
|
"MULTI_DB_GRID_MIRATION_ALGO", false, "Use the multi-db grid migration algorithm");
|
||||||
|
|
||||||
public static final BooleanFlag ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER = getDebugFlag(
|
public static final BooleanFlag ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER = getDebugFlag(
|
||||||
"ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER", true,
|
"ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER", true, "Show launcher preview in grid picker");
|
||||||
"Show launcher preview in grid picker");
|
|
||||||
|
public static final BooleanFlag USE_SURFACE_VIEW_FOR_GRID_PREVIEW = getDebugFlag(
|
||||||
|
"USE_SURFACE_VIEW_FOR_GRID_PREVIEW", false, "Use surface view for grid preview");
|
||||||
|
|
||||||
public static final BooleanFlag ENABLE_OVERVIEW_ACTIONS = getDebugFlag(
|
public static final BooleanFlag ENABLE_OVERVIEW_ACTIONS = getDebugFlag(
|
||||||
"ENABLE_OVERVIEW_ACTIONS", true, "Show app actions instead of the shelf in Overview."
|
"ENABLE_OVERVIEW_ACTIONS", true, "Show app actions instead of the shelf in Overview."
|
||||||
+ " As part of this decoupling, also distinguish swipe up from nav bar vs above it.");
|
+ " As part of this decoupling, also distinguish swipe up from nav bar vs above it.");
|
||||||
|
|
||||||
|
public static final BooleanFlag ENABLE_SELECT_MODE = getDebugFlag(
|
||||||
|
"ENABLE_SELECT_MODE", true, "Show Select Mode button in Overview Actions");
|
||||||
|
|
||||||
public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag(
|
public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag(
|
||||||
"ENABLE_DATABASE_RESTORE", true,
|
"ENABLE_DATABASE_RESTORE", true,
|
||||||
"Enable database restore when new restore session is created");
|
"Enable database restore when new restore session is created");
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.android.launcher3.graphics;
|
package com.android.launcher3.graphics;
|
||||||
|
|
||||||
|
import static com.android.launcher3.config.FeatureFlags.USE_SURFACE_VIEW_FOR_GRID_PREVIEW;
|
||||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||||
|
|
||||||
import android.content.ContentProvider;
|
import android.content.ContentProvider;
|
||||||
@@ -19,6 +20,7 @@ import android.util.Xml;
|
|||||||
import com.android.launcher3.InvariantDeviceProfile;
|
import com.android.launcher3.InvariantDeviceProfile;
|
||||||
import com.android.launcher3.InvariantDeviceProfile.GridOption;
|
import com.android.launcher3.InvariantDeviceProfile.GridOption;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
|
import com.android.launcher3.uioverrides.PreviewSurfaceRenderer;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
@@ -62,6 +64,11 @@ public class GridOptionsProvider extends ContentProvider {
|
|||||||
private static final String KEY_PREVIEW = "preview";
|
private static final String KEY_PREVIEW = "preview";
|
||||||
private static final String MIME_TYPE_PNG = "image/png";
|
private static final String MIME_TYPE_PNG = "image/png";
|
||||||
|
|
||||||
|
private static final String METHOD_GET_PREVIEW = "get_preview";
|
||||||
|
private static final String METADATA_KEY_PREVIEW_VERSION = "preview_version";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static final PipeDataWriter<Future<Bitmap>> BITMAP_WRITER =
|
public static final PipeDataWriter<Future<Bitmap>> BITMAP_WRITER =
|
||||||
new PipeDataWriter<Future<Bitmap>>() {
|
new PipeDataWriter<Future<Bitmap>>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -98,6 +105,10 @@ public class GridOptionsProvider extends ContentProvider {
|
|||||||
.add(KEY_IS_DEFAULT, idp.numColumns == gridOption.numColumns
|
.add(KEY_IS_DEFAULT, idp.numColumns == gridOption.numColumns
|
||||||
&& idp.numRows == gridOption.numRows);
|
&& idp.numRows == gridOption.numRows);
|
||||||
}
|
}
|
||||||
|
Bundle metadata = new Bundle();
|
||||||
|
metadata.putString(METADATA_KEY_PREVIEW_VERSION,
|
||||||
|
USE_SURFACE_VIEW_FOR_GRID_PREVIEW.get() ? "V2" : "V1");
|
||||||
|
cursor.setExtras(metadata);
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,4 +199,14 @@ public class GridOptionsProvider extends ContentProvider {
|
|||||||
throw new FileNotFoundException(e.getMessage());
|
throw new FileNotFoundException(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle call(String method, String arg, Bundle extras) {
|
||||||
|
if (!METHOD_GET_PREVIEW.equals(method)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviewSurfaceRenderer.render(getContext(), extras);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,6 +262,13 @@ public class LauncherPreviewRenderer implements Callable<Bitmap> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Populate preview and render it. */
|
||||||
|
public View getRenderedView() {
|
||||||
|
MainThreadRenderer renderer = new MainThreadRenderer(mContext);
|
||||||
|
renderer.populate();
|
||||||
|
return renderer.mRootView;
|
||||||
|
}
|
||||||
|
|
||||||
private class MainThreadRenderer extends ContextThemeWrapper
|
private class MainThreadRenderer extends ContextThemeWrapper
|
||||||
implements ActivityContext, WorkspaceLayoutManager, LayoutInflater.Factory2 {
|
implements ActivityContext, WorkspaceLayoutManager, LayoutInflater.Factory2 {
|
||||||
|
|
||||||
@@ -388,7 +395,7 @@ public class LauncherPreviewRenderer implements Callable<Bitmap> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderScreenShot(Canvas canvas) {
|
private void populate() {
|
||||||
if (ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER.get()) {
|
if (ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER.get()) {
|
||||||
boolean needsToMigrate = needsToMigrate(mContext, mIdp);
|
boolean needsToMigrate = needsToMigrate(mContext, mIdp);
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
@@ -499,7 +506,10 @@ public class LauncherPreviewRenderer implements Callable<Bitmap> {
|
|||||||
measureView(mRootView, mDp.widthPx, mDp.heightPx);
|
measureView(mRootView, mDp.widthPx, mDp.heightPx);
|
||||||
// Additional measure for views which use auto text size API
|
// Additional measure for views which use auto text size API
|
||||||
measureView(mRootView, mDp.widthPx, mDp.heightPx);
|
measureView(mRootView, mDp.widthPx, mDp.heightPx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderScreenShot(Canvas canvas) {
|
||||||
|
populate();
|
||||||
mRootView.draw(canvas);
|
mRootView.draw(canvas);
|
||||||
dispatchVisibilityAggregated(mRootView, false);
|
dispatchVisibilityAggregated(mRootView, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ public class UserEventDispatcher implements ResourceBasedOverride {
|
|||||||
fillIntentInfo(itemTarget, intent, userHandle);
|
fillIntentInfo(itemTarget, intent, userHandle);
|
||||||
}
|
}
|
||||||
LauncherEvent event = newLauncherEvent(action, targets);
|
LauncherEvent event = newLauncherEvent(action, targets);
|
||||||
ItemInfo info = (ItemInfo) v.getTag();
|
ItemInfo info = v == null ? null : (ItemInfo) v.getTag();
|
||||||
if (info != null && Utilities.IS_DEBUG_DEVICE && FeatureFlags.ENABLE_HYBRID_HOTSEAT.get()) {
|
if (info != null && Utilities.IS_DEBUG_DEVICE && FeatureFlags.ENABLE_HYBRID_HOTSEAT.get()) {
|
||||||
FileLog.d(TAG, "appLaunch: packageName:" + info.getTargetComponent().getPackageName()
|
FileLog.d(TAG, "appLaunch: packageName:" + info.getTargetComponent().getPackageName()
|
||||||
+ ",isWorkApp:" + (info.user != null && !Process.myUserHandle().equals(
|
+ ",isWorkApp:" + (info.user != null && !Process.myUserHandle().equals(
|
||||||
|
|||||||
@@ -936,8 +936,8 @@ public class GridSizeMigrationTask {
|
|||||||
|
|
||||||
boolean dbChanged = false;
|
boolean dbChanged = false;
|
||||||
if (migrateForPreview) {
|
if (migrateForPreview) {
|
||||||
copyTable(transaction.getDb(), Favorites.TABLE_NAME, Favorites.PREVIEW_TABLE_NAME,
|
copyTable(transaction.getDb(), Favorites.TABLE_NAME, transaction.getDb(),
|
||||||
context);
|
Favorites.PREVIEW_TABLE_NAME, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
GridBackupTable backupTable = new GridBackupTable(context, transaction.getDb(),
|
GridBackupTable backupTable = new GridBackupTable(context, transaction.getDb(),
|
||||||
@@ -950,10 +950,11 @@ public class GridSizeMigrationTask {
|
|||||||
|
|
||||||
HashSet<String> validPackages = getValidPackages(context);
|
HashSet<String> validPackages = getValidPackages(context);
|
||||||
// Hotseat.
|
// Hotseat.
|
||||||
if (srcHotseatCount != idp.numHotseatIcons) {
|
if (srcHotseatCount != idp.numHotseatIcons
|
||||||
// Migrate hotseat.
|
&& new GridSizeMigrationTask(context, transaction.getDb(), validPackages,
|
||||||
dbChanged = new GridSizeMigrationTask(context, transaction.getDb(), validPackages,
|
migrateForPreview, srcHotseatCount,
|
||||||
migrateForPreview, srcHotseatCount, idp.numHotseatIcons).migrateHotseat();
|
idp.numHotseatIcons).migrateHotseat()) {
|
||||||
|
dbChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grid size
|
// Grid size
|
||||||
|
|||||||
@@ -16,9 +16,46 @@
|
|||||||
|
|
||||||
package com.android.launcher3.model;
|
package com.android.launcher3.model;
|
||||||
|
|
||||||
|
import static com.android.launcher3.Utilities.getPointString;
|
||||||
|
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.DatabaseUtils;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import com.android.launcher3.InvariantDeviceProfile;
|
import com.android.launcher3.InvariantDeviceProfile;
|
||||||
|
import com.android.launcher3.ItemInfo;
|
||||||
|
import com.android.launcher3.LauncherAppState;
|
||||||
|
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||||
|
import com.android.launcher3.LauncherSettings;
|
||||||
|
import com.android.launcher3.Utilities;
|
||||||
|
import com.android.launcher3.graphics.LauncherPreviewRenderer;
|
||||||
|
import com.android.launcher3.pm.InstallSessionHelper;
|
||||||
|
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
|
||||||
|
import com.android.launcher3.util.GridOccupancy;
|
||||||
|
import com.android.launcher3.util.IntArray;
|
||||||
|
import com.android.launcher3.widget.WidgetManagerHelper;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class takes care of shrinking the workspace (by maximum of one row and one column), as a
|
* This class takes care of shrinking the workspace (by maximum of one row and one column), as a
|
||||||
@@ -26,14 +63,63 @@ import com.android.launcher3.InvariantDeviceProfile;
|
|||||||
*/
|
*/
|
||||||
public class GridSizeMigrationTaskV2 {
|
public class GridSizeMigrationTaskV2 {
|
||||||
|
|
||||||
private GridSizeMigrationTaskV2(Context context) {
|
public static final String KEY_MIGRATION_SRC_WORKSPACE_SIZE = "migration_src_workspace_size";
|
||||||
|
public static final String KEY_MIGRATION_SRC_HOTSEAT_COUNT = "migration_src_hotseat_count";
|
||||||
|
|
||||||
|
private static final String TAG = "GridSizeMigrationTaskV2";
|
||||||
|
private static final boolean DEBUG = true;
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final SQLiteDatabase mDb;
|
||||||
|
private final DbReader mSrcReader;
|
||||||
|
private final DbReader mDestReader;
|
||||||
|
|
||||||
|
private final List<DbEntry> mHotseatItems;
|
||||||
|
private final List<DbEntry> mWorkspaceItems;
|
||||||
|
|
||||||
|
private final List<DbEntry> mHotseatDiff;
|
||||||
|
private final List<DbEntry> mWorkspaceDiff;
|
||||||
|
|
||||||
|
private final int mDestHotseatSize;
|
||||||
|
private final int mTrgX, mTrgY;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
protected GridSizeMigrationTaskV2(Context context, SQLiteDatabase db, DbReader srcReader,
|
||||||
|
DbReader destReader, int destHotseatSize, Point targetSize) {
|
||||||
|
mContext = context;
|
||||||
|
mDb = db;
|
||||||
|
mSrcReader = srcReader;
|
||||||
|
mDestReader = destReader;
|
||||||
|
|
||||||
|
mHotseatItems = destReader.loadHotseatEntries();
|
||||||
|
mWorkspaceItems = destReader.loadAllWorkspaceEntries();
|
||||||
|
|
||||||
|
mHotseatDiff = calcDiff(mSrcReader.loadHotseatEntries(), mHotseatItems);
|
||||||
|
mWorkspaceDiff = calcDiff(mSrcReader.loadAllWorkspaceEntries(), mWorkspaceItems);
|
||||||
|
mDestHotseatSize = destHotseatSize;
|
||||||
|
|
||||||
|
mTrgX = targetSize.x;
|
||||||
|
mTrgY = targetSize.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check given a new IDP, if migration is necessary.
|
||||||
|
*/
|
||||||
|
public static boolean needsToMigrate(Context context, InvariantDeviceProfile idp) {
|
||||||
|
SharedPreferences prefs = Utilities.getPrefs(context);
|
||||||
|
String gridSizeString = getPointString(idp.numColumns, idp.numRows);
|
||||||
|
|
||||||
|
return !gridSizeString.equals(prefs.getString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, ""))
|
||||||
|
|| idp.numHotseatIcons != prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT,
|
||||||
|
idp.numHotseatIcons);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** See {@link #migrateGridIfNeeded(Context, InvariantDeviceProfile)} */
|
/** See {@link #migrateGridIfNeeded(Context, InvariantDeviceProfile)} */
|
||||||
public static boolean migrateGridIfNeeded(Context context) {
|
public static boolean migrateGridIfNeeded(Context context) {
|
||||||
// To be implemented.
|
if (context instanceof LauncherPreviewRenderer.PreviewContext) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
return migrateGridIfNeeded(context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,7 +129,608 @@ public class GridSizeMigrationTaskV2 {
|
|||||||
* @return false if the migration failed.
|
* @return false if the migration failed.
|
||||||
*/
|
*/
|
||||||
public static boolean migrateGridIfNeeded(Context context, InvariantDeviceProfile idp) {
|
public static boolean migrateGridIfNeeded(Context context, InvariantDeviceProfile idp) {
|
||||||
// To be implemented.
|
boolean migrateForPreview = idp != null;
|
||||||
|
if (!migrateForPreview) {
|
||||||
|
idp = LauncherAppState.getIDP(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!needsToMigrate(context, idp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedPreferences prefs = Utilities.getPrefs(context);
|
||||||
|
String gridSizeString = getPointString(idp.numColumns, idp.numRows);
|
||||||
|
|
||||||
|
if (gridSizeString.equals(prefs.getString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, ""))
|
||||||
|
&& idp.numHotseatIcons == prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT,
|
||||||
|
idp.numHotseatIcons)) {
|
||||||
|
// Skip if workspace and hotseat sizes have not changed.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<String> validPackages = getValidPackages(context);
|
||||||
|
int srcHotseatCount = prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons);
|
||||||
|
|
||||||
|
if (!LauncherSettings.Settings.call(
|
||||||
|
context.getContentResolver(),
|
||||||
|
LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER).getBoolean(
|
||||||
|
LauncherSettings.Settings.EXTRA_VALUE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
long migrationStartTime = System.currentTimeMillis();
|
||||||
|
try (SQLiteTransaction t = (SQLiteTransaction) LauncherSettings.Settings.call(
|
||||||
|
context.getContentResolver(),
|
||||||
|
LauncherSettings.Settings.METHOD_NEW_TRANSACTION).getBinder(
|
||||||
|
LauncherSettings.Settings.EXTRA_VALUE)) {
|
||||||
|
|
||||||
|
DbReader srcReader = new DbReader(t.getDb(), LauncherSettings.Favorites.TMP_TABLE,
|
||||||
|
context, validPackages, srcHotseatCount);
|
||||||
|
DbReader destReader = new DbReader(t.getDb(), LauncherSettings.Favorites.TABLE_NAME,
|
||||||
|
context, validPackages, idp.numHotseatIcons);
|
||||||
|
|
||||||
|
Point targetSize = new Point(idp.numColumns, idp.numRows);
|
||||||
|
GridSizeMigrationTaskV2 task = new GridSizeMigrationTaskV2(context, t.getDb(),
|
||||||
|
srcReader, destReader, idp.numHotseatIcons, targetSize);
|
||||||
|
task.migrate();
|
||||||
|
|
||||||
|
dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE);
|
||||||
|
|
||||||
|
t.commit();
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error during grid migration", e);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
Log.v(TAG, "Workspace migration completed in "
|
||||||
|
+ (System.currentTimeMillis() - migrationStartTime));
|
||||||
|
|
||||||
|
// Save current configuration, so that the migration does not run again.
|
||||||
|
prefs.edit()
|
||||||
|
.putString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString)
|
||||||
|
.putInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons)
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
protected boolean migrate() {
|
||||||
|
if (mHotseatDiff.isEmpty() && mWorkspaceDiff.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Migrate hotseat
|
||||||
|
HotseatPlacementSolution hotseatSolution = new HotseatPlacementSolution(mDb, mSrcReader,
|
||||||
|
mContext, mDestHotseatSize, mHotseatItems, mHotseatDiff);
|
||||||
|
hotseatSolution.find();
|
||||||
|
|
||||||
|
// Sort the items by the reading order.
|
||||||
|
Collections.sort(mWorkspaceDiff);
|
||||||
|
|
||||||
|
// Migrate workspace.
|
||||||
|
for (int screenId = 0; screenId <= mDestReader.mLastScreenId; screenId++) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "Migrating " + screenId);
|
||||||
|
}
|
||||||
|
List<DbEntry> entries = mDestReader.loadWorkspaceEntries(screenId);
|
||||||
|
GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
|
||||||
|
mContext, entries, screenId, mTrgX, mTrgY, mWorkspaceDiff);
|
||||||
|
workspaceSolution.find();
|
||||||
|
if (mWorkspaceDiff.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int screenId = mDestReader.mLastScreenId + 1;
|
||||||
|
while (!mWorkspaceDiff.isEmpty()) {
|
||||||
|
GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
|
||||||
|
mContext, new ArrayList<>(), screenId, mTrgX, mTrgY, mWorkspaceDiff);
|
||||||
|
workspaceSolution.find();
|
||||||
|
screenId++;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return what's in the src but not in the dest */
|
||||||
|
private static List<DbEntry> calcDiff(List<DbEntry> src, List<DbEntry> dest) {
|
||||||
|
Set<String> destSet = dest.parallelStream().map(DbEntry::getIntentStr).collect(
|
||||||
|
Collectors.toSet());
|
||||||
|
List<DbEntry> diff = new ArrayList<>();
|
||||||
|
for (DbEntry entry : src) {
|
||||||
|
if (!destSet.contains(entry.mIntent)) {
|
||||||
|
diff.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void insertEntryInDb(SQLiteDatabase db, Context context,
|
||||||
|
ArrayList<DbEntry> entriesFromSrcDb, DbEntry entry) {
|
||||||
|
int id = -1;
|
||||||
|
switch (entry.itemType) {
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
|
||||||
|
for (DbEntry e : entriesFromSrcDb) {
|
||||||
|
if (TextUtils.equals(e.mIntent, entry.mIntent)) {
|
||||||
|
id = e.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: {
|
||||||
|
for (DbEntry e : entriesFromSrcDb) {
|
||||||
|
if (e.mFolderItems.size() == entry.mFolderItems.size()
|
||||||
|
&& e.mFolderItems.containsAll(entry.mFolderItems)) {
|
||||||
|
id = e.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET: {
|
||||||
|
for (DbEntry e : entriesFromSrcDb) {
|
||||||
|
if (TextUtils.equals(e.mProvider, entry.mProvider)) {
|
||||||
|
id = e.id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor c = db.query(LauncherSettings.Favorites.TMP_TABLE, null,
|
||||||
|
LauncherSettings.Favorites._ID + " = '" + id + "'", null, null, null, null);
|
||||||
|
|
||||||
|
while (c.moveToNext()) {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
DatabaseUtils.cursorRowToContentValues(c, values);
|
||||||
|
entry.updateContentValues(values);
|
||||||
|
values.put(LauncherSettings.Favorites._ID,
|
||||||
|
LauncherSettings.Settings.call(context.getContentResolver(),
|
||||||
|
LauncherSettings.Settings.METHOD_NEW_ITEM_ID).getInt(
|
||||||
|
LauncherSettings.Settings.EXTRA_VALUE));
|
||||||
|
db.insert(LauncherSettings.Favorites.TABLE_NAME, null, values);
|
||||||
|
}
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void removeEntryFromDb(SQLiteDatabase db, IntArray entryId) {
|
||||||
|
db.delete(LauncherSettings.Favorites.TABLE_NAME, Utilities.createDbSelectionQuery(
|
||||||
|
LauncherSettings.Favorites._ID, entryId), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HashSet<String> getValidPackages(Context context) {
|
||||||
|
// Initialize list of valid packages. This contain all the packages which are already on
|
||||||
|
// the device and packages which are being installed. Any item which doesn't belong to
|
||||||
|
// this set is removed.
|
||||||
|
// Since the loader removes such items anyway, removing these items here doesn't cause
|
||||||
|
// any extra data loss and gives us more free space on the grid for better migration.
|
||||||
|
HashSet<String> validPackages = new HashSet<>();
|
||||||
|
for (PackageInfo info : context.getPackageManager()
|
||||||
|
.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES)) {
|
||||||
|
validPackages.add(info.packageName);
|
||||||
|
}
|
||||||
|
InstallSessionHelper.INSTANCE.get(context)
|
||||||
|
.getActiveSessions().keySet()
|
||||||
|
.forEach(packageUserKey -> validPackages.add(packageUserKey.mPackageName));
|
||||||
|
return validPackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class GridPlacementSolution {
|
||||||
|
|
||||||
|
private final SQLiteDatabase mDb;
|
||||||
|
private final DbReader mSrcReader;
|
||||||
|
private final Context mContext;
|
||||||
|
private final GridOccupancy mOccupied;
|
||||||
|
private final int mScreenId;
|
||||||
|
private final int mTrgX;
|
||||||
|
private final int mTrgY;
|
||||||
|
private final List<DbEntry> mItemsToPlace;
|
||||||
|
|
||||||
|
private int mNextStartX;
|
||||||
|
private int mNextStartY;
|
||||||
|
|
||||||
|
GridPlacementSolution(SQLiteDatabase db, DbReader srcReader, Context context,
|
||||||
|
List<DbEntry> placedWorkspaceItems, int screenId, int trgX,
|
||||||
|
int trgY, List<DbEntry> itemsToPlace) {
|
||||||
|
mDb = db;
|
||||||
|
mSrcReader = srcReader;
|
||||||
|
mContext = context;
|
||||||
|
mOccupied = new GridOccupancy(trgX, trgY);
|
||||||
|
mScreenId = screenId;
|
||||||
|
mTrgX = trgX;
|
||||||
|
mTrgY = trgY;
|
||||||
|
mNextStartX = 0;
|
||||||
|
mNextStartY = mTrgY - 1;
|
||||||
|
for (DbEntry entry : placedWorkspaceItems) {
|
||||||
|
mOccupied.markCells(entry, true);
|
||||||
|
}
|
||||||
|
mItemsToPlace = itemsToPlace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void find() {
|
||||||
|
Iterator<DbEntry> iterator = mItemsToPlace.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
final DbEntry entry = iterator.next();
|
||||||
|
if (entry.minSpanX > mTrgX || entry.minSpanY > mTrgY) {
|
||||||
|
iterator.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (findPlacement(entry)) {
|
||||||
|
insertEntryInDb(mDb, mContext, mSrcReader.mWorkspaceEntries, entry);
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean findPlacement(DbEntry entry) {
|
||||||
|
for (int y = mNextStartY; y >= 0; y--) {
|
||||||
|
for (int x = mNextStartX; x < mTrgX; x++) {
|
||||||
|
boolean fits = mOccupied.isRegionVacant(x, y, entry.spanX, entry.spanY);
|
||||||
|
boolean minFits = mOccupied.isRegionVacant(x, y, entry.minSpanX,
|
||||||
|
entry.minSpanY);
|
||||||
|
if (minFits) {
|
||||||
|
entry.spanX = entry.minSpanX;
|
||||||
|
entry.spanY = entry.minSpanY;
|
||||||
|
}
|
||||||
|
if (fits || minFits) {
|
||||||
|
entry.screenId = mScreenId;
|
||||||
|
entry.cellX = x;
|
||||||
|
entry.cellY = y;
|
||||||
|
mOccupied.markCells(entry, true);
|
||||||
|
mNextStartX = x + entry.spanX;
|
||||||
|
mNextStartY = y;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class HotseatPlacementSolution {
|
||||||
|
|
||||||
|
private final SQLiteDatabase mDb;
|
||||||
|
private final DbReader mSrcReader;
|
||||||
|
private final Context mContext;
|
||||||
|
private final HotseatOccupancy mOccupied;
|
||||||
|
private final List<DbEntry> mItemsToPlace;
|
||||||
|
|
||||||
|
HotseatPlacementSolution(SQLiteDatabase db, DbReader srcReader, Context context,
|
||||||
|
int hotseatSize, List<DbEntry> placedHotseatItems, List<DbEntry> itemsToPlace) {
|
||||||
|
mDb = db;
|
||||||
|
mSrcReader = srcReader;
|
||||||
|
mContext = context;
|
||||||
|
mOccupied = new HotseatOccupancy(hotseatSize);
|
||||||
|
for (DbEntry entry : placedHotseatItems) {
|
||||||
|
mOccupied.markCells(entry, true);
|
||||||
|
}
|
||||||
|
mItemsToPlace = itemsToPlace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void find() {
|
||||||
|
for (int i = 0; i < mOccupied.mCells.length; i++) {
|
||||||
|
if (!mOccupied.mCells[i] && !mItemsToPlace.isEmpty()) {
|
||||||
|
DbEntry entry = mItemsToPlace.remove(0);
|
||||||
|
entry.screenId = i;
|
||||||
|
// These values does not affect the item position, but we should set them
|
||||||
|
// to something other than -1.
|
||||||
|
entry.cellX = i;
|
||||||
|
entry.cellY = 0;
|
||||||
|
insertEntryInDb(mDb, mContext, mSrcReader.mHotseatEntries, entry);
|
||||||
|
mOccupied.markCells(entry, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class HotseatOccupancy {
|
||||||
|
|
||||||
|
private final boolean[] mCells;
|
||||||
|
|
||||||
|
private HotseatOccupancy(int hotseatSize) {
|
||||||
|
mCells = new boolean[hotseatSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markCells(ItemInfo item, boolean value) {
|
||||||
|
mCells[item.screenId] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class DbReader {
|
||||||
|
|
||||||
|
private final SQLiteDatabase mDb;
|
||||||
|
private final String mTableName;
|
||||||
|
private final Context mContext;
|
||||||
|
private final HashSet<String> mValidPackages;
|
||||||
|
private final int mHotseatSize;
|
||||||
|
private int mLastScreenId = -1;
|
||||||
|
|
||||||
|
private final ArrayList<DbEntry> mHotseatEntries = new ArrayList<>();
|
||||||
|
private final ArrayList<DbEntry> mWorkspaceEntries = new ArrayList<>();
|
||||||
|
|
||||||
|
DbReader(SQLiteDatabase db, String tableName, Context context,
|
||||||
|
HashSet<String> validPackages, int hotseatSize) {
|
||||||
|
mDb = db;
|
||||||
|
mTableName = tableName;
|
||||||
|
mContext = context;
|
||||||
|
mValidPackages = validPackages;
|
||||||
|
mHotseatSize = hotseatSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ArrayList<DbEntry> loadHotseatEntries() {
|
||||||
|
Cursor c = queryWorkspace(
|
||||||
|
new String[]{
|
||||||
|
LauncherSettings.Favorites._ID, // 0
|
||||||
|
LauncherSettings.Favorites.ITEM_TYPE, // 1
|
||||||
|
LauncherSettings.Favorites.INTENT, // 2
|
||||||
|
LauncherSettings.Favorites.SCREEN}, // 3
|
||||||
|
LauncherSettings.Favorites.CONTAINER + " = "
|
||||||
|
+ LauncherSettings.Favorites.CONTAINER_HOTSEAT);
|
||||||
|
|
||||||
|
final int indexId = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
|
||||||
|
final int indexItemType = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
|
||||||
|
final int indexIntent = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
|
||||||
|
final int indexScreen = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
|
||||||
|
|
||||||
|
IntArray entriesToRemove = new IntArray();
|
||||||
|
while (c.moveToNext()) {
|
||||||
|
DbEntry entry = new DbEntry();
|
||||||
|
entry.id = c.getInt(indexId);
|
||||||
|
entry.itemType = c.getInt(indexItemType);
|
||||||
|
entry.screenId = c.getInt(indexScreen);
|
||||||
|
|
||||||
|
if (entry.screenId >= mHotseatSize) {
|
||||||
|
entriesToRemove.add(entry.id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// calculate weight
|
||||||
|
switch (entry.itemType) {
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
|
||||||
|
entry.mIntent = c.getString(indexIntent);
|
||||||
|
verifyIntent(c.getString(indexIntent));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: {
|
||||||
|
int total = getFolderItemsCount(entry);
|
||||||
|
if (total == 0) {
|
||||||
|
throw new Exception("Folder is empty");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Exception("Invalid item type");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "Removing item " + entry.id, e);
|
||||||
|
}
|
||||||
|
entriesToRemove.add(entry.id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mHotseatEntries.add(entry);
|
||||||
|
}
|
||||||
|
removeEntryFromDb(mDb, entriesToRemove);
|
||||||
|
c.close();
|
||||||
|
return mHotseatEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ArrayList<DbEntry> loadAllWorkspaceEntries() {
|
||||||
|
Cursor c = queryWorkspace(
|
||||||
|
new String[]{
|
||||||
|
LauncherSettings.Favorites._ID, // 0
|
||||||
|
LauncherSettings.Favorites.ITEM_TYPE, // 1
|
||||||
|
LauncherSettings.Favorites.SCREEN, // 2
|
||||||
|
LauncherSettings.Favorites.CELLX, // 3
|
||||||
|
LauncherSettings.Favorites.CELLY, // 4
|
||||||
|
LauncherSettings.Favorites.SPANX, // 5
|
||||||
|
LauncherSettings.Favorites.SPANY, // 6
|
||||||
|
LauncherSettings.Favorites.INTENT, // 7
|
||||||
|
LauncherSettings.Favorites.APPWIDGET_PROVIDER, // 8
|
||||||
|
LauncherSettings.Favorites.APPWIDGET_ID}, // 9
|
||||||
|
LauncherSettings.Favorites.CONTAINER + " = "
|
||||||
|
+ LauncherSettings.Favorites.CONTAINER_DESKTOP);
|
||||||
|
return loadWorkspaceEntries(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ArrayList<DbEntry> loadWorkspaceEntries(int screen) {
|
||||||
|
Cursor c = queryWorkspace(
|
||||||
|
new String[]{
|
||||||
|
LauncherSettings.Favorites._ID, // 0
|
||||||
|
LauncherSettings.Favorites.ITEM_TYPE, // 1
|
||||||
|
LauncherSettings.Favorites.SCREEN, // 2
|
||||||
|
LauncherSettings.Favorites.CELLX, // 3
|
||||||
|
LauncherSettings.Favorites.CELLY, // 4
|
||||||
|
LauncherSettings.Favorites.SPANX, // 5
|
||||||
|
LauncherSettings.Favorites.SPANY, // 6
|
||||||
|
LauncherSettings.Favorites.INTENT, // 7
|
||||||
|
LauncherSettings.Favorites.APPWIDGET_PROVIDER, // 8
|
||||||
|
LauncherSettings.Favorites.APPWIDGET_ID}, // 9
|
||||||
|
LauncherSettings.Favorites.CONTAINER + " = "
|
||||||
|
+ LauncherSettings.Favorites.CONTAINER_DESKTOP
|
||||||
|
+ " AND " + LauncherSettings.Favorites.SCREEN + " = " + screen);
|
||||||
|
return loadWorkspaceEntries(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<DbEntry> loadWorkspaceEntries(Cursor c) {
|
||||||
|
final int indexId = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
|
||||||
|
final int indexItemType = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
|
||||||
|
final int indexScreen = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
|
||||||
|
final int indexCellX = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
|
||||||
|
final int indexCellY = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
|
||||||
|
final int indexSpanX = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
|
||||||
|
final int indexSpanY = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
|
||||||
|
final int indexIntent = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
|
||||||
|
final int indexAppWidgetProvider = c.getColumnIndexOrThrow(
|
||||||
|
LauncherSettings.Favorites.APPWIDGET_PROVIDER);
|
||||||
|
final int indexAppWidgetId = c.getColumnIndexOrThrow(
|
||||||
|
LauncherSettings.Favorites.APPWIDGET_ID);
|
||||||
|
|
||||||
|
IntArray entriesToRemove = new IntArray();
|
||||||
|
WidgetManagerHelper widgetManagerHelper = new WidgetManagerHelper(mContext);
|
||||||
|
while (c.moveToNext()) {
|
||||||
|
DbEntry entry = new DbEntry();
|
||||||
|
entry.id = c.getInt(indexId);
|
||||||
|
entry.itemType = c.getInt(indexItemType);
|
||||||
|
entry.screenId = c.getInt(indexScreen);
|
||||||
|
mLastScreenId = Math.max(mLastScreenId, entry.screenId);
|
||||||
|
entry.cellX = c.getInt(indexCellX);
|
||||||
|
entry.cellY = c.getInt(indexCellY);
|
||||||
|
entry.spanX = c.getInt(indexSpanX);
|
||||||
|
entry.spanY = c.getInt(indexSpanY);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// calculate weight
|
||||||
|
switch (entry.itemType) {
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
|
||||||
|
entry.mIntent = c.getString(indexIntent);
|
||||||
|
verifyIntent(entry.mIntent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: {
|
||||||
|
entry.mProvider = c.getString(indexAppWidgetProvider);
|
||||||
|
ComponentName cn = ComponentName.unflattenFromString(entry.mProvider);
|
||||||
|
verifyPackage(cn.getPackageName());
|
||||||
|
|
||||||
|
int widgetId = c.getInt(indexAppWidgetId);
|
||||||
|
LauncherAppWidgetProviderInfo pInfo =
|
||||||
|
widgetManagerHelper.getLauncherAppWidgetInfo(widgetId);
|
||||||
|
Point spans = null;
|
||||||
|
if (pInfo != null) {
|
||||||
|
spans = pInfo.getMinSpans();
|
||||||
|
}
|
||||||
|
if (spans != null) {
|
||||||
|
entry.minSpanX = spans.x > 0 ? spans.x : entry.spanX;
|
||||||
|
entry.minSpanY = spans.y > 0 ? spans.y : entry.spanY;
|
||||||
|
} else {
|
||||||
|
// Assume that the widget be resized down to 2x2
|
||||||
|
entry.minSpanX = entry.minSpanY = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: {
|
||||||
|
int total = getFolderItemsCount(entry);
|
||||||
|
if (total == 0) {
|
||||||
|
throw new Exception("Folder is empty");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Exception("Invalid item type");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "Removing item " + entry.id, e);
|
||||||
|
}
|
||||||
|
entriesToRemove.add(entry.id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mWorkspaceEntries.add(entry);
|
||||||
|
}
|
||||||
|
removeEntryFromDb(mDb, entriesToRemove);
|
||||||
|
c.close();
|
||||||
|
return mWorkspaceEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getFolderItemsCount(DbEntry entry) {
|
||||||
|
Cursor c = queryWorkspace(
|
||||||
|
new String[]{LauncherSettings.Favorites._ID, LauncherSettings.Favorites.INTENT},
|
||||||
|
LauncherSettings.Favorites.CONTAINER + " = " + entry.id);
|
||||||
|
|
||||||
|
int total = 0;
|
||||||
|
while (c.moveToNext()) {
|
||||||
|
try {
|
||||||
|
String intent = c.getString(1);
|
||||||
|
verifyIntent(intent);
|
||||||
|
total++;
|
||||||
|
entry.mFolderItems.add(intent);
|
||||||
|
} catch (Exception e) {
|
||||||
|
removeEntryFromDb(mDb, IntArray.wrap(c.getInt(0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.close();
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cursor queryWorkspace(String[] columns, String where) {
|
||||||
|
return mDb.query(mTableName, columns, where, null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Verifies if the mIntent should be restored. */
|
||||||
|
private void verifyIntent(String intentStr)
|
||||||
|
throws Exception {
|
||||||
|
Intent intent = Intent.parseUri(intentStr, 0);
|
||||||
|
if (intent.getComponent() != null) {
|
||||||
|
verifyPackage(intent.getComponent().getPackageName());
|
||||||
|
} else if (intent.getPackage() != null) {
|
||||||
|
// Only verify package if the component was null.
|
||||||
|
verifyPackage(intent.getPackage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Verifies if the package should be restored */
|
||||||
|
private void verifyPackage(String packageName)
|
||||||
|
throws Exception {
|
||||||
|
if (!mValidPackages.contains(packageName)) {
|
||||||
|
// TODO(b/151468819): Handle promise app icon restoration during grid migration.
|
||||||
|
throw new Exception("Package not available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class DbEntry extends ItemInfo implements Comparable<DbEntry> {
|
||||||
|
|
||||||
|
private String mIntent;
|
||||||
|
private String mProvider;
|
||||||
|
private Set<String> mFolderItems = new HashSet<>();
|
||||||
|
|
||||||
|
/** Comparator according to the reading order */
|
||||||
|
@Override
|
||||||
|
public int compareTo(DbEntry another) {
|
||||||
|
if (screenId != another.screenId) {
|
||||||
|
return Integer.compare(screenId, another.screenId);
|
||||||
|
}
|
||||||
|
if (cellY != another.cellY) {
|
||||||
|
return -Integer.compare(cellY, another.cellY);
|
||||||
|
}
|
||||||
|
return Integer.compare(cellX, another.cellX);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
DbEntry entry = (DbEntry) o;
|
||||||
|
return Objects.equals(mIntent, entry.mIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(mIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateContentValues(ContentValues values) {
|
||||||
|
values.put(LauncherSettings.Favorites.SCREEN, screenId);
|
||||||
|
values.put(LauncherSettings.Favorites.CELLX, cellX);
|
||||||
|
values.put(LauncherSettings.Favorites.CELLY, cellY);
|
||||||
|
values.put(LauncherSettings.Favorites.SPANX, spanX);
|
||||||
|
values.put(LauncherSettings.Favorites.SPANY, spanY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIntentStr() {
|
||||||
|
return mIntent;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,13 +118,20 @@ public class LauncherDbUtils {
|
|||||||
db.execSQL("DROP TABLE IF EXISTS " + tableName);
|
db.execSQL("DROP TABLE IF EXISTS " + tableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Copy from table to the to table. */
|
/** Copy fromTable in fromDb to toTable in toDb. */
|
||||||
public static void copyTable(SQLiteDatabase db, String from, String to, Context context) {
|
public static void copyTable(SQLiteDatabase fromDb, String fromTable, SQLiteDatabase toDb,
|
||||||
|
String toTable, Context context) {
|
||||||
long userSerial = UserCache.INSTANCE.get(context).getSerialNumberForUser(
|
long userSerial = UserCache.INSTANCE.get(context).getSerialNumberForUser(
|
||||||
Process.myUserHandle());
|
Process.myUserHandle());
|
||||||
dropTable(db, to);
|
dropTable(toDb, toTable);
|
||||||
Favorites.addTableToDb(db, userSerial, false, to);
|
Favorites.addTableToDb(toDb, userSerial, false, toTable);
|
||||||
db.execSQL("INSERT INTO " + to + " SELECT * FROM " + from);
|
if (fromDb != toDb) {
|
||||||
|
toDb.execSQL("ATTACH DATABASE '" + fromDb.getPath() + "' AS from_db");
|
||||||
|
toDb.execSQL(
|
||||||
|
"INSERT INTO " + toTable + " SELECT * FROM from_db." + fromTable);
|
||||||
|
} else {
|
||||||
|
toDb.execSQL("INSERT INTO " + toTable + " SELECT * FROM " + fromTable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.states;
|
||||||
|
|
||||||
|
import android.view.animation.Interpolator;
|
||||||
|
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for building animator set
|
||||||
|
*/
|
||||||
|
public class StateAnimationConfig {
|
||||||
|
|
||||||
|
// We separate the state animations into "atomic" and "non-atomic" components. The atomic
|
||||||
|
// components may be run atomically - that is, all at once, instead of user-controlled. However,
|
||||||
|
// atomic components are not restricted to this purpose; they can be user-controlled alongside
|
||||||
|
// non atomic components as well. Note that each gesture model has exactly one atomic component,
|
||||||
|
// PLAY_ATOMIC_OVERVIEW_SCALE *or* PLAY_ATOMIC_OVERVIEW_PEEK.
|
||||||
|
@IntDef(flag = true, value = {
|
||||||
|
PLAY_NON_ATOMIC,
|
||||||
|
PLAY_ATOMIC_OVERVIEW_SCALE,
|
||||||
|
PLAY_ATOMIC_OVERVIEW_PEEK,
|
||||||
|
SKIP_OVERVIEW,
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface AnimationFlags {}
|
||||||
|
public static final int PLAY_NON_ATOMIC = 1 << 0;
|
||||||
|
public static final int PLAY_ATOMIC_OVERVIEW_SCALE = 1 << 1;
|
||||||
|
public static final int PLAY_ATOMIC_OVERVIEW_PEEK = 1 << 2;
|
||||||
|
public static final int SKIP_OVERVIEW = 1 << 3;
|
||||||
|
|
||||||
|
public long duration;
|
||||||
|
public boolean userControlled;
|
||||||
|
public @AnimationFlags int animFlags = ANIM_ALL_COMPONENTS;
|
||||||
|
|
||||||
|
public static final int ANIM_ALL_COMPONENTS = PLAY_NON_ATOMIC | PLAY_ATOMIC_OVERVIEW_SCALE
|
||||||
|
| PLAY_ATOMIC_OVERVIEW_PEEK;
|
||||||
|
|
||||||
|
// Various types of animation state transition
|
||||||
|
@IntDef(value = {
|
||||||
|
ANIM_VERTICAL_PROGRESS,
|
||||||
|
ANIM_WORKSPACE_SCALE,
|
||||||
|
ANIM_WORKSPACE_TRANSLATE,
|
||||||
|
ANIM_WORKSPACE_FADE,
|
||||||
|
ANIM_HOTSEAT_SCALE,
|
||||||
|
ANIM_HOTSEAT_TRANSLATE,
|
||||||
|
ANIM_OVERVIEW_SCALE,
|
||||||
|
ANIM_OVERVIEW_TRANSLATE_X,
|
||||||
|
ANIM_OVERVIEW_TRANSLATE_Y,
|
||||||
|
ANIM_OVERVIEW_FADE,
|
||||||
|
ANIM_ALL_APPS_FADE,
|
||||||
|
ANIM_OVERVIEW_SCRIM_FADE,
|
||||||
|
ANIM_ALL_APPS_HEADER_FADE,
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface AnimType {}
|
||||||
|
public static final int ANIM_VERTICAL_PROGRESS = 0;
|
||||||
|
public static final int ANIM_WORKSPACE_SCALE = 1;
|
||||||
|
public static final int ANIM_WORKSPACE_TRANSLATE = 2;
|
||||||
|
public static final int ANIM_WORKSPACE_FADE = 3;
|
||||||
|
public static final int ANIM_HOTSEAT_SCALE = 4;
|
||||||
|
public static final int ANIM_HOTSEAT_TRANSLATE = 5;
|
||||||
|
public static final int ANIM_OVERVIEW_SCALE = 6;
|
||||||
|
public static final int ANIM_OVERVIEW_TRANSLATE_X = 7;
|
||||||
|
public static final int ANIM_OVERVIEW_TRANSLATE_Y = 8;
|
||||||
|
public static final int ANIM_OVERVIEW_FADE = 9;
|
||||||
|
public static final int ANIM_ALL_APPS_FADE = 10;
|
||||||
|
public static final int ANIM_OVERVIEW_SCRIM_FADE = 11;
|
||||||
|
public static final int ANIM_ALL_APPS_HEADER_FADE = 12; // e.g. predictions
|
||||||
|
|
||||||
|
private static final int ANIM_TYPES_COUNT = 13;
|
||||||
|
|
||||||
|
private final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
|
||||||
|
|
||||||
|
public StateAnimationConfig() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the config to target
|
||||||
|
*/
|
||||||
|
public void copyTo(StateAnimationConfig target) {
|
||||||
|
target.duration = duration;
|
||||||
|
target.animFlags = animFlags;
|
||||||
|
target.userControlled = userControlled;
|
||||||
|
for (int i = 0; i < ANIM_TYPES_COUNT; i++) {
|
||||||
|
target.mInterpolators[i] = mInterpolators[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the interpolator set for animId or fallback if nothing is set
|
||||||
|
*
|
||||||
|
* @see #setInterpolator(int, Interpolator)
|
||||||
|
*/
|
||||||
|
public Interpolator getInterpolator(@AnimType int animId, Interpolator fallback) {
|
||||||
|
return mInterpolators[animId] == null ? fallback : mInterpolators[animId];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an interpolator for a given animation type
|
||||||
|
*/
|
||||||
|
public void setInterpolator(@AnimType int animId, Interpolator interpolator) {
|
||||||
|
mInterpolators[animId] = interpolator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Whether Overview is scaling as part of this animation. If this is the only
|
||||||
|
* component (i.e. NON_ATOMIC_COMPONENT isn't included), then this scaling is happening
|
||||||
|
* atomically, rather than being part of a normal state animation. StateHandlers can use
|
||||||
|
* this to designate part of their animation that should scale with Overview.
|
||||||
|
*/
|
||||||
|
public boolean playAtomicOverviewScaleComponent() {
|
||||||
|
return hasAnimationFlag(StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Whether this animation will play atomically at the same time as a different,
|
||||||
|
* user-controlled state transition. StateHandlers, which contribute to both animations, can
|
||||||
|
* use this to avoid animating the same properties in both animations, since they'd conflict
|
||||||
|
* with one another.
|
||||||
|
*/
|
||||||
|
public boolean onlyPlayAtomicComponent() {
|
||||||
|
return getAnimComponents() == StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE
|
||||||
|
|| getAnimComponents() == StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the config and any of the provided component flags
|
||||||
|
*/
|
||||||
|
public boolean hasAnimationFlag(@AnimationFlags int a) {
|
||||||
|
return (animFlags & a) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Only the flags that determine which animation components to play.
|
||||||
|
*/
|
||||||
|
public @AnimationFlags int getAnimComponents() {
|
||||||
|
return animFlags & StateAnimationConfig.ANIM_ALL_COMPONENTS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,11 +19,11 @@ import static com.android.launcher3.LauncherAnimUtils.MIN_PROGRESS_TO_ALL_APPS;
|
|||||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||||
import static com.android.launcher3.LauncherState.NORMAL;
|
import static com.android.launcher3.LauncherState.NORMAL;
|
||||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||||
import static com.android.launcher3.LauncherStateManager.ANIM_ALL_COMPONENTS;
|
|
||||||
import static com.android.launcher3.LauncherStateManager.PLAY_ATOMIC_OVERVIEW_SCALE;
|
|
||||||
import static com.android.launcher3.LauncherStateManager.PLAY_NON_ATOMIC;
|
|
||||||
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
|
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
|
||||||
import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
|
import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE;
|
||||||
|
import static com.android.launcher3.states.StateAnimationConfig.PLAY_NON_ATOMIC;
|
||||||
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
@@ -37,12 +37,12 @@ import android.view.MotionEvent;
|
|||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherAnimUtils;
|
import com.android.launcher3.LauncherAnimUtils;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationFlags;
|
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
|
||||||
import com.android.launcher3.anim.PendingAnimation;
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||||
@@ -358,14 +358,18 @@ public abstract class AbstractStateChangeTouchController
|
|||||||
|
|
||||||
private AnimatorSet createAtomicAnimForState(LauncherState fromState, LauncherState targetState,
|
private AnimatorSet createAtomicAnimForState(LauncherState fromState, LauncherState targetState,
|
||||||
long duration) {
|
long duration) {
|
||||||
AnimatorSetBuilder builder = getAnimatorSetBuilderForStates(fromState, targetState);
|
StateAnimationConfig config = getConfigForStates(fromState, targetState);
|
||||||
return mLauncher.getStateManager().createAtomicAnimation(fromState, targetState, builder,
|
config.animFlags = PLAY_ATOMIC_OVERVIEW_SCALE;
|
||||||
PLAY_ATOMIC_OVERVIEW_SCALE, duration);
|
config.duration = duration;
|
||||||
|
return mLauncher.getStateManager().createAtomicAnimation(fromState, targetState, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AnimatorSetBuilder getAnimatorSetBuilderForStates(LauncherState fromState,
|
/**
|
||||||
LauncherState toState) {
|
* Returns animation config for state transition between provided states
|
||||||
return new AnimatorSetBuilder();
|
*/
|
||||||
|
protected StateAnimationConfig getConfigForStates(
|
||||||
|
LauncherState fromState, LauncherState toState) {
|
||||||
|
return new StateAnimationConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import android.view.MotionEvent;
|
|||||||
import com.android.launcher3.AbstractFloatingView;
|
import com.android.launcher3.AbstractFloatingView;
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager.AnimationFlags;
|
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
package com.android.launcher3.widget;
|
package com.android.launcher3.widget;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||||
import android.animation.ObjectAnimator;
|
|
||||||
import android.animation.PropertyValuesHolder;
|
import android.animation.PropertyValuesHolder;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@@ -28,16 +28,15 @@ import android.view.Gravity;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.animation.Interpolator;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.android.launcher3.Insettable;
|
import com.android.launcher3.Insettable;
|
||||||
import com.android.launcher3.ItemInfo;
|
import com.android.launcher3.ItemInfo;
|
||||||
import com.android.launcher3.LauncherAppState;
|
import com.android.launcher3.LauncherAppState;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.ResourceUtils;
|
import com.android.launcher3.ResourceUtils;
|
||||||
import com.android.launcher3.anim.Interpolators;
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.model.WidgetItem;
|
import com.android.launcher3.model.WidgetItem;
|
||||||
import com.android.launcher3.util.PackageUserKey;
|
import com.android.launcher3.util.PackageUserKey;
|
||||||
|
|
||||||
@@ -156,7 +155,7 @@ public class WidgetsBottomSheet extends BaseWidgetSheet implements Insettable {
|
|||||||
setupNavBarColor();
|
setupNavBarColor();
|
||||||
mOpenCloseAnimator.setValues(
|
mOpenCloseAnimator.setValues(
|
||||||
PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
|
PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
|
||||||
mOpenCloseAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
mOpenCloseAnimator.setInterpolator(FAST_OUT_SLOW_IN);
|
||||||
mOpenCloseAnimator.start();
|
mOpenCloseAnimator.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,9 +190,9 @@ public class WidgetsBottomSheet extends BaseWidgetSheet implements Insettable {
|
|||||||
mIsOpen ? R.string.widgets_list : R.string.widgets_list_closed));
|
mIsOpen ? R.string.widgets_list : R.string.widgets_list_closed));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
public Animator createHintCloseAnim(float distanceToMove) {
|
public void addHintCloseAnim(
|
||||||
return ObjectAnimator.ofInt(this, PADDING_BOTTOM, (int) (distanceToMove + mInsets.bottom));
|
float distanceToMove, Interpolator interpolator, PendingAnimation target) {
|
||||||
|
target.setInt(this, PADDING_BOTTOM, (int) (distanceToMove + mInsets.bottom), interpolator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.launcher3.widget;
|
package com.android.launcher3.widget;
|
||||||
|
|
||||||
|
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||||
import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
|
import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.AnimatorSet;
|
|
||||||
import android.animation.ObjectAnimator;
|
|
||||||
import android.animation.PropertyValuesHolder;
|
import android.animation.PropertyValuesHolder;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@@ -30,8 +29,8 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
|
import android.view.animation.Interpolator;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import com.android.launcher3.Insettable;
|
import com.android.launcher3.Insettable;
|
||||||
@@ -39,6 +38,7 @@ import com.android.launcher3.Launcher;
|
|||||||
import com.android.launcher3.LauncherAppState;
|
import com.android.launcher3.LauncherAppState;
|
||||||
import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
|
import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||||
import com.android.launcher3.views.RecyclerViewFastScroller;
|
import com.android.launcher3.views.RecyclerViewFastScroller;
|
||||||
import com.android.launcher3.views.TopRoundedCornerView;
|
import com.android.launcher3.views.TopRoundedCornerView;
|
||||||
@@ -242,13 +242,11 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
|||||||
return mAdapter.getItemCount();
|
return mAdapter.getItemCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
public Animator createHintCloseAnim(float distanceToMove) {
|
public void addHintCloseAnim(
|
||||||
AnimatorSet anim = new AnimatorSet();
|
float distanceToMove, Interpolator interpolator, PendingAnimation target) {
|
||||||
anim.play(ObjectAnimator.ofFloat(mRecyclerView, TRANSLATION_Y, -distanceToMove));
|
target.setFloat(mRecyclerView, VIEW_TRANSLATE_Y, -distanceToMove, interpolator);
|
||||||
anim.play(ObjectAnimator.ofFloat(mRecyclerView, ALPHA, 0.5f));
|
target.setViewAlpha(mRecyclerView, 0.5f, interpolator);
|
||||||
return anim;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,10 +19,12 @@ package com.android.launcher3.uioverrides;
|
|||||||
|
|
||||||
import android.util.IntProperty;
|
import android.util.IntProperty;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherState;
|
import com.android.launcher3.LauncherState;
|
||||||
import com.android.launcher3.LauncherStateManager;
|
import com.android.launcher3.LauncherStateManager;
|
||||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
import com.android.launcher3.anim.PendingAnimation;
|
||||||
|
import com.android.launcher3.states.StateAnimationConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls the blur, for the Launcher surface only.
|
* Controls the blur, for the Launcher surface only.
|
||||||
@@ -52,6 +54,6 @@ public class BackgroundBlurController implements LauncherStateManager.StateHandl
|
|||||||
public void setState(LauncherState toState) {}
|
public void setState(LauncherState toState) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStateWithAnimation(LauncherState toState, AnimatorSetBuilder builder,
|
public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
|
||||||
LauncherStateManager.AnimationConfig config) {}
|
PendingAnimation animation) { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.uioverrides;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
/** Render preview using surface view. */
|
||||||
|
public class PreviewSurfaceRenderer {
|
||||||
|
|
||||||
|
/** Handle a received surface view request. */
|
||||||
|
public static void render(Context context, Bundle bundle) { }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user