Merge "Increasing the size of the drag icon when a shortcut is dragged" into ub-launcher3-calgary
diff --git a/res/anim/discovery_bounce.xml b/res/anim/discovery_bounce.xml
new file mode 100644
index 0000000..1f7d466
--- /dev/null
+++ b/res/anim/discovery_bounce.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:ordering="sequentially"
+ android:startOffset="200">
+
+ <objectAnimator
+ android:propertyName="progress"
+ android:duration="250"
+ android:interpolator="@interpolator/disco_bounce_section1"
+ android:valueFrom="1f"
+ android:valueTo=".94f"
+ android:valueType="floatType"/>
+ <objectAnimator
+ android:propertyName="progress"
+ android:duration="216"
+ android:interpolator="@interpolator/disco_bounce_section2"
+ android:valueFrom=".94f"
+ android:valueTo="1.012f"
+ android:valueType="floatType"/>
+ <objectAnimator
+ android:propertyName="progress"
+ android:duration="234"
+ android:interpolator="@interpolator/disco_bounce_section3"
+ android:valueFrom="1.012f"
+ android:valueTo="1f"
+ android:valueType="floatType"/>
+</set>
diff --git a/res/interpolator/disco_bounce_section1.xml b/res/interpolator/disco_bounce_section1.xml
new file mode 100644
index 0000000..2156216
--- /dev/null
+++ b/res/interpolator/disco_bounce_section1.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:controlX1="0.9"
+ android:controlY1="0"
+ android:controlX2="0.5"
+ android:controlY2="1"/>
diff --git a/res/interpolator/disco_bounce_section2.xml b/res/interpolator/disco_bounce_section2.xml
new file mode 100644
index 0000000..86cc789
--- /dev/null
+++ b/res/interpolator/disco_bounce_section2.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:controlX1="0.9"
+ android:controlY1="0"
+ android:controlX2="0.6"
+ android:controlY2="1"/>
diff --git a/res/interpolator/disco_bounce_section3.xml b/res/interpolator/disco_bounce_section3.xml
new file mode 100644
index 0000000..1acef03
--- /dev/null
+++ b/res/interpolator/disco_bounce_section3.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:controlX1="0.1"
+ android:controlY1="0"
+ android:controlX2="0.7"
+ android:controlY2="1"/>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index d277bc6..43c7281 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -198,6 +198,7 @@
static final String INTRO_SCREEN_DISMISSED = "launcher.intro_screen_dismissed";
static final String FIRST_RUN_ACTIVITY_DISPLAYED = "launcher.first_run_activity_displayed";
+ static final String APPS_VIEW_SHOWN = "launcher.apps_view_shown";
/** The different states that Launcher can be in. */
enum State { NONE, WORKSPACE, WORKSPACE_SPRING_LOADED, APPS, APPS_SPRING_LOADED,
@@ -288,6 +289,7 @@
private IconCache mIconCache;
private ExtractedColors mExtractedColors;
private LauncherAccessibilityDelegate mAccessibilityDelegate;
+ private boolean mIsResumeFromActionScreenOff;
@Thunk boolean mUserPresent = true;
private boolean mVisible = false;
private boolean mHasFocus = false;
@@ -1079,6 +1081,10 @@
InstallShortcutReceiver.disableAndFlushInstallQueue(this);
}
+ if (shouldShowDiscoveryBounce()) {
+ mAllAppsController.showDiscoveryBounce();
+ }
+ mIsResumeFromActionScreenOff = false;
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onResume();
}
@@ -1623,6 +1629,7 @@
mAppsView.reset();
}
}
+ mIsResumeFromActionScreenOff = true;
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
mUserPresent = true;
updateAutoAdvanceState();
@@ -2591,7 +2598,7 @@
protected void onClickAllAppsButton(View v) {
if (LOGD) Log.d(TAG, "onClickAllAppsButton");
if (!isAppsViewVisible()) {
- mUserEventDispatcher.logActionOnControl(LauncherLogProto.Action.TAP,
+ getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.TAP,
LauncherLogProto.ALL_APPS_BUTTON);
showAppsView(true /* animated */, false /* resetListToTop */,
true /* updatePredictedApps */, false /* focusSearchBar */);
@@ -2601,7 +2608,7 @@
protected void onLongClickAllAppsButton(View v) {
if (LOGD) Log.d(TAG, "onLongClickAllAppsButton");
if (!isAppsViewVisible()) {
- mUserEventDispatcher.logActionOnControl(LauncherLogProto.Action.LONGPRESS,
+ getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.LONGPRESS,
LauncherLogProto.ALL_APPS_BUTTON);
showAppsView(true /* animated */, false /* resetListToTop */,
true /* updatePredictedApps */, true /* focusSearchBar */);
@@ -3348,6 +3355,7 @@
*/
public void showAppsView(boolean animated, boolean resetListToTop, boolean updatePredictedApps,
boolean focusSearchBar) {
+ markAppsViewShown();
if (resetListToTop) {
mAppsView.scrollToTop();
}
@@ -4358,10 +4366,6 @@
!mSharedPrefs.getBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, false);
}
- protected boolean hasRunFirstRunActivity() {
- return mSharedPrefs.getBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, false);
- }
-
public boolean showFirstRunActivity() {
if (shouldRunFirstRunActivity() &&
hasFirstRunActivity()) {
@@ -4381,6 +4385,29 @@
editor.apply();
}
+ private void markAppsViewShown() {
+ if (mSharedPrefs.getBoolean(APPS_VIEW_SHOWN, false)) {
+ return;
+ }
+ mSharedPrefs.edit().putBoolean(APPS_VIEW_SHOWN, true).apply();
+ }
+
+ private boolean shouldShowDiscoveryBounce() {
+ if (mState != mState.WORKSPACE) {
+ return false;
+ }
+ if (mLauncherCallbacks != null && mLauncherCallbacks.shouldShowDiscoveryBounce()) {
+ return true;
+ }
+ if (!mIsResumeFromActionScreenOff) {
+ return false;
+ }
+ if (mSharedPrefs.getBoolean(APPS_VIEW_SHOWN, false)) {
+ return false;
+ }
+ return true;
+ }
+
/**
* To be overridden by subclasses to indicate that there is an in-activity full-screen intro
* screen that must be displayed and dismissed.
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index e971631..2bbe0fb 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -110,4 +110,6 @@
* but for implementation purposes is passed around as an object.
*/
public void setLauncherSearchCallback(Object callbacks);
+
+ public boolean shouldShowDiscoveryBounce();
}
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 136308b..78280f7 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -1,6 +1,7 @@
package com.android.launcher3.allapps;
import android.animation.Animator;
+import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
@@ -13,15 +14,15 @@
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
-import com.android.launcher3.pageindicators.CaretDrawable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
-import com.android.launcher3.Workspace.Direction;
+import com.android.launcher3.pageindicators.CaretDrawable;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.TouchController;
@@ -64,15 +65,15 @@
private final VerticalPullDetector mDetector;
private final ArgbEvaluator mEvaluator;
- // Animation in this class is controlled by a single variable {@link mShiftCurrent}.
- // Visually, it represents top y coordinate of the all apps container. Using the
- // {@link mShiftRange} as the denominator, this fraction value ranges in [0, 1].
- //
- // When {@link mShiftCurrent} is 0, all apps container is pulled up.
- // When {@link mShiftCurrent} is {@link mShirtRange}, all apps container is pulled down.
+ // Animation in this class is controlled by a single variable {@link mProgress}.
+ // Visually, it represents top y coordinate of the all apps container if multiplied with
+ // {@link mShiftRange}.
+
+ // When {@link mProgress} is 0, all apps container is pulled up.
+ // When {@link mProgress} is 1, all apps container is pulled down.
private float mShiftStart; // [0, mShiftRange]
- private float mShiftCurrent; // [0, mShiftRange]
private float mShiftRange; // changes depending on the orientation
+ private float mProgress; // [0, 1], mShiftRange * mProgress = shiftCurrent
private static final float DEFAULT_SHIFT_RANGE = 10;
@@ -86,20 +87,26 @@
private boolean mLightStatusBar;
- public AllAppsTransitionController(Launcher launcher) {
- mLauncher = launcher;
- mDetector = new VerticalPullDetector(launcher);
+ // Used in discovery bounce animation to provide the transition without workspace changing.
+ private boolean mIsTranslateWithoutWorkspace = false;
+ private AnimatorSet mDiscoBounceAnimation;
+
+ public AllAppsTransitionController(Launcher l) {
+ mLauncher = l;
+ mDetector = new VerticalPullDetector(l);
mDetector.setListener(this);
- mShiftCurrent = mShiftRange = DEFAULT_SHIFT_RANGE;
- mBezelSwipeUpHeight = launcher.getResources().getDimensionPixelSize(
+ mShiftRange = DEFAULT_SHIFT_RANGE;
+ mProgress = 1f;
+ mBezelSwipeUpHeight = l.getResources().getDimensionPixelSize(
R.dimen.all_apps_bezel_swipe_height);
- mCaretAnimationDuration = launcher.getResources().getInteger(
+ mCaretAnimationDuration = l.getResources().getInteger(
R.integer.config_caretAnimationDuration);
- mCaretInterpolator = AnimationUtils.loadInterpolator(launcher,
+ mCaretInterpolator = AnimationUtils.loadInterpolator(l,
R.interpolator.caret_animation_interpolator);
+
mEvaluator = new ArgbEvaluator();
- mAllAppsBackgroundColor = launcher.getColor(R.color.all_apps_container_color);
+ mAllAppsBackgroundColor = l.getColor(R.color.all_apps_container_color);
}
@Override
@@ -175,11 +182,11 @@
}
private boolean isInDisallowRecatchTopZone() {
- return mShiftCurrent / mShiftRange < RECATCH_REJECTION_FRACTION;
+ return mProgress < RECATCH_REJECTION_FRACTION;
}
private boolean isInDisallowRecatchBottomZone() {
- return mShiftCurrent / mShiftRange > 1 - RECATCH_REJECTION_FRACTION;
+ return mProgress > 1 - RECATCH_REJECTION_FRACTION;
}
@Override
@@ -195,8 +202,8 @@
if (mAppsView == null) {
return false; // early termination.
}
- float progress = Math.min(Math.max(0, mShiftStart + displacement), mShiftRange);
- setProgress(progress);
+ float shift = Math.min(Math.max(0, mShiftStart + displacement), mShiftRange);
+ setProgress(shift / mShiftRange);
return true;
}
@@ -271,13 +278,11 @@
mAppsView.getRevealView().setVisibility(View.VISIBLE);
mAppsView.setRevealDrawableColor(mHotseatBackgroundColor);
}
- } else {
- setProgress(mShiftCurrent);
}
}
- private void updateLightStatusBar(float progress) {
- boolean enable = progress <= mStatusBarHeight / 2;
+ private void updateLightStatusBar(float shift) {
+ boolean enable = shift <= mStatusBarHeight / 2;
// Do not modify status bar on landscape as all apps is not full bleed.
if (mLauncher.getDeviceProfile().isVerticalBarLayout()) {
return;
@@ -300,38 +305,43 @@
}
/**
- * @param progress y value of the border between hotseat and all apps
+ * @param progress value between 0 and 1
*/
public void setProgress(float progress) {
- updateLightStatusBar(progress);
- mShiftCurrent = progress;
- float alpha = calcAlphaAllApps(progress);
- float workspaceHotseatAlpha = 1 - alpha;
+ mProgress = progress;
+ float shiftCurrent = progress * mShiftRange;
+
+ float workspaceHotseatAlpha = Utilities.boundToRange(progress, 0f, 1f);
+ float alpha = 1 - workspaceHotseatAlpha;
+
float interpolation = mAccelInterpolator.getInterpolation(workspaceHotseatAlpha);
- int color = (Integer) mEvaluator.evaluate(mDecelInterpolator.getInterpolation(alpha),
+ int color = (Integer) mEvaluator.evaluate(alpha,
mHotseatBackgroundColor, mAllAppsBackgroundColor);
mAppsView.setRevealDrawableColor(color);
mAppsView.getContentView().setAlpha(alpha);
- mAppsView.setTranslationY(progress);
- mWorkspace.setWorkspaceYTranslationAndAlpha(
- PARALLAX_COEFFICIENT * (-mShiftRange + progress),
- interpolation);
- if (mLauncher.getDeviceProfile().isVerticalBarLayout()) {
- mWorkspace.setHotseatTranslationAndAlpha(Direction.Y,
- PARALLAX_COEFFICIENT * (-mShiftRange + progress), interpolation);
+ mAppsView.setTranslationY(shiftCurrent);
+
+ if (!mLauncher.getDeviceProfile().isVerticalBarLayout()) {
+ mWorkspace.setHotseatTranslationAndAlpha(Workspace.Direction.Y, -mShiftRange + shiftCurrent,
+ interpolation);
} else {
- mWorkspace.setHotseatTranslationAndAlpha(Direction.Y,
- -mShiftRange + progress, interpolation);
+ mWorkspace.setHotseatTranslationAndAlpha(Workspace.Direction.Y,
+ PARALLAX_COEFFICIENT * (-mShiftRange + shiftCurrent),
+ interpolation);
}
+
+ if (mIsTranslateWithoutWorkspace) {
+ return;
+ }
+ mWorkspace.setWorkspaceYTranslationAndAlpha(
+ PARALLAX_COEFFICIENT * (-mShiftRange + shiftCurrent),
+ interpolation);
+ updateLightStatusBar(shiftCurrent);
}
public float getProgress() {
- return mShiftCurrent;
- }
-
- private float calcAlphaAllApps(float progress) {
- return ((mShiftRange - progress) / mShiftRange);
+ return mProgress;
}
private void calculateDuration(float velocity, float disp) {
@@ -354,10 +364,8 @@
mShiftStart = mAppsView.getTranslationY();
}
final float fromAllAppsTop = mAppsView.getTranslationY();
- final float toAllAppsTop = 0;
-
ObjectAnimator driftAndAlpha = ObjectAnimator.ofFloat(this, "progress",
- fromAllAppsTop, toAllAppsTop);
+ fromAllAppsTop / mShiftRange, 0f);
driftAndAlpha.setDuration(mAnimationDuration);
driftAndAlpha.setInterpolator(new PagedView.ScrollInterpolator());
animationOut.play(driftAndAlpha);
@@ -387,6 +395,36 @@
}
}
+ public void showDiscoveryBounce() {
+ // cancel existing animation in case user locked and unlocked at a super human speed.
+ cancelDiscoveryAnimation();
+
+ // assumption is that this variable is always null
+ mDiscoBounceAnimation = (AnimatorSet) AnimatorInflater.loadAnimator(mLauncher,
+ R.anim.discovery_bounce);
+ mDiscoBounceAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+ mIsTranslateWithoutWorkspace = true;
+ preparePull(true);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ finishPullDown(false);
+ mDiscoBounceAnimation = null;
+ mIsTranslateWithoutWorkspace = false;
+ }
+ });
+ mDiscoBounceAnimation.setTarget(this);
+ mAppsView.post(new Runnable() {
+ @Override
+ public void run() {
+ mDiscoBounceAnimation.start();
+ }
+ });
+ }
+
public void animateToWorkspace(AnimatorSet animationOut, long duration, boolean start) {
if (animationOut == null) {
return;
@@ -397,10 +435,9 @@
mShiftStart = mAppsView.getTranslationY();
}
final float fromAllAppsTop = mAppsView.getTranslationY();
- final float toAllAppsTop = mShiftRange;
ObjectAnimator driftAndAlpha = ObjectAnimator.ofFloat(this, "progress",
- fromAllAppsTop, toAllAppsTop);
+ fromAllAppsTop / mShiftRange, 1f);
driftAndAlpha.setDuration(mAnimationDuration);
driftAndAlpha.setInterpolator(new PagedView.ScrollInterpolator());
animationOut.play(driftAndAlpha);
@@ -411,7 +448,6 @@
@Override
public void onAnimationCancel(Animator animation) {
canceled = true;
- setProgress(mShiftCurrent);
}
@Override
@@ -442,7 +478,7 @@
mHotseat.setBackgroundTransparent(false /* transparent */);
mHotseat.setVisibility(View.VISIBLE);
mAppsView.reset();
- setProgress(mShiftRange);
+ setProgress(1f);
if (animated) {
animateCaret();
} else {
@@ -453,10 +489,18 @@
private void cancelAnimation() {
if (mCurrentAnimation != null) {
- mCurrentAnimation.setDuration(0);
mCurrentAnimation.cancel();
mCurrentAnimation = null;
}
+ cancelDiscoveryAnimation();
+ }
+
+ public void cancelDiscoveryAnimation() {
+ if (mDiscoBounceAnimation == null) {
+ return;
+ }
+ mDiscoBounceAnimation.cancel();
+ mDiscoBounceAnimation = null;
}
private void cleanUpAnimation() {
@@ -490,13 +534,14 @@
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- float prevShiftRatio = mShiftCurrent / mShiftRange;
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (!mLauncher.getDeviceProfile().isVerticalBarLayout()) {
mShiftRange = top;
} else {
mShiftRange = bottom;
}
- setProgress(mShiftRange * prevShiftRatio);
+ setProgress(mProgress);
}
+
+
}
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 5f8faab..28b6f3e 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -280,6 +280,10 @@
int action = ev.getAction();
if (action == MotionEvent.ACTION_DOWN) {
+ // Cancel discovery bounce animation when a user start interacting on anywhere on
+ // dray layer even if mAllAppsController is NOT the active controller.
+ // TODO: handle other input other than touch
+ mAllAppsController.cancelDiscoveryAnimation();
if (handleTouchDown(ev, true)) {
return true;
}
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
index dffe2db..8091825 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
@@ -76,7 +76,7 @@
private final int mStartDragThreshold;
private BubbleTextView mDeferredDragIcon;
private int mActivePointerId;
- private Point mTouchDown = null;
+ private int[] mTouchDown = null;
private DragView mDragView;
private float mLastX, mLastY;
private float mDistanceDragged = 0;
@@ -237,7 +237,7 @@
/**
* Orients this container above or below the given icon, aligning with the left or right.
*
- * These are the preferred orientations, in order:
+ * These are the preferred orientations, in order (RTL prefers right-aligned over left):
* - Above and left-aligned
* - Above and right-aligned
* - Below and left-aligned
@@ -254,16 +254,25 @@
DragLayer dragLayer = mLauncher.getDragLayer();
dragLayer.getDescendantRectRelativeToSelf(icon, mTempRect);
- // Align left and above by default.
- int x = mTempRect.left + icon.getPaddingLeft();
- int y = mTempRect.top - height;
Rect insets = dragLayer.getInsets();
- mIsLeftAligned = x + width < dragLayer.getRight() - insets.right;
- if (!mIsLeftAligned) {
- x = mTempRect.right - width - icon.getPaddingRight();
+ // Align left (right in RTL) if there is room.
+ boolean isRtl = Utilities.isRtl(getResources());
+ int leftAlignedX = mTempRect.left + icon.getPaddingLeft();
+ int rightAlignedX = mTempRect.right - width - icon.getPaddingRight();
+ int x = leftAlignedX;
+ boolean canBeLeftAligned = leftAlignedX + width < dragLayer.getRight() - insets.right;
+ boolean canBeRightAligned = rightAlignedX > dragLayer.getLeft() + insets.left;
+ if (!canBeLeftAligned || (isRtl && canBeRightAligned)) {
+ x = rightAlignedX;
+ }
+ mIsLeftAligned = x == leftAlignedX;
+ if (isRtl) {
+ x -= dragLayer.getWidth() - width;
}
+ // Open above icon if there is room.
+ int y = mTempRect.top - height;
mIsAboveIcon = mTempRect.top - height > dragLayer.getTop() + insets.top;
if (!mIsAboveIcon) {
y = mTempRect.bottom;
@@ -304,7 +313,7 @@
mDragView.show(motionDownX, motionDownY);
}
- public boolean onForwardedEvent(MotionEvent ev, int activePointerId, Point touchDown) {
+ public boolean onForwardedEvent(MotionEvent ev, int activePointerId, int[] touchDown) {
mActivePointerId = activePointerId;
mTouchDown = touchDown;
return dispatchTouchEvent(ev);
@@ -398,9 +407,9 @@
*/
private boolean shouldStartDeferredDrag(int x, int y, boolean containerContainsTouch) {
int closestEdgeY = mIsAboveIcon ? getMeasuredHeight() : 0;
- double distToEdge = Math.abs(mTouchDown.y - closestEdgeY);
- double newDistToEdge = Math.hypot(x - mTouchDown.x, y - closestEdgeY);
- return !containerContainsTouch && (newDistToEdge - distToEdge > mStartDragThreshold);
+ double distToEdge = Math.abs(mTouchDown[1] - closestEdgeY);
+ double newDistToEdge = Math.hypot(x - mTouchDown[0], y - closestEdgeY);
+ return !containerContainsTouch && (newDistToEdge - distToEdge > mStartDragThreshold);
}
public void cleanupDeferredDrag() {
diff --git a/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java b/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
index 63c8363..962fbac 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
@@ -1,7 +1,6 @@
package com.android.launcher3.shortcuts;
import android.content.Context;
-import android.graphics.Point;
import android.os.SystemClock;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
@@ -53,9 +52,9 @@
private Launcher mLauncher;
private DragLayer mDragLayer;
- private MotionEvent mTouchDownEvent;
- /** The coordinates of the touch down, relative do the shortcuts container. */
- private final Point mTouchDown;
+ /** The coordinates of the touch down, relative to the shortcuts container. */
+ private final int[] mTouchDown;
+ private boolean mHasMappedTouchDownToContainerCoord;
public ShortcutsContainerListener(BubbleTextView icon) {
mSrcIcon = icon;
@@ -68,7 +67,7 @@
mLauncher = Launcher.getLauncher(mSrcIcon.getContext());
mDragLayer = mLauncher.getDragLayer();
- mTouchDown = new Point();
+ mTouchDown = new int[2];
}
@Override
@@ -79,10 +78,10 @@
}
if (event.getAction() == MotionEvent.ACTION_DOWN) {
- if (mTouchDownEvent != null) {
- mTouchDownEvent.recycle();
- }
- mTouchDownEvent = MotionEvent.obtainNoHistory(event);
+ mTouchDown[0] = (int) event.getX();
+ mTouchDown[1] = (int) event.getY();
+ mDragLayer.getDescendantCoordRelativeToSelf(mSrcIcon, mTouchDown);
+ mHasMappedTouchDownToContainerCoord = false;
}
final boolean wasForwarding = mForwarding;
@@ -140,10 +139,6 @@
deepShortcutsContainer.populateAndShow(mSrcIcon, ids);
mSrcIcon.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
-
- // Convert touch down event to the container's coordinates.
- Utilities.translateEventCoordinates(mSrcIcon, deepShortcutsContainer, mTouchDownEvent);
- mTouchDown.set((int) mTouchDownEvent.getX(), (int) mTouchDownEvent.getY());
return true;
}
return false;
@@ -257,13 +252,21 @@
if (dst == null) {
return false;
}
+ if (!dst.isLaidOut()) {
+ return true;
+ }
// Convert event to destination-local coordinates.
final MotionEvent dstEvent = MotionEvent.obtainNoHistory(srcEvent);
Utilities.translateEventCoordinates(src, dst, dstEvent);
+ // Convert touch down event to destination-local coordinates.
+ if (!mHasMappedTouchDownToContainerCoord) {
+ mDragLayer.mapCoordInSelfToDescendent(dst, mTouchDown);
+ mHasMappedTouchDownToContainerCoord = true;
+ }
+
// Forward converted event to destination view, then recycle it.
- // TODO: don't create objects in onForwardedEvent.
final boolean handled = dst.onForwardedEvent(dstEvent, mActivePointerId, mTouchDown);
dstEvent.recycle();
diff --git a/src/com/android/launcher3/testing/LauncherExtension.java b/src/com/android/launcher3/testing/LauncherExtension.java
index c62ce0e..ae552d2 100644
--- a/src/com/android/launcher3/testing/LauncherExtension.java
+++ b/src/com/android/launcher3/testing/LauncherExtension.java
@@ -255,5 +255,10 @@
@Override
public void onDetachedFromWindow() {
}
+
+ @Override
+ public boolean shouldShowDiscoveryBounce() {
+ return false;
+ }
}
}