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

Commit 05b7e2c6 authored by Jorim Jaggi's avatar Jorim Jaggi Committed by Android (Google) Code Review
Browse files

Merge "Change fling behavior of PanelView."

parents 01ad7a18 1d480695
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -233,9 +233,6 @@
         in dps over one second of time. -->
    <dimen name="recents_animation_movement_in_dps_per_second">800dp</dimen>

    <!-- Space below the notification stack -->
    <dimen name="notification_stack_margin_bottom">0dp</dimen>

    <!-- Space reserved for the cards behind the top card in the top stack -->
    <dimen name="top_stack_peek_amount">12dp</dimen>

+82 −8
Original line number Diff line number Diff line
@@ -27,23 +27,32 @@ import android.view.animation.PathInterpolator;
 */
public class FlingAnimationUtils {

    private static final float LINEAR_OUT_SLOW_IN_Y2 = 0.35f;
    private static final float MAX_LENGTH_SECONDS = 0.4f;
    private static final float LINEAR_OUT_SLOW_IN_X2 = 0.35f;
    private static final float LINEAR_OUT_FASTER_IN_Y2 = 0.7f;
    private static final float MIN_VELOCITY_DP_PER_SECOND = 250;

    /**
     * Crazy math. http://en.wikipedia.org/wiki/B%C3%A9zier_curve
     */
    private static final float LINEAR_OUT_SLOW_IN_START_GRADIENT = 1/LINEAR_OUT_SLOW_IN_Y2;
    private static final float LINEAR_OUT_SLOW_IN_START_GRADIENT = 1.0f / LINEAR_OUT_SLOW_IN_X2;
    private static final float LINEAR_OUT_FASTER_IN_START_GRADIENT = LINEAR_OUT_FASTER_IN_Y2;

    private Interpolator mLinearOutSlowIn;
    private Interpolator mFastOutSlowIn;
    private Interpolator mFastOutLinearIn;
    private Interpolator mLinearOutFasterIn;

    private float mMinVelocityPxPerSecond;
    private float mMaxLengthSeconds;

    public FlingAnimationUtils(Context ctx) {
        mLinearOutSlowIn = new PathInterpolator(0, 0, LINEAR_OUT_SLOW_IN_Y2, 1);
    public FlingAnimationUtils(Context ctx, float maxLengthSeconds) {
        mMaxLengthSeconds = maxLengthSeconds;
        mLinearOutSlowIn = new PathInterpolator(0, 0, LINEAR_OUT_SLOW_IN_X2, 1);
        mLinearOutFasterIn = new PathInterpolator(0, 0, 1, LINEAR_OUT_FASTER_IN_Y2);
        mFastOutSlowIn
                = AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_slow_in);
        mFastOutLinearIn
                = AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_linear_in);
        mMinVelocityPxPerSecond
                = MIN_VELOCITY_DP_PER_SECOND * ctx.getResources().getDisplayMetrics().density;
    }
@@ -58,15 +67,33 @@ public class FlingAnimationUtils {
     * @param velocity the current velocity of the motion
     */
    public void apply(ValueAnimator animator, float currValue, float endValue, float velocity) {
        apply(animator, currValue, endValue, velocity, Math.abs(endValue - currValue));
    }

    /**
     * Applies the interpolator and length to the animator, such that the fling animation is
     * consistent with the finger motion.
     *
     * @param animator the animator to apply
     * @param currValue the current value
     * @param endValue the end value of the animator
     * @param velocity the current velocity of the motion
     * @param maxDistance the maximum distance for this interaction; the maximum animation length
     *                    gets multiplied by the ratio between the actual distance and this value
     */
    public void apply(ValueAnimator animator, float currValue, float endValue, float velocity,
            float maxDistance) {
        float maxLengthSeconds = (float) (mMaxLengthSeconds
                * Math.sqrt(Math.abs(endValue - currValue) / maxDistance));
        float diff = Math.abs(endValue - currValue);
        float velAbs = Math.abs(velocity);
        float durationSeconds = LINEAR_OUT_SLOW_IN_START_GRADIENT * diff / velAbs;
        if (durationSeconds <= MAX_LENGTH_SECONDS) {
        if (durationSeconds <= maxLengthSeconds) {
            animator.setInterpolator(mLinearOutSlowIn);
        } else if (velAbs >= mMinVelocityPxPerSecond) {

            // Cross fade between fast-out-slow-in and linear interpolator with current velocity.
            durationSeconds = MAX_LENGTH_SECONDS;
            durationSeconds = maxLengthSeconds;
            VelocityInterpolator velocityInterpolator
                    = new VelocityInterpolator(durationSeconds, velAbs, diff);
            InterpolatorInterpolator superInterpolator = new InterpolatorInterpolator(
@@ -75,12 +102,59 @@ public class FlingAnimationUtils {
        } else {

            // Just use a normal interpolator which doesn't take the velocity into account.
            durationSeconds = MAX_LENGTH_SECONDS;
            durationSeconds = maxLengthSeconds;
            animator.setInterpolator(mFastOutSlowIn);
        }
        animator.setDuration((long) (durationSeconds * 1000));
    }

    /**
     * Applies the interpolator and length to the animator, such that the fling animation is
     * consistent with the finger motion for the case when the animation is making something
     * disappear.
     *
     * @param animator the animator to apply
     * @param currValue the current value
     * @param endValue the end value of the animator
     * @param velocity the current velocity of the motion
     * @param maxDistance the maximum distance for this interaction; the maximum animation length
     *                    gets multiplied by the ratio between the actual distance and this value
     */
    public void applyDismissing(ValueAnimator animator, float currValue, float endValue,
            float velocity, float maxDistance) {
        float maxLengthSeconds = (float) (mMaxLengthSeconds
                * Math.pow(Math.abs(endValue - currValue) / maxDistance, 0.5f));
        float diff = Math.abs(endValue - currValue);
        float velAbs = Math.abs(velocity);
        float durationSeconds = LINEAR_OUT_FASTER_IN_START_GRADIENT * diff / velAbs;
        if (durationSeconds <= maxLengthSeconds) {
            animator.setInterpolator(mLinearOutFasterIn);
        } else if (velAbs >= mMinVelocityPxPerSecond) {

            // Cross fade between linear-out-faster-in and linear interpolator with current
            // velocity.
            durationSeconds = maxLengthSeconds;
            VelocityInterpolator velocityInterpolator
                    = new VelocityInterpolator(durationSeconds, velAbs, diff);
            InterpolatorInterpolator superInterpolator = new InterpolatorInterpolator(
                    velocityInterpolator, mLinearOutFasterIn, mLinearOutSlowIn);
            animator.setInterpolator(superInterpolator);
        } else {

            // Just use a normal interpolator which doesn't take the velocity into account.
            durationSeconds = maxLengthSeconds;
            animator.setInterpolator(mFastOutLinearIn);
        }
        animator.setDuration((long) (durationSeconds * 1000));
    }

    /**
     * @return the minimum velocity a gesture needs to have to be considered a fling
     */
    public float getMinVelocityPxPerSecond() {
        return mMinVelocityPxPerSecond;
    }

    /**
     * An interpolator which interpolates two interpolators with an interpolator.
     */
+9 −16
Original line number Diff line number Diff line
@@ -150,7 +150,7 @@ public class NotificationPanelView extends PanelView implements
        mMoreCardNotificationAmount =
                (float) getResources().getDimensionPixelSize(R.dimen.notification_summary_height) /
                        getResources().getDimensionPixelSize(R.dimen.notification_min_height);
        mFlingAnimationUtils = new FlingAnimationUtils(getContext());
        mFlingAnimationUtils = new FlingAnimationUtils(getContext(), 0.4f);
        mStatusBarMinHeight = getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.status_bar_height);
    }
@@ -618,17 +618,15 @@ public class NotificationPanelView extends PanelView implements

    @Override
    protected int getMaxPanelHeight() {
        if (!isInSettings()) {
        // TODO: Figure out transition for collapsing when QS is open, adjust height here.
        int maxPanelHeight = super.getMaxPanelHeight();
            int notificationMarginBottom = mStackScrollerContainer.getPaddingBottom();
            int emptyBottomMargin = notificationMarginBottom
        int emptyBottomMargin = mStackScrollerContainer.getHeight()
                - mNotificationStackScroller.getHeight()
                + mNotificationStackScroller.getEmptyBottomMargin();
        int maxHeight = maxPanelHeight - emptyBottomMargin;
        maxHeight = Math.max(maxHeight, mStatusBarMinHeight);
        return maxHeight;
    }
        return super.getMaxPanelHeight();
    }

    private boolean isInSettings() {
        return mQsExpanded;
@@ -639,11 +637,6 @@ public class NotificationPanelView extends PanelView implements
        mNotificationStackScroller.setStackHeight(expandedHeight);
    }

    @Override
    protected int getDesiredMeasureHeight() {
        return mMaxPanelHeight;
    }

    @Override
    protected void onExpandingStarted() {
        super.onExpandingStarted();
+62 −257

File changed.

Preview size limit exceeded, changes collapsed.

+6 −8
Original line number Diff line number Diff line
@@ -84,7 +84,6 @@ public class NotificationStackScrollLayout extends ViewGroup
    private int mCollapsedSize;
    private int mBottomStackSlowDownHeight;
    private int mBottomStackPeekSize;
    private int mEmptyMarginBottom;
    private int mPaddingBetweenElements;
    private int mPaddingBetweenElementsDimmed;
    private int mPaddingBetweenElementsNormal;
@@ -178,6 +177,8 @@ public class NotificationStackScrollLayout extends ViewGroup
            canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
            y = (int) getLayoutHeight();
            canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
            y = getHeight() - getEmptyBottomMargin();
            canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
        }
    }

@@ -201,8 +202,6 @@ public class NotificationStackScrollLayout extends ViewGroup
                .getDimensionPixelSize(R.dimen.notification_min_height);
        mBottomStackPeekSize = context.getResources()
                .getDimensionPixelSize(R.dimen.bottom_stack_peek_amount);
        mEmptyMarginBottom = context.getResources().getDimensionPixelSize(
                R.dimen.notification_stack_margin_bottom);
        mStackScrollAlgorithm = new StackScrollAlgorithm(context);
        mPaddingBetweenElementsDimmed = context.getResources()
                .getDimensionPixelSize(R.dimen.notification_padding_dimmed);
@@ -242,7 +241,7 @@ public class NotificationStackScrollLayout extends ViewGroup
                    (int) (centerX + width / 2.0f),
                    (int) height);
        }
        setMaxLayoutHeight(getHeight() - mEmptyMarginBottom);
        setMaxLayoutHeight(getHeight());
        updateContentHeight();
        updateScrollPositionIfNecessary();
        requestChildrenUpdate();
@@ -297,10 +296,7 @@ public class NotificationStackScrollLayout extends ViewGroup
     *         last child is not in the bottom stack.
     */
    private boolean needsHeightAdaption() {
        View lastChild = getLastChildNotGone();
        View firstChild = getFirstChildNotGone();
        boolean isLastChildExpanded = isViewExpanded(lastChild);
        return isLastChildExpanded && lastChild != firstChild;
        return getNotGoneChildCount() > 1;
    }

    private boolean isViewExpanded(View view) {
@@ -1429,6 +1425,8 @@ public class NotificationStackScrollLayout extends ViewGroup
        int emptyMargin = mMaxLayoutHeight - mContentHeight;
        if (needsHeightAdaption()) {
            emptyMargin = emptyMargin - mBottomStackSlowDownHeight - mBottomStackPeekSize;
        } else {
            emptyMargin = emptyMargin - mBottomStackPeekSize;
        }
        return Math.max(emptyMargin, 0);
    }