Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e97f0c52 authored by Ricardo Cerqueira's avatar Ricardo Cerqueira
Browse files

Add overscroll effects configuration

I has my bouncy again!
Includes the fixes done in CM6, and Robert
Burns' weight configuration

Change-Id: Ib0a90b47b80ac8b213fd137340419a31dc5fbc1a
parent 34e77c15
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -2279,6 +2279,16 @@ public final class Settings {
        /** @hide */
        public static final String ELECTRON_BEAM_ANIMATION_OFF = "electron_beam_animation_off";

        /** @hide */
        public static final String OVERSCROLL_EFFECT = "overscroll_effect";

        /**
         * Sets the overscroller weight (edge bounce effect on lists)
         * @hide
         */
        public static final String OVERSCROLL_WEIGHT = "overscroll_weight";


        /**
         * Settings to backup. This is here so that it's in the same place as the settings
         * keys and easy to update.
+21 −1
Original line number Diff line number Diff line
@@ -66,6 +66,8 @@ import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.ScrollBarDrawable;

import android.provider.Settings;

import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -1592,6 +1594,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     */
    protected ViewParent mParent;

    /* @hide */
    public static final int OVER_SCROLL_SETTING_EDGEGLOW = 1;
    /* @hide */
    public static final int OVER_SCROLL_SETTING_BOUNCEGLOW = 2;
    /* @hide */
    public static final int OVER_SCROLL_SETTING_BOUNCE = 3;

    /**
     * {@hide}
     */
@@ -1876,6 +1885,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
        // Used for debug only
        //++sInstanceCount;
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
    }

@@ -8834,7 +8844,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
            int scrollRangeX, int scrollRangeY,
            int maxOverScrollX, int maxOverScrollY,
            boolean isTouchEvent) {
        final int overScrollMode = mOverScrollMode;
        final int overScrollMode = getOverScrollMode();
        final boolean canScrollHorizontal =
                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
        final boolean canScrollVertical =
@@ -8906,6 +8916,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     * @return This view's over-scroll mode.
     */
    public int getOverScrollMode() {
        final int overScrollEffect = Settings.System.getInt(mContext.getContentResolver(),
                Settings.System.OVERSCROLL_EFFECT, OVER_SCROLL_SETTING_EDGEGLOW);
        if (overScrollEffect <= 0) {
            /* Disabled */
            return OVER_SCROLL_NEVER;
        } else if ( mOverScrollMode != OVER_SCROLL_ALWAYS &&
                    (mViewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) == 0) {
            /* Don't overscroll items without scrollbars */
            return OVER_SCROLL_NEVER;
        }
        return mOverScrollMode;
    }

+98 −38
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@ import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
import android.view.inputmethod.InputMethodManager;

import android.provider.Settings;

import java.util.ArrayList;
import java.util.List;

@@ -386,10 +388,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     */
    int mOverscrollMax;

    /**
     * Preferred overscroll effect
     */
    int mOverscrollEffect;

    /**
     * Content height divided by this is the overscroll limit.
     */
    static final int OVERSCROLL_LIMIT_DIVISOR = 3;
    static final int OVERSCROLL_LIMIT_DIVISOR = 5;

    /**
     * Used to request a layout when we changed touch mode
@@ -525,6 +532,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     */
    private int mDirection = 0;

    /**
     * Used to store the overscroll mode in this view
     */
    private int mOverScrollMode = 0;

    /**
     * Interface definition for a callback to be invoked when the list or grid
     * has been scrolled.
@@ -1245,10 +1257,19 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
            mRecycler.markChildrenDirty();
        }

        mOverScrollMode = getOverScrollMode();
        layoutChildren();
        mInLayout = false;

        mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
        mOverscrollMax = (b - t) / getOverscrollWeight();

        mOverscrollEffect = Settings.System.getInt(mContext.getContentResolver(),
                Settings.System.OVERSCROLL_EFFECT, OVER_SCROLL_SETTING_EDGEGLOW);

        if (mOverscrollEffect >= OVER_SCROLL_SETTING_BOUNCEGLOW) {
            mOverscrollDistance = getOverscrollMax();
            mOverflingDistance = getOverscrollMax();
        }
    }

    /**
@@ -1369,6 +1390,22 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        return mListPadding.right;
    }

    /**
     * Returns the overscroll weight for this view
     *
     * @return This view's overscroll weight.
     */
    private int getOverscrollWeight() {
        final int weight = Settings.System.getInt(mContext.getContentResolver(),
            Settings.System.OVERSCROLL_WEIGHT, 0);

        if (weight == 0) {
            return OVERSCROLL_LIMIT_DIVISOR;
        } else {
            return weight;
        }
    }

    /**
     * Get a view and have it show the data associated with the specified
     * position. This is called when we have already discovered that the view is
@@ -2025,7 +2062,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        // Check if we have moved far enough that it looks more like a
        // scroll than a tap
        final int distance = Math.abs(deltaY);
        final boolean overscroll = mScrollY != 0;
        final boolean overscroll = mScrollY != 0 && (mOverScrollMode != OVER_SCROLL_NEVER);
        if (overscroll || distance > mTouchSlop) {
            createScrollingCache();
            mTouchMode = overscroll ? TOUCH_MODE_OVERSCROLL : TOUCH_MODE_SCROLL;
@@ -2227,7 +2264,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                        // Check if the top of the motion view is where it is
                        // supposed to be
                        final int motionViewRealTop = motionView.getTop();
                        if (atEdge) {
                        if (atEdge && mOverScrollMode != OVER_SCROLL_NEVER) {
                            // Apply overscroll

                            int overscroll = -incrementalDeltaY -
@@ -2239,12 +2276,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                                mVelocityTracker.clear();
                            }

                            final int overscrollMode = getOverScrollMode();
                            if (overscrollMode == OVER_SCROLL_ALWAYS ||
                                    (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
                            if (mOverScrollMode == OVER_SCROLL_ALWAYS ||
                                    (mOverScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
                                            !contentFits())) {
                                mDirection = 0; // Reset when entering overscroll.
                                mTouchMode = TOUCH_MODE_OVERSCROLL;
                                if (mOverscrollEffect < OVER_SCROLL_SETTING_BOUNCE) {
                                    if (rawDeltaY > 0) {
                                        mEdgeGlowTop.onPull((float) overscroll / getHeight());
                                        if (!mEdgeGlowBottom.isFinished()) {
@@ -2258,6 +2295,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                                    }
                                }
                            }
                        }
                        mMotionY = y;
                        invalidate();
                    }
@@ -2307,10 +2345,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                    } else {
                        overScrollBy(0, -incrementalDeltaY, 0, mScrollY, 0, 0,
                                0, mOverscrollDistance, true);
                        final int overscrollMode = getOverScrollMode();
                        if (overscrollMode == OVER_SCROLL_ALWAYS ||
                                (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
                        if (mOverScrollMode == OVER_SCROLL_ALWAYS ||
                                (mOverScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
                                        !contentFits())) {
                            if (mOverscrollEffect < OVER_SCROLL_SETTING_BOUNCE) {
                                if (rawDeltaY > 0) {
                                    mEdgeGlowTop.onPull((float) -incrementalDeltaY / getHeight());
                                    if (!mEdgeGlowBottom.isFinished()) {
@@ -2322,6 +2360,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                                        mEdgeGlowTop.onRelease();
                                    }
                                }
                            }
                            invalidate();
                        }
                        if (Math.abs(mOverscrollDistance) == Math.abs(mScrollY)) {
@@ -2464,7 +2503,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te

            setPressed(false);

            if (mEdgeGlowTop != null) {
            if (mOverScrollMode != OVER_SCROLL_NEVER &&
                    mOverscrollEffect < OVER_SCROLL_SETTING_BOUNCE &&
                    mEdgeGlowTop != null) {
                mEdgeGlowTop.onRelease();
                mEdgeGlowBottom.onRelease();
            }
@@ -2526,7 +2567,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                }
            }
            
            if (mEdgeGlowTop != null) {
            if (mOverScrollMode != OVER_SCROLL_NEVER &&
                    mOverscrollEffect < OVER_SCROLL_SETTING_BOUNCE &&
                    mEdgeGlowTop != null) {
                mEdgeGlowTop.onRelease();
                mEdgeGlowBottom.onRelease();
            }
@@ -2567,10 +2610,22 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        awakenScrollBars();
    }

    private int getOverscrollMax() {
        final int childCount = getChildCount();
        if (childCount > 0) {
            return Math.min(mOverscrollMax,
                    getChildAt(childCount - 1).getBottom() / getOverscrollWeight());
        } else {
            return mOverscrollMax;
        }
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        if (mEdgeGlowTop != null) {
        if (mOverScrollMode != OVER_SCROLL_NEVER &&
                mOverscrollEffect < OVER_SCROLL_SETTING_BOUNCE &&
                mEdgeGlowTop != null) {
            final int scrollY = mScrollY;
            if (!mEdgeGlowTop.isFinished()) {
                final int restoreCount = canvas.save();
@@ -2799,10 +2854,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te

        void edgeReached(int delta) {
            mScroller.notifyVerticalEdgeReached(mScrollY, 0, mOverflingDistance);
            final int overscrollMode = getOverScrollMode();
            if (overscrollMode == OVER_SCROLL_ALWAYS ||
                    (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && !contentFits())) {
            mTouchMode = TOUCH_MODE_OVERFLING;
            if (mOverScrollMode == OVER_SCROLL_ALWAYS ||
                    (mOverScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && 
                     !contentFits() && 
                     mOverscrollEffect < OVER_SCROLL_SETTING_BOUNCE)) {
                final int vel = (int) mScroller.getCurrVelocity();
                if (delta > 0) {
                    mEdgeGlowTop.onAbsorb(vel);
@@ -3306,6 +3362,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te

        if (firstPosition + childCount == mItemCount && lastBottom <= end &&
                incrementalDeltaY <= 0) {

            // Don't need to move views up if the bottom of the last position
            // is already visible
            return incrementalDeltaY != 0;
@@ -4243,11 +4300,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
    }

    private void finishGlows() {
        if (mOverScrollMode != OVER_SCROLL_NEVER &&
            mOverscrollEffect < OVER_SCROLL_SETTING_BOUNCE) {
            if (mEdgeGlowTop != null) {
                mEdgeGlowTop.finish();
                mEdgeGlowBottom.finish();
            }
        }
    }

    /**
     * Sets the recycler listener to be notified whenever a View is set aside in
+1 −1
Original line number Diff line number Diff line
@@ -514,7 +514,7 @@ public class OverScroller {
        private int mOver;

        // Duration in milliseconds to go back from edge to edge. Springback is half of it.
        private static final int OVERSCROLL_SPRINGBACK_DURATION = 200;
        private static final int OVERSCROLL_SPRINGBACK_DURATION = 350;

        // Oscillation period
        private static final float TIME_COEF =