Merge "Fix disco bounce crash b/30413641" into ub-launcher3-calgary
diff --git a/res/interpolator/caret_animation_interpolator.xml b/res/interpolator/caret_animation_interpolator.xml
deleted file mode 100644
index 25af4bc..0000000
--- a/res/interpolator/caret_animation_interpolator.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pathInterpolator
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0.0,0.0 c 0.0001,0.0 0.0,1.0 1.0,1.0" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2bc0cae..d11d5a5 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -254,4 +254,7 @@
<!-- Accessibility action to show quick actions menu for an icon. [CHAR_LIMIT=30] -->
<string name="action_deep_shortcut">Shortcuts</string>
+ <!-- Accessibility description for the shortcuts menu shown for an app. -->
+ <string name="shortcuts_menu_description"><xliff:g id="number_of_shortcuts" example="3">%1$d</xliff:g> shortcuts for <xliff:g id="app_name" example="Messenger">%2$s</xliff:g></string>
+
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 4c0230a..267a2d3 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -84,7 +84,9 @@
<item name="android:paddingEnd">@dimen/deep_shortcut_padding_end</item>
<item name="android:drawableEnd">@drawable/deep_shortcuts_drag_handle</item>
<item name="android:drawablePadding">@dimen/deep_shortcut_drawable_padding</item>
- <item name="android:textColor">@color/quantum_panel_text_color</item>
+ <item name="android:textColor">#FF212121</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:fontFamily">sans-serif</item>
<item name="android:shadowRadius">0</item>
<item name="customShadows">false</item>
<item name="layoutHorizontal">true</item>
diff --git a/src/com/android/launcher3/allapps/AllAppsCaretController.java b/src/com/android/launcher3/allapps/AllAppsCaretController.java
new file mode 100644
index 0000000..622322b
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsCaretController.java
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+package com.android.launcher3.allapps;
+
+import android.animation.ObjectAnimator;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.pageindicators.CaretDrawable;
+
+public class AllAppsCaretController {
+ // Determines when the caret should flip. Should be accessed via getThreshold()
+ private static final float CARET_THRESHOLD = 0.015f;
+ private static final float CARET_THRESHOLD_LAND = 0.5f;
+ // The velocity at which the caret will peak (i.e. exhibit a 90 degree bend)
+ private static final float PEAK_VELOCITY = VerticalPullDetector.RELEASE_VELOCITY_PX_MS * .7f;
+
+ private Launcher mLauncher;
+
+ private ObjectAnimator mCaretAnimator;
+ private CaretDrawable mCaretDrawable;
+ private float mLastCaretProgress;
+ private boolean mThresholdCrossed;
+
+ public AllAppsCaretController(CaretDrawable caret, Launcher launcher) {
+ mLauncher = launcher;
+ mCaretDrawable = caret;
+
+ final long caretAnimationDuration = launcher.getResources().getInteger(
+ R.integer.config_caretAnimationDuration);
+ final Interpolator caretInterpolator = AnimationUtils.loadInterpolator(launcher,
+ android.R.interpolator.fast_out_slow_in);
+
+ // We will set values later
+ mCaretAnimator = ObjectAnimator.ofFloat(mCaretDrawable, "caretProgress", 0);
+ mCaretAnimator.setDuration(caretAnimationDuration);
+ mCaretAnimator.setInterpolator(caretInterpolator);
+ }
+
+ /**
+ * Updates the state of the caret based on the progress of the {@link AllAppsContainerView}, as
+ * defined by the {@link AllAppsTransitionController}. Uses the container's velocity to adjust
+ * angle of caret.
+ *
+ * @param containerProgress The progress of the container in the range [0..1]
+ * @param velocity The velocity of the container
+ * @param dragging {@code true} if the container is being dragged
+ */
+ public void updateCaret(float containerProgress, float velocity, boolean dragging) {
+ // If we're in portrait and the shift is not 0 or 1, adjust the caret based on velocity
+ if (getThreshold() < containerProgress && containerProgress < 1 - getThreshold() &&
+ !mLauncher.useVerticalBarLayout()) {
+ mThresholdCrossed = true;
+
+ // How fast are we moving as a percentage of the peak velocity?
+ final float pctOfFlingVelocity = Math.max(-1, Math.min(velocity / PEAK_VELOCITY, 1));
+
+ mCaretDrawable.setCaretProgress(pctOfFlingVelocity);
+
+ // Set the last caret progress to this progress to prevent animator cancellation
+ mLastCaretProgress = pctOfFlingVelocity;
+ // Animate to neutral. This is necessary so the caret doesn't "freeze" when the
+ // container stops moving (e.g., during a drag or when the threshold is reached).
+ animateCaretToProgress(CaretDrawable.PROGRESS_CARET_NEUTRAL);
+ } else if (!dragging) {
+ // Otherwise, if we're not dragging, match the caret to the appropriate state
+ if (containerProgress <= getThreshold()) { // All Apps is up
+ animateCaretToProgress(CaretDrawable.PROGRESS_CARET_POINTING_DOWN);
+ } else if (containerProgress >= 1 - getThreshold()) { // All Apps is down
+ animateCaretToProgress(CaretDrawable.PROGRESS_CARET_POINTING_UP);
+ }
+ }
+ }
+
+ private void animateCaretToProgress(float progress) {
+ // If the new progress is the same as the last progress we animated to, terminate early
+ if (Float.compare(mLastCaretProgress, progress) == 0) {
+ return;
+ }
+
+ if (mCaretAnimator.isRunning()) {
+ mCaretAnimator.cancel(); // Stop the animator in its tracks
+ }
+
+ // Update the progress and start the animation
+ mLastCaretProgress = progress;
+ mCaretAnimator.setFloatValues(progress);
+ mCaretAnimator.start();
+ }
+
+ private float getThreshold() {
+ // In landscape, just return the landscape threshold.
+ if (mLauncher.useVerticalBarLayout()) {
+ return CARET_THRESHOLD_LAND;
+ }
+
+ // Before the threshold is crossed, it is reported as zero. This makes the caret immediately
+ // responsive when a drag begins. After the threshold is crossed, we return the constant
+ // value. This means the caret will start its state-based adjustment sooner. That is, we
+ // won't have to wait until the panel is completely settled to begin animation.
+ return mThresholdCrossed ? CARET_THRESHOLD : 0f;
+ }
+
+ public void onDragStart() {
+ mThresholdCrossed = false;
+ }
+}
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 7eef2dd..e46b889 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -11,7 +11,6 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
-import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import com.android.launcher3.DeviceProfile;
@@ -22,7 +21,6 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
-import com.android.launcher3.pageindicators.CaretDrawable;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.TouchController;
@@ -56,11 +54,7 @@
private Hotseat mHotseat;
private int mHotseatBackgroundColor;
- private ObjectAnimator mCaretAnimator;
- private final long mCaretAnimationDuration;
- private final Interpolator mCaretInterpolator;
- private CaretDrawable mCaretDrawable;
- private float mLastCaretProgress;
+ private AllAppsCaretController mCaretController;
private float mStatusBarHeight;
@@ -105,11 +99,6 @@
mBezelSwipeUpHeight = l.getResources().getDimensionPixelSize(
R.dimen.all_apps_bezel_swipe_height);
- mCaretAnimationDuration = l.getResources().getInteger(
- R.integer.config_caretAnimationDuration);
- mCaretInterpolator = AnimationUtils.loadInterpolator(l,
- R.interpolator.caret_animation_interpolator);
-
mEvaluator = new ArgbEvaluator();
mAllAppsBackgroundColor = l.getColor(R.color.all_apps_container_color);
}
@@ -196,6 +185,7 @@
@Override
public void onDragStart(boolean start) {
+ mCaretController.onDragStart();
cancelAnimation();
mCurrentAnimation = LauncherAnimUtils.createAnimatorSet();
mShiftStart = mAppsView.getTranslationY();
@@ -336,19 +326,15 @@
return;
}
mWorkspace.setWorkspaceYTranslationAndAlpha(
- PARALLAX_COEFFICIENT * (-mShiftRange + shiftCurrent),
- interpolation);
- updateCaret(progress);
- updateLightStatusBar(shiftCurrent);
+ PARALLAX_COEFFICIENT * (-mShiftRange + shiftCurrent), interpolation);
if (!mDetector.isDraggingState()) {
mContainerVelocity = mDetector.computeVelocity(shiftCurrent - shiftPrevious,
System.currentTimeMillis());
}
- }
- public float getContainerVelocity() {
- return mContainerVelocity;
+ mCaretController.updateCaret(progress, mContainerVelocity, mDetector.isDraggingState());
+ updateLightStatusBar(shiftCurrent);
}
public float getProgress() {
@@ -516,56 +502,14 @@
mCurrentAnimation = null;
}
- private void updateCaret(float shift) {
- // Animate to a neutral state by default
- float newCaretProgress = CaretDrawable.PROGRESS_CARET_NEUTRAL;
-
- // If we're in portrait and the shift is not 0 or 1, adjust the caret based on velocity
- if (0f < shift && shift < 1f && !mLauncher.useVerticalBarLayout()) {
- // How fast are we moving as a percentage of the minimum fling velocity?
- final float pctOfFlingVelocity = Math.max(-1, Math.min(
- mContainerVelocity / VerticalPullDetector.RELEASE_VELOCITY_PX_MS, 1));
-
- mCaretDrawable.setCaretProgress(pctOfFlingVelocity);
-
- // Set the last caret progress to this progress to prevent animator cancellation
- mLastCaretProgress = pctOfFlingVelocity;
- } else if (!mDetector.isDraggingState()) {
- // Otherwise, if we're not dragging, match the caret to the appropriate state
- if (Float.compare(shift, 0f) == 0) { // All Apps is up
- newCaretProgress = CaretDrawable.PROGRESS_CARET_POINTING_DOWN;
- } else if (Float.compare(shift, 1f) == 0) { // All Apps is down
- newCaretProgress = CaretDrawable.PROGRESS_CARET_POINTING_UP;
- }
- }
-
- // If the new progress is the same as the last progress we animated to, terminate early
- if (Float.compare(mLastCaretProgress, newCaretProgress) == 0) {
- return;
- }
-
- if (mCaretAnimator.isRunning()) {
- mCaretAnimator.cancel(); // Stop the animator in its tracks
- }
-
- // Update the progress and start the animation
- mLastCaretProgress = newCaretProgress;
- mCaretAnimator.setFloatValues(newCaretProgress);
- mCaretAnimator.start();
- }
-
public void setupViews(AllAppsContainerView appsView, Hotseat hotseat, Workspace workspace) {
mAppsView = appsView;
mHotseat = hotseat;
mWorkspace = workspace;
- mCaretDrawable = mWorkspace.getPageIndicator().getCaretDrawable();
mHotseat.addOnLayoutChangeListener(this);
mHotseat.bringToFront();
-
- // we will set values later
- mCaretAnimator = ObjectAnimator.ofFloat(mCaretDrawable, "caretProgress", 0);
- mCaretAnimator.setDuration(mCaretAnimationDuration);
- mCaretAnimator.setInterpolator(mCaretInterpolator);
+ mCaretController = new AllAppsCaretController(
+ mWorkspace.getPageIndicator().getCaretDrawable(), mLauncher);
}
@Override
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
index 53a28de..3d1bee5 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
@@ -40,6 +40,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
import android.view.animation.DecelerateInterpolator;
import android.widget.LinearLayout;
@@ -147,6 +148,8 @@
shortcut.getBubbleText().setAccessibilityDelegate(mAccessibilityDelegate);
addView(shortcut);
}
+ setContentDescription(getContext().getString(R.string.shortcuts_menu_description,
+ numShortcuts, originalIcon.getContentDescription().toString()));
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
orientAboutIcon(originalIcon);
@@ -276,6 +279,8 @@
@Override
public void onAnimationEnd(Animator animation) {
mOpenCloseAnimator = null;
+
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
});