Merge "Don't end atomic animation when passing through state" into ub-launcher3-edmonton
diff --git a/quickstep/res/layout/drag_handle_indicator.xml b/quickstep/res/layout/drag_handle_indicator.xml
deleted file mode 100644
index 9ee05d5..0000000
--- a/quickstep/res/layout/drag_handle_indicator.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.quickstep.views.QuickstepDragIndicator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/drag_indicator"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@string/accessibility_desc_recent_apps"
- android:scaleType="centerInside"
- android:tint="?attr/workspaceTextColor" />
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 9e4d60c..ad5f767 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -30,8 +30,9 @@
<dimen name="quickstep_fling_min_velocity">250dp</dimen>
<!-- Launcher app transition -->
- <dimen name="content_trans_y">25dp</dimen>
- <dimen name="workspace_trans_y">80dp</dimen>
+ <dimen name="content_trans_y">50dp</dimen>
+ <dimen name="workspace_trans_y">50dp</dimen>
+ <dimen name="closing_window_trans_y">115dp</dimen>
<dimen name="recents_empty_message_text_size">16sp</dimen>
<dimen name="recents_empty_message_text_padding">16dp</dimen>
@@ -50,5 +51,4 @@
<dimen name="clear_all_container_width">168dp</dimen>
<dimen name="shelf_surface_radius">16dp</dimen>
- <dimen name="shelf_surface_top_padding">4dp</dimen>
</resources>
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 4963f5d..fc02f72 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -19,12 +19,11 @@
import static com.android.launcher3.BaseActivity.INVISIBLE_ALL;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_APP_TRANSITIONS;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.Utilities.postAsyncCallback;
-import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
-import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
-import static com.android.launcher3.anim.Interpolators.APP_CLOSE_ALPHA;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.TaskUtils.findTaskViewToLaunch;
import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator;
@@ -58,7 +57,6 @@
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.InsettableFrameLayout.LayoutParams;
-import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.dragndrop.DragLayer;
@@ -102,11 +100,10 @@
public static final int RECENTS_LAUNCH_DURATION = 336;
private static final int LAUNCHER_RESUME_START_DELAY = 100;
- private static final int CLOSING_TRANSITION_DURATION_MS = 350;
+ private static final int CLOSING_TRANSITION_DURATION_MS = 250;
// Progress = 0: All apps is fully pulled up, Progress = 1: All apps is fully pulled down.
public static final float ALL_APPS_PROGRESS_OFF_SCREEN = 1.3059858f;
- public static final float ALL_APPS_PROGRESS_OVERSHOOT = 0.99581414f;
private final DragLayer mDragLayer;
private final Launcher mLauncher;
@@ -116,6 +113,7 @@
private final float mContentTransY;
private final float mWorkspaceTransY;
+ private final float mClosingWindowTransY;
private DeviceProfile mDeviceProfile;
private View mFloatingView;
@@ -129,6 +127,16 @@
}
};
+ private final Runnable mDragLayerResetRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mDragLayer.setLayerType(View.LAYER_TYPE_NONE, null);
+ mDragLayer.setAlpha(1);
+ mDragLayer.setTranslationY(0);
+ mLauncher.getWorkspace().getPageIndicator().skipAnimationsToEnd();
+ }
+ };
+
private final AnimatorListenerAdapter mForceInvisibleListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
@@ -151,6 +159,7 @@
Resources res = mLauncher.getResources();
mContentTransY = res.getDimensionPixelSize(R.dimen.content_trans_y);
mWorkspaceTransY = res.getDimensionPixelSize(R.dimen.workspace_trans_y);
+ mClosingWindowTransY = res.getDimensionPixelSize(R.dimen.closing_window_trans_y);
mLauncher.addOnDeviceProfileChangeListener(this);
registerRemoteAnimations();
@@ -187,7 +196,7 @@
anim.play(getIconAnimator(v));
if (launcherClosing) {
Pair<AnimatorSet, Runnable> launcherContentAnimator =
- getLauncherContentAnimator(false /* show */);
+ getLauncherContentAnimator(true /* isAppOpening */);
anim.play(launcherContentAnimator.first);
anim.addListener(new AnimatorListenerAdapter() {
@Override
@@ -281,21 +290,21 @@
/**
* Content is everything on screen except the background and the floating view (if any).
*
- * @param show If true: Animate the content so that it moves upwards and fades in.
- * Else: Animate the content so that it moves downwards and fades out.
+ * @param isAppOpening True when this is called when an app is opening.
+ * False when this is called when an app is closing.
*/
- private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean show) {
+ private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean isAppOpening) {
AnimatorSet launcherAnimator = new AnimatorSet();
Runnable endListener;
- float[] alphas = show
- ? new float[] {0, 1}
- : new float[] {1, 0};
- float[] trans = show
- ? new float[] {mContentTransY, 0,}
- : new float[] {0, mContentTransY};
+ if (mLauncher.isInState(ALL_APPS)) {
+ float[] alphas = isAppOpening
+ ? new float[] {1, 0}
+ : new float[] {0, 1};
+ float[] trans = isAppOpening
+ ? new float[] {0, mContentTransY}
+ : new float[] {-mContentTransY, 0};
- if (mLauncher.isInState(LauncherState.ALL_APPS) && !mDeviceProfile.isVerticalBarLayout()) {
// All Apps in portrait mode is full screen, so we only animate AllAppsContainerView.
final View appsView = mLauncher.getAppsView();
final float startAlpha = appsView.getAlpha();
@@ -326,6 +335,9 @@
appsView.setLayerType(View.LAYER_TYPE_NONE, null);
};
} else {
+ float[] alphas = new float[] {1, 0};
+ float[] trans = new float[] {0, mContentTransY};
+
mDragLayer.setAlpha(alphas[0]);
mDragLayer.setTranslationY(trans[0]);
@@ -343,12 +355,7 @@
// Pause page indicator animations as they lead to layer trashing.
mLauncher.getWorkspace().getPageIndicator().pauseAnimations();
- endListener = () -> {
- mDragLayer.setLayerType(View.LAYER_TYPE_NONE, null);
- mDragLayer.setAlpha(1);
- mDragLayer.setTranslationY(0);
- mLauncher.getWorkspace().getPageIndicator().skipAnimationsToEnd();
- };
+ endListener = mDragLayerResetRunnable;
}
return new Pair<>(launcherAnimator, endListener);
}
@@ -646,16 +653,14 @@
*/
private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] targets) {
Matrix matrix = new Matrix();
- float height = mLauncher.getDeviceProfile().heightPx;
- float width = mLauncher.getDeviceProfile().widthPx;
- float endX = (mLauncher.<RecentsView>getOverviewPanel().isRtl() ? -width : width) * 1.16f;
-
ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
- closingAnimator.setDuration(CLOSING_TRANSITION_DURATION_MS);
+ int duration = CLOSING_TRANSITION_DURATION_MS;
+ closingAnimator.setDuration(duration);
+ Rect crop = new Rect();
closingAnimator.addUpdateListener(new MultiValueUpdateListener() {
- FloatProp mDx = new FloatProp(0, endX, 0, 350, AGGRESSIVE_EASE_IN_OUT);
- FloatProp mScale = new FloatProp(1f, 0.8f, 0, 267, AGGRESSIVE_EASE);
- FloatProp mAlpha = new FloatProp(1f, 0f, 0, 350, APP_CLOSE_ALPHA);
+ FloatProp mDy = new FloatProp(0, mClosingWindowTransY, 0, duration, DEACCEL_1_7);
+ FloatProp mScale = new FloatProp(1f, 1.075f, 0, duration, DEACCEL_1_7);
+ FloatProp mAlpha = new FloatProp(1f, 0f, 0, duration, DEACCEL_1_7);
boolean isFirstFrame = true;
@@ -667,13 +672,16 @@
isFirstFrame = false;
}
for (RemoteAnimationTargetCompat app : targets) {
+ crop.set(app.clipRect);
+ crop.top = mDeviceProfile.getInsets().top;
if (app.mode == RemoteAnimationTargetCompat.MODE_CLOSING) {
t.setAlpha(app.leash, mAlpha.value);
matrix.setScale(mScale.value, mScale.value,
app.sourceContainerBounds.centerX(),
app.sourceContainerBounds.centerY());
- matrix.postTranslate(mDx.value, 0);
+ matrix.postTranslate(0, mDy.value);
matrix.postTranslate(app.position.x, app.position.y);
+ t.setWindowCrop(app.leash, crop);
t.setMatrix(app.leash, matrix);
}
}
@@ -694,7 +702,7 @@
if (mLauncher.isInState(LauncherState.ALL_APPS)
|| mLauncher.getDeviceProfile().isVerticalBarLayout()) {
Pair<AnimatorSet, Runnable> contentAnimator =
- getLauncherContentAnimator(true /* show */);
+ getLauncherContentAnimator(false /* isAppOpening */);
contentAnimator.first.setStartDelay(LAUNCHER_RESUME_START_DELAY);
anim.play(contentAnimator.first);
anim.addListener(new AnimatorListenerAdapter() {
@@ -706,53 +714,29 @@
} else {
AnimatorSet workspaceAnimator = new AnimatorSet();
- mLauncher.getWorkspace().setTranslationY(mWorkspaceTransY);
- workspaceAnimator.play(ObjectAnimator.ofFloat(mLauncher.getWorkspace(),
- View.TRANSLATION_Y, mWorkspaceTransY, 0));
+ mDragLayer.setTranslationY(-mWorkspaceTransY);
+ workspaceAnimator.play(ObjectAnimator.ofFloat(mDragLayer, View.TRANSLATION_Y,
+ -mWorkspaceTransY, 0));
- View currentPage = ((CellLayout) mLauncher.getWorkspace()
- .getChildAt(mLauncher.getWorkspace().getCurrentPage()))
- .getShortcutsAndWidgets();
- currentPage.setAlpha(0f);
- workspaceAnimator.play(ObjectAnimator.ofFloat(currentPage, View.ALPHA, 0, 1f));
+ mDragLayer.setAlpha(0);
+ workspaceAnimator.play(ObjectAnimator.ofFloat(mDragLayer, View.ALPHA, 0, 1f));
workspaceAnimator.setStartDelay(LAUNCHER_RESUME_START_DELAY);
workspaceAnimator.setDuration(333);
- workspaceAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- currentPage.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ workspaceAnimator.setInterpolator(Interpolators.DEACCEL_1_7);
+
+ // Pause page indicator animations as they lead to layer trashing.
+ mLauncher.getWorkspace().getPageIndicator().pauseAnimations();
+ mDragLayer.setLayerType(View.LAYER_TYPE_HARDWARE, null);
workspaceAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- currentPage.setLayerType(View.LAYER_TYPE_NONE, null);
+ mDragLayerResetRunnable.run();
}
});
-
- // Animate the shelf in two parts: slide in, and overeshoot.
- AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
- // The shelf will start offscreen
- final float startY = ALL_APPS_PROGRESS_OFF_SCREEN;
- // And will end slightly pulled up, so that there is something to overshoot back to 1f.
- final float slideEnd = ALL_APPS_PROGRESS_OVERSHOOT;
-
- allAppsController.setProgress(startY);
-
- Animator allAppsSlideIn =
- ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS, startY, slideEnd);
- allAppsSlideIn.setStartDelay(LAUNCHER_RESUME_START_DELAY);
- allAppsSlideIn.setDuration(317);
- allAppsSlideIn.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-
- Animator allAppsOvershoot =
- ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS, slideEnd, 1f);
- allAppsOvershoot.setDuration(153);
- allAppsOvershoot.setInterpolator(Interpolators.OVERSHOOT_0);
-
anim.play(workspaceAnimator);
- anim.playSequentially(allAppsSlideIn, allAppsOvershoot);
- anim.addListener(mReapplyStateListener);
}
}
-
private boolean hasControlRemoteAppTransitionPermission() {
return mLauncher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION)
== PackageManager.PERMISSION_GRANTED;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index eaf8aa0..4029b82 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -97,9 +97,9 @@
@Override
public int getVisibleElements(Launcher launcher) {
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
- return DRAG_HANDLE_INDICATOR;
+ return 0;
} else {
- return HOTSEAT_SEARCH_BOX | DRAG_HANDLE_INDICATOR |
+ return HOTSEAT_SEARCH_BOX |
(launcher.getAppsView().getFloatingHeaderView().hasVisibleContent()
? ALL_APPS_HEADER_EXTRA : HOTSEAT_ICONS);
}
diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
index 8923608..9416a29 100644
--- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java
+++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
@@ -21,9 +21,12 @@
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
import static com.android.systemui.shared.system.SettingsCompat.SWIPE_UP_SETTING_NAME;
+import static com.android.launcher3.Utilities.getSystemProperty;
+
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -33,6 +36,8 @@
import android.util.Log;
import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.util.UiThreadHelper;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -52,6 +57,8 @@
private static final String TAG = "OverviewFlags";
+ private static final String HAS_ENABLED_QUICKSTEP_ONCE = "launcher.has_enabled_quickstep_once";
+
// We do not need any synchronization for this variable as its only written on UI thread.
private static OverviewInteractionState INSTANCE;
@@ -77,6 +84,7 @@
private final SwipeUpGestureEnabledSettingObserver mSwipeUpSettingObserver;
+ private final Context mContext;
private final Handler mUiHandler;
private final Handler mBgHandler;
@@ -88,12 +96,18 @@
private Runnable mOnSwipeUpSettingChangedListener;
private OverviewInteractionState(Context context) {
+ mContext = context;
mUiHandler = new Handler(this::handleUiMessage);
mBgHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleBgMessage);
- mSwipeUpSettingObserver = new SwipeUpGestureEnabledSettingObserver(mUiHandler,
- context.getContentResolver());
- mSwipeUpSettingObserver.register();
+ if (shouldIgnoreSwipeUpEnabledSettings()) {
+ mSwipeUpSettingObserver = null;
+ mSwipeUpEnabled = true;
+ } else {
+ mSwipeUpSettingObserver = new SwipeUpGestureEnabledSettingObserver(mUiHandler,
+ context.getContentResolver());
+ mSwipeUpSettingObserver.register();
+ }
}
public boolean isSwipeUpGestureEnabled() {
@@ -125,6 +139,8 @@
break;
case MSG_SET_SWIPE_UP_ENABLED:
mSwipeUpEnabled = msg.arg1 != 0;
+ resetHomeBounceSeenOnQuickstepEnabledFirstTime();
+
if (mOnSwipeUpSettingChangedListener != null) {
mOnSwipeUpSettingChangedListener.run();
}
@@ -171,6 +187,7 @@
mResolver.registerContentObserver(Settings.Secure.getUriFor(SWIPE_UP_SETTING_NAME),
false, this);
mSwipeUpEnabled = getValue();
+ resetHomeBounceSeenOnQuickstepEnabledFirstTime();
}
@Override
@@ -184,4 +201,23 @@
return Settings.Secure.getInt(mResolver, SWIPE_UP_SETTING_NAME, 0) == 1;
}
}
+
+ private boolean shouldIgnoreSwipeUpEnabledSettings() {
+ String sdkInt = getSystemProperty("ro.product.first_api_level", "0");
+ try {
+ return Integer.parseInt(sdkInt) >= Build.VERSION_CODES.P;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
+ if (mSwipeUpEnabled && !Utilities.getPrefs(mContext).getBoolean(
+ HAS_ENABLED_QUICKSTEP_ONCE, true)) {
+ Utilities.getPrefs(mContext).edit()
+ .putBoolean(HAS_ENABLED_QUICKSTEP_ONCE, true)
+ .putBoolean(DiscoveryBounce.HOME_BOUNCE_SEEN, false)
+ .apply();
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index b1fa5e2..2ff70dd 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -43,8 +43,7 @@
extraSpace = 0;
} else {
Resources res = context.getResources();
- extraSpace = dp.hotseatBarSizePx + res.getDimension(R.dimen.shelf_surface_top_padding)
- + res.getDimension(R.dimen.shelf_surface_radius);
+ extraSpace = dp.hotseatBarSizePx + res.getDimension(R.dimen.vertical_drag_handle_size);
}
calculateTaskSize(context, dp, extraSpace, MULTI_WINDOW_STRATEGY_HALF_SCREEN, outRect);
}
diff --git a/quickstep/src/com/android/quickstep/views/QuickstepDragIndicator.java b/quickstep/src/com/android/quickstep/views/QuickstepDragIndicator.java
deleted file mode 100644
index 5e9cd6e..0000000
--- a/quickstep/src/com/android/quickstep/views/QuickstepDragIndicator.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.views;
-
-import static com.android.launcher3.LauncherState.ALL_APPS;
-import static com.android.launcher3.LauncherState.OVERVIEW;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.accessibility.AccessibilityNodeInfo;
-
-import com.android.launcher3.R;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
-import com.android.launcher3.views.LauncherDragIndicator;
-
-public class QuickstepDragIndicator extends LauncherDragIndicator {
-
- public QuickstepDragIndicator(Context context) {
- super(context);
- }
-
- public QuickstepDragIndicator(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public QuickstepDragIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- private boolean isInOverview() {
- return mLauncher.isInState(OVERVIEW);
- }
-
- @Override
- public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(info);
- info.setContentDescription(getContext().getString(R.string.all_apps_button_label));
- }
-
- @Override
- protected void initCustomActions(AccessibilityNodeInfo info) {
- if (!isInOverview()) {
- super.initCustomActions(info);
- }
- }
-
- @Override
- public void onClick(View view) {
- mLauncher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
- ControlType.ALL_APPS_BUTTON,
- isInOverview() ? ContainerType.TASKSWITCHER : ContainerType.WORKSPACE);
- mLauncher.getStateManager().goToState(ALL_APPS);
- }
-}
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index aa04672..b47af2d 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -31,7 +31,6 @@
import android.util.AttributeSet;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.uioverrides.OverviewState;
import com.android.launcher3.util.Themes;
@@ -49,8 +48,6 @@
private static final int THRESHOLD_ALPHA_DARK = 102;
private static final int THRESHOLD_ALPHA_LIGHT = 46;
- private final Launcher mLauncher;
-
// In transposed layout, we simply draw a flat color.
private boolean mDrawingFlatColor;
@@ -58,7 +55,6 @@
private final int mEndAlpha;
private final int mThresholdAlpha;
private final float mRadius;
- private final float mTopPadding;
private final float mMaxScrimAlpha;
private final Paint mPaint;
@@ -77,15 +73,12 @@
public ShelfScrimView(Context context, AttributeSet attrs) {
super(context, attrs);
-
- mLauncher = Launcher.getLauncher(context);
mMaxScrimAlpha = OVERVIEW.getWorkspaceScrimAlpha(mLauncher);
mEndAlpha = Color.alpha(mEndScrim);
mThresholdAlpha = Themes.getAttrBoolean(mLauncher, R.attr.isMainColorDark)
? THRESHOLD_ALPHA_DARK : THRESHOLD_ALPHA_LIGHT;
mRadius = mLauncher.getResources().getDimension(R.dimen.shelf_surface_radius);
- mTopPadding = mLauncher.getResources().getDimension(R.dimen.shelf_surface_top_padding);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
// Just assume the easiest UI for now, until we have the proper layout information.
@@ -110,10 +103,10 @@
mRemainingScreenPathValid = false;
updateColors();
}
+ updateDragHandleAlpha();
invalidate();
}
-
@Override
public void updateColors() {
super.updateColors();
@@ -131,6 +124,7 @@
(1 - mProgress) / (1 - mMoveThreshold)));
mShelfColor = setAlphaComponent(mEndScrim, alpha);
}
+
mRemainingScreenColor = 0;
} else if (mProgress <= 0) {
mScrimMoveFactor = 0;
@@ -150,23 +144,42 @@
}
@Override
+ protected void updateDragHandleAlpha() {
+ if (mDrawingFlatColor) {
+ super.updateDragHandleAlpha();
+ } else if (mDragHandle != null) {
+ mDragHandle.setAlpha(255);
+ }
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
+ float translate = drawBackground(canvas);
+
+ if (mDragHandle != null) {
+ canvas.translate(0, -translate);
+ mDragHandle.draw(canvas);
+ canvas.translate(0, translate);
+ }
+ }
+
+ private float drawBackground(Canvas canvas) {
if (mDrawingFlatColor) {
if (mCurrentFlatColor != 0) {
canvas.drawColor(mCurrentFlatColor);
}
- return;
+ return 0;
}
if (mShelfColor == 0) {
- return;
+ return 0;
} else if (mScrimMoveFactor <= 0) {
canvas.drawColor(mShelfColor);
- return;
+ return getHeight();
}
float minTop = getHeight() - mMinSize;
- float top = minTop * mScrimMoveFactor - mTopPadding - mRadius;
+ float top = minTop * mScrimMoveFactor - mDragHandleSize;
// Draw the scrim over the remaining screen if needed.
if (mRemainingScreenColor != 0) {
@@ -192,5 +205,6 @@
mPaint.setColor(mShelfColor);
canvas.drawRoundRect(0, top, getWidth(), getHeight() + mRadius,
mRadius, mRadius, mPaint);
+ return minTop - mDragHandleSize - top;
}
}
diff --git a/res/drawable/all_apps_handle_landscape.xml b/res/drawable/drag_handle_indicator.xml
similarity index 77%
rename from res/drawable/all_apps_handle_landscape.xml
rename to res/drawable/drag_handle_indicator.xml
index 15518ff..b01b84a 100644
--- a/res/drawable/all_apps_handle_landscape.xml
+++ b/res/drawable/drag_handle_indicator.xml
@@ -15,25 +15,25 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/dynamic_grid_min_page_indicator_size"
- android:height="@dimen/dynamic_grid_min_page_indicator_size"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0" >
+ android:width="@dimen/vertical_drag_handle_size"
+ android:height="@dimen/vertical_drag_handle_size"
+ android:viewportWidth="36.0"
+ android:viewportHeight="36.0" >
<group
- android:translateX="17.5"
- android:translateY="17.5">
+ android:translateX="11.5"
+ android:translateY="11.5">
<path
android:pathData="M2 8.5L6.5 4L11 8.5"
android:strokeColor="?attr/workspaceAmbientShadowColor"
- android:strokeWidth="4"
+ android:strokeWidth="3.6"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:pathData="M2 8.5L6.5 4L11 8.5"
android:strokeColor="?attr/workspaceTextColor"
- android:strokeWidth="2"
+ android:strokeWidth="1.8"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</group>
diff --git a/res/drawable/ic_drag_indicator.xml b/res/drawable/ic_drag_indicator.xml
deleted file mode 100644
index d50bdd3..0000000
--- a/res/drawable/ic_drag_indicator.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="2dp"
- android:width="16dp"
- android:viewportHeight="2.0"
- android:viewportWidth="16.0">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M1,0h14c0.55,0,1,0.45,1,1s-0.45,1-1,1H1C0.45,2,0,1.55,0,1S0.45,0,1,0z"/>
-</vector>
\ No newline at end of file
diff --git a/res/layout/drag_handle_indicator.xml b/res/layout/drag_handle_indicator.xml
deleted file mode 100644
index d5a7b8a..0000000
--- a/res/layout/drag_handle_indicator.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.launcher3.views.LauncherDragIndicator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/drag_indicator"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@string/all_apps_button_label"
- android:scaleType="centerInside"
- android:tint="?attr/workspaceTextColor" />
diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml
index cd8a425..ec8bd5c 100644
--- a/res/layout/launcher.xml
+++ b/res/layout/launcher.xml
@@ -67,9 +67,6 @@
android:layout_height="match_parent"
android:visibility="invisible" />
- <include android:id="@+id/drag_indicator"
- layout="@layout/drag_handle_indicator" />
-
<!-- DO NOT CHANGE THE ID -->
<include
android:id="@+id/hotseat"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b1ad11e..cd050e8 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -42,6 +42,7 @@
<dimen name="all_apps_scrim_radius">8dp</dimen>
<dimen name="all_apps_scrim_margin">8dp</dimen>
<dimen name="all_apps_scrim_blur">4dp</dimen>
+ <dimen name="vertical_drag_handle_size">24dp</dimen>
<!-- Drop target bar -->
<dimen name="dynamic_grid_drop_target_size">48dp</dimen>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 8088f64..2f83f45 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -196,7 +196,6 @@
private final int[] mTmpAddItemCellCoordinates = new int[2];
@Thunk Hotseat mHotseat;
- private View mDragHandleIndicator;
@Nullable private View mHotseatSearchBox;
private DropTargetBar mDropTargetBar;
@@ -933,7 +932,6 @@
mOverviewPanel = findViewById(R.id.overview_panel);
mOverviewPanelContainer = findViewById(R.id.overview_panel_container);
mHotseat = findViewById(R.id.hotseat);
- mDragHandleIndicator = findViewById(R.id.drag_indicator);
mHotseatSearchBox = findViewById(R.id.search_container_hotseat);
mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
@@ -1194,10 +1192,6 @@
return mHotseat;
}
- public View getDragHandleIndicator() {
- return mDragHandleIndicator;
- }
-
public View getHotseatSearchBox() {
return mHotseatSearchBox;
}
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 6790b7f..4e10ab6 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -51,7 +51,6 @@
public static final int ALL_APPS_HEADER = 1 << 2;
public static final int ALL_APPS_HEADER_EXTRA = 1 << 3; // e.g. app predictions
public static final int ALL_APPS_CONTENT = 1 << 4;
- public static final int DRAG_HANDLE_INDICATOR = 1 << 5;
protected static final int FLAG_MULTI_PAGE = 1 << 0;
protected static final int FLAG_DISABLE_ACCESSIBILITY = 1 << 1;
@@ -197,9 +196,9 @@
public int getVisibleElements(Launcher launcher) {
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
- return HOTSEAT_ICONS | DRAG_HANDLE_INDICATOR;
+ return HOTSEAT_ICONS;
}
- return HOTSEAT_ICONS | DRAG_HANDLE_INDICATOR | HOTSEAT_SEARCH_BOX;
+ return HOTSEAT_ICONS | HOTSEAT_SEARCH_BOX;
}
/**
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 720c574..d870109 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -194,7 +194,7 @@
// Variables relating to the creation of user folders by hovering shortcuts over shortcuts
private static final int FOLDER_CREATION_TIMEOUT = 0;
- public static final int REORDER_TIMEOUT = 350;
+ public static final int REORDER_TIMEOUT = 650;
private final Alarm mFolderCreationAlarm = new Alarm();
private final Alarm mReorderAlarm = new Alarm();
private PreviewBackground mFolderCreateBg;
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 55968db..d6b2349 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.LauncherAnimUtils.DRAWABLE_ALPHA;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
-import static com.android.launcher3.LauncherState.DRAG_HANDLE_INDICATOR;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.HOTSEAT_SEARCH_BOX;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
@@ -103,10 +102,6 @@
(elements & HOTSEAT_SEARCH_BOX) != 0 ? 1 : 0,
pageAlphaProvider.interpolator);
- propertySetter.setViewAlpha(mLauncher.getDragHandleIndicator(),
- (elements & DRAG_HANDLE_INDICATOR) != 0 ? 1 : 0,
- pageAlphaProvider.interpolator);
-
// Set scrim
propertySetter.setFloat(ViewScrim.get(mWorkspace), ViewScrim.PROGRESS,
state.getWorkspaceScrimAlpha(mLauncher), Interpolators.LINEAR);
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 4a0b622..113571a 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -101,7 +101,6 @@
mAppsView.setAlpha(1);
mLauncher.getHotseat().setTranslationY(0);
mLauncher.getWorkspace().getPageIndicator().setTranslationY(0);
- mLauncher.getDragHandleIndicator().setTranslationY(0);
}
}
@@ -125,7 +124,6 @@
if (!mIsVerticalLayout) {
mLauncher.getHotseat().setTranslationY(hotseatTranslation);
mLauncher.getWorkspace().getPageIndicator().setTranslationY(hotseatTranslation);
- mLauncher.getDragHandleIndicator().setTranslationY(hotseatTranslation);
}
// Use a light system UI (dark icons) if all apps is behind at least half of the
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index 06ddf22..0d388fe 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -38,6 +38,7 @@
public static final Interpolator DEACCEL = new DecelerateInterpolator();
public static final Interpolator DEACCEL_1_5 = new DecelerateInterpolator(1.5f);
+ public static final Interpolator DEACCEL_1_7 = new DecelerateInterpolator(1.7f);
public static final Interpolator DEACCEL_2 = new DecelerateInterpolator(2);
public static final Interpolator DEACCEL_2_5 = new DecelerateInterpolator(2.5f);
public static final Interpolator DEACCEL_3 = new DecelerateInterpolator(3f);
@@ -57,8 +58,6 @@
EXAGGERATED_EASE = new PathInterpolator(exaggeratedEase);
}
- public static final Interpolator APP_CLOSE_ALPHA = new PathInterpolator(0.4f, 0, 1f, 1f);
-
public static final Interpolator OVERSHOOT_0 = new OvershootInterpolator(0);
public static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
diff --git a/src/com/android/launcher3/views/LauncherDragIndicator.java b/src/com/android/launcher3/views/LauncherDragIndicator.java
deleted file mode 100644
index 986e4be..0000000
--- a/src/com/android/launcher3/views/LauncherDragIndicator.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.views;
-
-import static com.android.launcher3.LauncherState.ALL_APPS;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Insettable;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
-
-public class LauncherDragIndicator extends ImageView implements Insettable, OnClickListener {
-
- private static final int WALLPAPERS = R.string.wallpaper_button_text;
- private static final int WIDGETS = R.string.widget_button_text;
- private static final int SETTINGS = R.string.settings_button_text;
-
- protected final Launcher mLauncher;
-
- public LauncherDragIndicator(Context context) {
- this(context, null);
- }
-
- public LauncherDragIndicator(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public LauncherDragIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- mLauncher = Launcher.getLauncher(context);
- setOnClickListener(this);
- }
-
- @Override
- public void setInsets(Rect insets) {
- DeviceProfile grid = mLauncher.getDeviceProfile();
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
-
- if (grid.isVerticalBarLayout()) {
- if (grid.isSeascape()) {
- lp.leftMargin = grid.hotseatBarSidePaddingPx;
- lp.rightMargin = insets.right;
- lp.gravity = Gravity.RIGHT | Gravity.BOTTOM;
- } else {
- lp.leftMargin = insets.left;
- lp.rightMargin = grid.hotseatBarSidePaddingPx;
- lp.gravity = Gravity.LEFT | Gravity.BOTTOM;
- }
- lp.bottomMargin = grid.workspacePadding.bottom;
- setImageResource(R.drawable.all_apps_handle_landscape);
- } else {
- lp.leftMargin = lp.rightMargin = 0;
- lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
- lp.bottomMargin = getPortraitBottomMargin(grid, insets);
- setImageResource(R.drawable.ic_drag_indicator);
- }
-
- lp.width = lp.height = grid.pageIndicatorSizePx;
- setLayoutParams(lp);
- }
-
- protected int getPortraitBottomMargin(DeviceProfile grid, Rect insets) {
- return grid.hotseatBarSizePx + insets.bottom - grid.pageIndicatorSizePx;
- }
-
- @Override
- public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(info);
- initCustomActions(info);
- }
-
- protected void initCustomActions(AccessibilityNodeInfo info) {
- Context context = getContext();
- if (Utilities.isWallpaperAllowed(context)) {
- info.addAction(new AccessibilityAction(WALLPAPERS, context.getText(WALLPAPERS)));
- }
- info.addAction(new AccessibilityAction(WIDGETS, context.getText(WIDGETS)));
- info.addAction(new AccessibilityAction(SETTINGS, context.getText(SETTINGS)));
- }
-
- @Override
- public boolean performAccessibilityAction(int action, Bundle arguments) {
- if (action == WALLPAPERS) {
- return OptionsPopupView.startWallpaperPicker(this);
- } else if (action == WIDGETS) {
- return OptionsPopupView.onWidgetsClicked(this);
- } else if (action == SETTINGS) {
- return OptionsPopupView.startSettings(this);
- }
- return super.performAccessibilityAction(action, arguments);
- }
-
- @Override
- public void onClick(View view) {
- if (!mLauncher.isInState(ALL_APPS)) {
- mLauncher.getUserEventDispatcher().logActionOnControl(
- Action.Touch.TAP, ControlType.ALL_APPS_BUTTON);
- mLauncher.getStateManager().goToState(ALL_APPS);
- }
- }
-}
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index b49b565..28602f5 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -15,28 +15,63 @@
*/
package com.android.launcher3.views;
+import static android.content.Context.ACCESSIBILITY_SERVICE;
import static android.support.v4.graphics.ColorUtils.compositeColors;
import static android.support.v4.graphics.ColorUtils.setAlphaComponent;
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
+import android.support.v4.widget.ExploreByTouchHelper;
import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager;
+import com.android.launcher3.LauncherStateManager.StateListener;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.uioverrides.WallpaperColorInfo;
import com.android.launcher3.uioverrides.WallpaperColorInfo.OnChangeListener;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import com.android.launcher3.util.Themes;
+import java.util.List;
+
/**
* Simple scrim which draws a flat color
*/
-public class ScrimView extends View implements Insettable, OnChangeListener {
+public class ScrimView extends View implements Insettable, OnChangeListener,
+ AccessibilityStateChangeListener, StateListener {
+ private static final int WALLPAPERS = R.string.wallpaper_button_text;
+ private static final int WIDGETS = R.string.widget_button_text;
+ private static final int SETTINGS = R.string.settings_button_text;
+
+ private final Rect mTempRect = new Rect();
+ private final int[] mTempPos = new int[2];
+
+ protected final Launcher mLauncher;
private final WallpaperColorInfo mWallpaperColorInfo;
+ private final AccessibilityManager mAM;
protected final int mEndScrim;
protected float mMaxScrimAlpha;
@@ -48,28 +83,56 @@
protected int mEndFlatColor;
protected int mEndFlatColorAlpha;
+ protected final int mDragHandleSize;
+ private final Rect mDragHandleBounds;
+ private final AccessibilityHelper mAccessibilityHelper;
+ @Nullable
+ protected Drawable mDragHandle;
+
public ScrimView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mLauncher = Launcher.getLauncher(context);
mWallpaperColorInfo = WallpaperColorInfo.getInstance(context);
mEndScrim = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
mMaxScrimAlpha = 0.7f;
+
+ mDragHandleSize = context.getResources()
+ .getDimensionPixelSize(R.dimen.vertical_drag_handle_size);
+ mDragHandleBounds = new Rect(0, 0, mDragHandleSize, mDragHandleSize);
+
+ mAccessibilityHelper = new AccessibilityHelper();
+ ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
+
+ mAM = (AccessibilityManager) context.getSystemService(ACCESSIBILITY_SERVICE);
}
@Override
- public void setInsets(Rect insets) { }
+ public void setInsets(Rect insets) {
+ updateDragHandleBounds();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ updateDragHandleBounds();
+ }
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mWallpaperColorInfo.addOnChangeListener(this);
onExtractedColorsChanged(mWallpaperColorInfo);
+
+ mAM.addAccessibilityStateChangeListener(this);
+ onAccessibilityStateChanged(mAM.isEnabled());
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mWallpaperColorInfo.removeOnChangeListener(this);
+ mAM.removeAccessibilityStateChangeListener(this);
}
@Override
@@ -91,6 +154,7 @@
if (mProgress != progress) {
mProgress = progress;
updateColors();
+ updateDragHandleAlpha();
invalidate();
}
}
@@ -102,10 +166,158 @@
mEndFlatColor, Math.round((1 - mProgress) * mEndFlatColorAlpha));
}
+ protected void updateDragHandleAlpha() {
+ if (mDragHandle != null) {
+ mDragHandle.setAlpha(Math.round(255 * Utilities.boundToRange(mProgress, 0, 1)));
+ }
+ }
+
@Override
protected void onDraw(Canvas canvas) {
if (mCurrentFlatColor != 0) {
canvas.drawColor(mCurrentFlatColor);
}
}
+
+ protected void updateDragHandleBounds() {
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ final int left;
+ final int width = getMeasuredWidth();
+ final int top = getMeasuredHeight() - mDragHandleSize - grid.getInsets().bottom;
+ final int topMargin;
+
+ if (grid.isVerticalBarLayout()) {
+ topMargin = grid.workspacePadding.bottom;
+ if (grid.isSeascape()) {
+ left = width - grid.getInsets().right - mDragHandleSize;
+ } else {
+ left = mDragHandleSize + grid.getInsets().left;
+ }
+ } else {
+ left = (width - mDragHandleSize) / 2;
+ topMargin = grid.hotseatBarSizePx;
+ }
+ mDragHandleBounds.offsetTo(left, top - topMargin);
+
+ if (mDragHandle != null) {
+ mDragHandle.setBounds(mDragHandleBounds);
+ }
+ }
+
+ @Override
+ public void onAccessibilityStateChanged(boolean enabled) {
+ LauncherStateManager stateManager = mLauncher.getStateManager();
+ stateManager.removeStateListener(this);
+
+ if (enabled) {
+ mDragHandle = mLauncher.getDrawable(R.drawable.drag_handle_indicator);
+ mDragHandle.setBounds(mDragHandleBounds);
+
+ stateManager.addStateListener(this);
+ onStateSetImmediately(mLauncher.getStateManager().getState());
+
+ updateDragHandleAlpha();
+ } else {
+ mDragHandle = null;
+ }
+ invalidate();
+ }
+
+ @Override
+ public boolean dispatchHoverEvent(MotionEvent event) {
+ return mAccessibilityHelper.dispatchHoverEvent(event) || super.dispatchHoverEvent(event);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ return mAccessibilityHelper.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public void onFocusChanged(boolean gainFocus, int direction,
+ Rect previouslyFocusedRect) {
+ super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+ mAccessibilityHelper.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+ }
+
+ @Override
+ public void onStateTransitionStart(LauncherState toState) {}
+
+ @Override
+ public void onStateTransitionComplete(LauncherState finalState) {
+ onStateSetImmediately(finalState);
+ }
+
+ @Override
+ public void onStateSetImmediately(LauncherState state) {
+ setImportantForAccessibility(state == ALL_APPS
+ ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+ : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+ }
+
+ private class AccessibilityHelper extends ExploreByTouchHelper {
+
+ private static final int DRAG_HANDLE_ID = 1;
+
+ public AccessibilityHelper() {
+ super(ScrimView.this);
+ }
+
+ @Override
+ protected int getVirtualViewAt(float x, float y) {
+ return mDragHandleBounds.contains((int) x, (int) y)
+ ? DRAG_HANDLE_ID : INVALID_ID;
+ }
+
+ @Override
+ protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
+ virtualViewIds.add(DRAG_HANDLE_ID);
+ }
+
+ @Override
+ protected void onPopulateNodeForVirtualView(int virtualViewId,
+ AccessibilityNodeInfoCompat node) {
+ node.setContentDescription(getContext().getString(R.string.all_apps_button_label));
+ node.setBoundsInParent(mDragHandleBounds);
+
+ getLocationOnScreen(mTempPos);
+ mTempRect.set(mDragHandleBounds);
+ mTempRect.offset(mTempPos[0], mTempPos[1]);
+ node.setBoundsInScreen(mTempRect);
+
+ node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
+ node.setClickable(true);
+ node.setFocusable(true);
+
+ if (mLauncher.isInState(NORMAL)) {
+ Context context = getContext();
+ if (Utilities.isWallpaperAllowed(context)) {
+ node.addAction(
+ new AccessibilityActionCompat(WALLPAPERS, context.getText(WALLPAPERS)));
+ }
+ node.addAction(new AccessibilityActionCompat(WIDGETS, context.getText(WIDGETS)));
+ node.addAction(new AccessibilityActionCompat(SETTINGS, context.getText(SETTINGS)));
+ }
+ }
+
+ @Override
+ protected boolean onPerformActionForVirtualView(
+ int virtualViewId, int action, Bundle arguments) {
+ if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
+ mLauncher.getUserEventDispatcher().logActionOnControl(
+ Action.Touch.TAP, ControlType.ALL_APPS_BUTTON,
+ mLauncher.getStateManager().getState().containerType);
+ mLauncher.getStateManager().goToState(ALL_APPS);
+ return true;
+ } else if (action == WALLPAPERS) {
+ return OptionsPopupView.startWallpaperPicker(ScrimView.this);
+ } else if (action == WIDGETS) {
+ return OptionsPopupView.onWidgetsClicked(ScrimView.this);
+ } else if (action == SETTINGS) {
+ return OptionsPopupView.startSettings(ScrimView.this);
+ }
+
+ return false;
+ }
+ }
}