summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2017-06-27 05:51:22 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2017-06-27 05:51:23 +0000
commita80b18420609e1d9dab27be4d38e0c7263d4c8b0 (patch)
treeb5558db463a799969d73ffae32b87910af1162ff /src/com/android/launcher3
parent71d94efcfb3d651ab2547b4feb51741a0d6f021b (diff)
parentad3194ec81a2eb1d5823dd892fc8590c613c991b (diff)
downloadandroid_packages_apps_Trebuchet-a80b18420609e1d9dab27be4d38e0c7263d4c8b0.tar.gz
android_packages_apps_Trebuchet-a80b18420609e1d9dab27be4d38e0c7263d4c8b0.tar.bz2
android_packages_apps_Trebuchet-a80b18420609e1d9dab27be4d38e0c7263d4c8b0.zip
Merge "Add overscroll w/ physics to All Apps." into ub-launcher3-dorval-polish
Diffstat (limited to 'src/com/android/launcher3')
-rw-r--r--src/com/android/launcher3/allapps/AllAppsContainerView.java2
-rw-r--r--src/com/android/launcher3/allapps/AllAppsRecyclerView.java126
-rw-r--r--src/com/android/launcher3/anim/SpringAnimationHandler.java15
3 files changed, 142 insertions, 1 deletions
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 47b68a2ee..189b9358f 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -220,7 +220,7 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
});
// Load the all apps recycler view
- mAppsRecyclerView = (AllAppsRecyclerView) findViewById(R.id.apps_list_view);
+ mAppsRecyclerView = findViewById(R.id.apps_list_view);
mAppsRecyclerView.setApps(mApps);
mAppsRecyclerView.setLayoutManager(mLayoutManager);
mAppsRecyclerView.setAdapter(mAdapter);
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 2b2fddcdd..a2bd43d84 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -15,12 +15,14 @@
*/
package com.android.launcher3.allapps;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
+import android.util.Property;
import android.util.SparseIntArray;
import android.view.MotionEvent;
import android.view.View;
@@ -54,6 +56,22 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
private int mEmptySearchBackgroundTopOffset;
private SpringAnimationHandler mSpringAnimationHandler;
+ private OverScrollHelper mOverScrollHelper;
+ private VerticalPullDetector mPullDetector;
+
+ private float mContentTranslationY = 0;
+ public static final Property<AllAppsRecyclerView, Float> CONTENT_TRANS_Y =
+ new Property<AllAppsRecyclerView, Float>(Float.class, "appsRecyclerViewContentTransY") {
+ @Override
+ public Float get(AllAppsRecyclerView allAppsRecyclerView) {
+ return allAppsRecyclerView.getContentTranslationY();
+ }
+
+ @Override
+ public void set(AllAppsRecyclerView allAppsRecyclerView, Float y) {
+ allAppsRecyclerView.setContentTranslationY(y);
+ }
+ };
public AllAppsRecyclerView(Context context) {
this(context, null);
@@ -74,6 +92,12 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
addOnItemTouchListener(this);
mEmptySearchBackgroundTopOffset = res.getDimensionPixelSize(
R.dimen.all_apps_empty_search_bg_top_offset);
+
+ mOverScrollHelper = new OverScrollHelper();
+ mPullDetector = new VerticalPullDetector(getContext());
+ mPullDetector.setListener(mOverScrollHelper);
+ mPullDetector.setDetectableScrollConditions(VerticalPullDetector.DIRECTION_UP
+ | VerticalPullDetector.DIRECTION_DOWN, true);
}
public void setSpringAnimationHandler(SpringAnimationHandler springAnimationHandler) {
@@ -81,7 +105,14 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
}
@Override
+ public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent ev) {
+ mPullDetector.onTouchEvent(ev);
+ return super.onInterceptTouchEvent(rv, ev) || mOverScrollHelper.isInOverScroll();
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent e) {
+ mPullDetector.onTouchEvent(e);
if (FeatureFlags.LAUNCHER3_PHYSICS && mSpringAnimationHandler != null) {
mSpringAnimationHandler.addMovement(e);
}
@@ -168,6 +199,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
@Override
public void onDraw(Canvas c) {
+ c.translate(0, mContentTranslationY);
+
// Draw the background
if (mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) {
mEmptySearchBackground.draw(c);
@@ -176,6 +209,19 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
super.onDraw(c);
}
+ public float getContentTranslationY() {
+ return mContentTranslationY;
+ }
+
+ /**
+ * Use this method instead of calling {@link #setTranslationY(float)}} directly to avoid drawing
+ * on top of other Views.
+ */
+ public void setContentTranslationY(float y) {
+ mContentTranslationY = y;
+ invalidate();
+ }
+
@Override
protected boolean verifyDrawable(Drawable who) {
return who == mEmptySearchBackground || super.verifyDrawable(who);
@@ -434,4 +480,84 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
y + mEmptySearchBackground.getIntrinsicHeight());
}
+ private class OverScrollHelper implements VerticalPullDetector.Listener {
+
+ private static final float MAX_RELEASE_VELOCITY = 5000; // px / s
+ private static final float MAX_OVERSCROLL_PERCENTAGE = 0.07f;
+
+ private boolean mIsInOverScroll;
+
+ @Override
+ public void onDragStart(boolean start) {
+ }
+
+ @Override
+ public boolean onDrag(float displacement, float velocity) {
+ // We are in overscroll iff we are trying to drag further down when we're already at
+ // the bottom of All Apps.
+ mIsInOverScroll = !canScrollVertically(1) && displacement < 0;
+
+ if (mIsInOverScroll) {
+ displacement = getDampedOverScroll(displacement);
+ setContentTranslationY(displacement);
+ }
+ return mIsInOverScroll;
+ }
+
+ @Override
+ public void onDragEnd(float velocity, boolean fling) {
+ float y = getContentTranslationY();
+ if (mIsInOverScroll && Float.compare(y, 0) != 0) {
+ if (FeatureFlags.LAUNCHER3_PHYSICS) {
+ // We calculate our own velocity to give the springs the desired effect.
+ velocity = y / getDampedOverScroll(getHeight()) * MAX_RELEASE_VELOCITY;
+ mSpringAnimationHandler.animateToPositionWithVelocity(0, -velocity);
+ }
+
+ ObjectAnimator.ofFloat(AllAppsRecyclerView.this,
+ AllAppsRecyclerView.CONTENT_TRANS_Y, 0)
+ .setDuration(100)
+ .start();
+ }
+ mIsInOverScroll = false;
+ }
+
+ public boolean isInOverScroll() {
+ return mIsInOverScroll;
+ }
+
+ private float getDampedOverScroll(float y) {
+ return dampedOverScroll(y, getHeight()) * MAX_OVERSCROLL_PERCENTAGE;
+ }
+
+ /**
+ * This curve determines how the effect of scrolling over the limits of the page diminishes
+ * as the user pulls further and further from the bounds
+ *
+ * @param f The percentage of how much the user has overscrolled.
+ * @return A transformed percentage based on the influence curve.
+ */
+ private float overScrollInfluenceCurve(float f) {
+ f -= 1.0f;
+ return f * f * f + 1.0f;
+ }
+
+ /**
+ * @param amount The original amount overscrolled.
+ * @param max The maximum amount that the View can overscroll.
+ * @return The dampened overscroll amount.
+ */
+ private float dampedOverScroll(float amount, float max) {
+ float f = amount / max;
+ if (Float.compare(f, 0) == 0) return 0;
+ f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
+
+ // Clamp this factor, f, to -1 < f < 1
+ if (Math.abs(f) >= 1) {
+ f /= Math.abs(f);
+ }
+
+ return Math.round(f * max);
+ }
+ }
}
diff --git a/src/com/android/launcher3/anim/SpringAnimationHandler.java b/src/com/android/launcher3/anim/SpringAnimationHandler.java
index 038f82682..1efc4e4e1 100644
--- a/src/com/android/launcher3/anim/SpringAnimationHandler.java
+++ b/src/com/android/launcher3/anim/SpringAnimationHandler.java
@@ -127,6 +127,19 @@ public class SpringAnimationHandler<T> {
reset();
}
+ /**
+ * Similar to {@link #animateToFinalPosition(float)}, but used in cases where we want to
+ * manually set the velocity.
+ */
+ public void animateToPositionWithVelocity(float position, float velocity) {
+ if (DEBUG) Log.d(TAG, "animateToPosition#velocity=" + velocity);
+
+ setStartVelocity(velocity);
+ mShouldComputeVelocity = false;
+ animateToFinalPosition(position);
+ }
+
+
public boolean isRunning() {
// All the animations run at the same time so we can just check the first one.
return !mAnimations.isEmpty() && mAnimations.get(0).isRunning();
@@ -153,6 +166,8 @@ public class SpringAnimationHandler<T> {
}
private void setStartVelocity(float velocity) {
+ if (DEBUG) Log.d(TAG, "setStartVelocity=" + velocity);
+
int size = mAnimations.size();
for (int i = 0; i < size; ++i) {
mAnimations.get(i).setStartVelocity(velocity);