summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorim Jaggi <jjaggi@google.com>2014-05-20 19:41:58 +0200
committerJorim Jaggi <jjaggi@google.com>2014-05-22 01:01:36 +0200
commit1d480695df31f1c328473f32d5007cea6a03b6e0 (patch)
tree59dfaf84c6791c6fcfe73874cbbdc8b63175b933
parentb7b61ddaef4f2a2ebc79e832fb909fd4dcac8ba5 (diff)
downloadframeworks_base-1d480695df31f1c328473f32d5007cea6a03b6e0.zip
frameworks_base-1d480695df31f1c328473f32d5007cea6a03b6e0.tar.gz
frameworks_base-1d480695df31f1c328473f32d5007cea6a03b6e0.tar.bz2
Change fling behavior of PanelView.
Change-Id: Ie700be6b1ef48350601ce6bc7fe60579fddae098
-rw-r--r--packages/SystemUI/res/values/dimens.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java90
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java319
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java14
5 files changed, 159 insertions, 292 deletions
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 44b9d38..c209434 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -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>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
index 0606a94..bb3a295 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
@@ -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,13 +102,60 @@ 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.
*/
private static final class InterpolatorInterpolator implements Interpolator {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 19252c0..7e3bf68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -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,16 +618,14 @@ public class NotificationPanelView extends PanelView implements
@Override
protected int getMaxPanelHeight() {
- if (!isInSettings()) {
- int maxPanelHeight = super.getMaxPanelHeight();
- int notificationMarginBottom = mStackScrollerContainer.getPaddingBottom();
- int emptyBottomMargin = notificationMarginBottom
- + mNotificationStackScroller.getEmptyBottomMargin();
- int maxHeight = maxPanelHeight - emptyBottomMargin;
- maxHeight = Math.max(maxHeight, mStatusBarMinHeight);
- return maxHeight;
- }
- return super.getMaxPanelHeight();
+ // TODO: Figure out transition for collapsing when QS is open, adjust height here.
+ int maxPanelHeight = super.getMaxPanelHeight();
+ int emptyBottomMargin = mStackScrollerContainer.getHeight()
+ - mNotificationStackScroller.getHeight()
+ + mNotificationStackScroller.getEmptyBottomMargin();
+ int maxHeight = maxPanelHeight - emptyBottomMargin;
+ maxHeight = Math.max(maxHeight, mStatusBarMinHeight);
+ return maxHeight;
}
private boolean isInSettings() {
@@ -640,11 +638,6 @@ public class NotificationPanelView extends PanelView implements
}
@Override
- protected int getDesiredMeasureHeight() {
- return mMaxPanelHeight;
- }
-
- @Override
protected void onExpandingStarted() {
super.onExpandingStarted();
mNotificationStackScroller.onExpansionStarted();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index a89fc0a..b6a43a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -16,58 +16,33 @@
package com.android.systemui.statusbar.phone;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
-import android.animation.TimeAnimator;
-import android.animation.TimeAnimator.TimeListener;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
-import android.view.View;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;
import com.android.systemui.R;
+import com.android.systemui.statusbar.FlingAnimationUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayDeque;
-import java.util.Iterator;
public class PanelView extends FrameLayout {
public static final boolean DEBUG = PanelBar.DEBUG;
public static final String TAG = PanelView.class.getSimpleName();
- public static final boolean DEBUG_NAN = true; // http://b/7686690
-
private final void logf(String fmt, Object... args) {
Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
}
- public static final boolean BRAKES = false;
-
- private float mSelfExpandVelocityPx; // classic value: 2000px/s
- private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
- private float mFlingExpandMinVelocityPx; // classic value: 200px/s
- private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
- private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
- private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
- private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
-
- private float mFlingGestureMinDistPx;
-
- private float mExpandAccelPx; // classic value: 2000px/s/s
- private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
-
- private float mFlingGestureMaxOutputVelocityPx; // how fast can it really go? (should be a little
- // faster than mSelfCollapseVelocityPx)
-
- private float mCollapseBrakingDistancePx = 200; // XXX Resource
- private float mExpandBrakingDistancePx = 150; // XXX Resource
- private float mBrakingSpeedPx = 150; // XXX Resource
-
private float mPeekHeight;
private float mInitialOffsetOnTouch;
private float mExpandedFraction = 0;
@@ -78,36 +53,17 @@ public class PanelView extends FrameLayout {
private int mTrackingPointer;
protected int mTouchSlop;
- private TimeAnimator mTimeAnimator;
+ private ValueAnimator mHeightAnimator;
private ObjectAnimator mPeekAnimator;
private VelocityTrackerInterface mVelocityTracker;
+ private FlingAnimationUtils mFlingAnimationUtils;
PanelBar mBar;
- private final TimeListener mAnimationCallback = new TimeListener() {
- @Override
- public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
- animationTick(deltaTime);
- }
- };
-
- private final Runnable mStopAnimator = new Runnable() {
- @Override
- public void run() {
- if (mTimeAnimator != null && mTimeAnimator.isStarted()) {
- mTimeAnimator.end();
- mClosing = false;
- onExpandingFinished();
- }
- }
- };
-
- private float mVel, mAccel;
protected int mMaxPanelHeight = -1;
private String mViewName;
private float mInitialTouchY;
private float mInitialTouchX;
- private float mFinalTouchY;
protected void onExpandingFinished() {
}
@@ -117,7 +73,7 @@ public class PanelView extends FrameLayout {
private void runPeekAnimation() {
if (DEBUG) logf("peek to height=%.1f", mPeekHeight);
- if (mTimeAnimator.isStarted()) {
+ if (mHeightAnimator != null) {
return;
}
if (mPeekAnimator == null) {
@@ -128,104 +84,13 @@ public class PanelView extends FrameLayout {
mPeekAnimator.start();
}
- private void animationTick(long dtms) {
- if (!mTimeAnimator.isStarted()) {
- // XXX HAX to work around bug in TimeAnimator.end() not resetting its last time
- mTimeAnimator = new TimeAnimator();
- mTimeAnimator.setTimeListener(mAnimationCallback);
-
- if (mPeekAnimator != null) mPeekAnimator.cancel();
-
- mTimeAnimator.start();
-
- if (mVel == 0) {
- // if the panel is less than halfway open, close it
- mClosing = (mFinalTouchY / getMaxPanelHeight()) < 0.5f;
- } else {
- mClosing = mExpandedHeight > 0 && mVel < 0;
- }
- } else if (dtms > 0) {
- final float dt = dtms * 0.001f; // ms -> s
- if (DEBUG) logf("tick: v=%.2fpx/s dt=%.4fs", mVel, dt);
- if (DEBUG) logf("tick: before: h=%d", (int) mExpandedHeight);
-
- final float fh = getMaxPanelHeight();
- boolean braking = false;
- if (BRAKES) {
- if (mClosing) {
- braking = mExpandedHeight <= mCollapseBrakingDistancePx;
- mAccel = braking ? 10*mCollapseAccelPx : -mCollapseAccelPx;
- } else {
- braking = mExpandedHeight >= (fh-mExpandBrakingDistancePx);
- mAccel = braking ? 10*-mExpandAccelPx : mExpandAccelPx;
- }
- } else {
- mAccel = mClosing ? -mCollapseAccelPx : mExpandAccelPx;
- }
-
- mVel += mAccel * dt;
-
- if (braking) {
- if (mClosing && mVel > -mBrakingSpeedPx) {
- mVel = -mBrakingSpeedPx;
- } else if (!mClosing && mVel < mBrakingSpeedPx) {
- mVel = mBrakingSpeedPx;
- }
- } else {
- if (mClosing && mVel > -mFlingCollapseMinVelocityPx) {
- mVel = -mFlingCollapseMinVelocityPx;
- } else if (!mClosing && mVel > mFlingGestureMaxOutputVelocityPx) {
- mVel = mFlingGestureMaxOutputVelocityPx;
- }
- }
-
- float h = mExpandedHeight + mVel * dt;
-
- if (DEBUG) logf("tick: new h=%d closing=%s", (int) h, mClosing?"true":"false");
-
- setExpandedHeightInternal(h);
-
- mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
-
- if (mVel == 0
- || (mClosing && mExpandedHeight == 0)
- || (!mClosing && mExpandedHeight == fh)) {
- post(mStopAnimator);
- }
- } else {
- Log.v(TAG, "animationTick called with dtms=" + dtms + "; nothing to do (h="
- + mExpandedHeight + " v=" + mVel + ")");
- }
- }
-
public PanelView(Context context, AttributeSet attrs) {
super(context, attrs);
-
- mTimeAnimator = new TimeAnimator();
- mTimeAnimator.setTimeListener(mAnimationCallback);
- setOnHierarchyChangeListener(mHierarchyListener);
+ mFlingAnimationUtils = new FlingAnimationUtils(context, 0.6f);
}
protected void loadDimens() {
final Resources res = getContext().getResources();
-
- mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
- mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
- mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
- mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
-
- mFlingGestureMinDistPx = res.getDimension(R.dimen.fling_gesture_min_dist);
-
- mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
- mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
-
- mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
- mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
-
- mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
-
- mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity);
-
mPeekHeight = res.getDimension(R.dimen.peek_height)
+ getPaddingBottom(); // our window might have a dropshadow
@@ -273,7 +138,9 @@ public class PanelView extends FrameLayout {
initVelocityTracker();
}
trackMovement(event);
- mTimeAnimator.cancel(); // end any outstanding animations
+ if (mHeightAnimator != null) {
+ mHeightAnimator.cancel(); // end any outstanding animations
+ }
onTrackingStarted();
mInitialOffsetOnTouch = mExpandedHeight;
if (mExpandedHeight == 0) {
@@ -314,15 +181,11 @@ public class PanelView extends FrameLayout {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- mFinalTouchY = y;
mTracking = false;
mTrackingPointer = -1;
onTrackingStopped();
trackMovement(event);
-
- float vel = getCurrentVelocity();
- fling(vel, true);
-
+ flingWithCurrentVelocity();
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
@@ -342,53 +205,13 @@ public class PanelView extends FrameLayout {
}
private float getCurrentVelocity() {
- float vel = 0;
- float yVel = 0, xVel = 0;
- boolean negative = false;
// the velocitytracker might be null if we got a bad input stream
if (mVelocityTracker == null) {
return 0;
}
-
mVelocityTracker.computeCurrentVelocity(1000);
-
- yVel = mVelocityTracker.getYVelocity();
- negative = yVel < 0;
-
- xVel = mVelocityTracker.getXVelocity();
- if (xVel < 0) {
- xVel = -xVel;
- }
- if (xVel > mFlingGestureMaxXVelocityPx) {
- xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
- }
-
- vel = (float) Math.hypot(yVel, xVel);
- if (vel > mFlingGestureMaxOutputVelocityPx) {
- vel = mFlingGestureMaxOutputVelocityPx;
- }
-
- // if you've barely moved your finger, we treat the velocity as 0
- // preventing spurious flings due to touch screen jitter
- final float deltaY = Math.abs(mFinalTouchY - mInitialTouchY);
- if (deltaY < mFlingGestureMinDistPx
- || vel < mFlingExpandMinVelocityPx
- ) {
- vel = 0;
- }
-
- if (negative) {
- vel = -vel;
- }
-
- if (DEBUG) {
- logf("gesture: dy=%f vel=(%f,%f) vlinear=%f",
- deltaY,
- xVel, yVel,
- vel);
- }
- return vel;
+ return mVelocityTracker.getYVelocity();
}
@Override
@@ -413,8 +236,8 @@ public class PanelView extends FrameLayout {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
- if (mTimeAnimator.isRunning()) {
- mTimeAnimator.cancel(); // end any outstanding animations
+ if (mHeightAnimator != null) {
+ mHeightAnimator.cancel(); // end any outstanding animations
return true;
}
mInitialTouchY = y;
@@ -479,15 +302,47 @@ public class PanelView extends FrameLayout {
mMaxPanelHeight = -1;
}
- public void fling(float vel, boolean always) {
- if (DEBUG) logf("fling: vel=%.3f, this=%s", vel, this);
- mVel = vel;
+ private void flingWithCurrentVelocity() {
+ float vel = getCurrentVelocity();
+ boolean expand;
+ if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
+ expand = getExpandedFraction() > 0.5f;
+ } else {
+ expand = vel > 0;
+ }
+ fling(vel, expand);
+ }
- if (always||mVel != 0) {
- animationTick(0); // begin the animation
+ protected void fling(float vel, boolean expand) {
+ cancelPeek();
+ float target = expand ? getMaxPanelHeight() : 0.0f;
+ ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, target);
+ if (expand) {
+ mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight());
} else {
- onExpandingFinished();
+ mFlingAnimationUtils.applyDismissing(animator, mExpandedHeight, target, vel,
+ getHeight());
+
+ // Make it shorter if we run a canned animation
+ if (vel == 0) {
+ animator.setDuration((long) (animator.getDuration() / 1.75f));
+ }
}
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ setExpandedHeight((Float) animation.getAnimatedValue());
+ }
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mHeightAnimator = null;
+ onExpandingFinished();
+ }
+ });
+ animator.start();
+ mHeightAnimator = animator;
}
@Override
@@ -500,7 +355,6 @@ public class PanelView extends FrameLayout {
return mViewName;
}
- // Rubberbands the panel to hold its contents.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -514,25 +368,16 @@ public class PanelView extends FrameLayout {
// we only adapt the max height if it's bigger
mMaxPanelHeight = newHeight;
// If the user isn't actively poking us, let's rubberband to the content
- if (!mTracking && !mTimeAnimator.isStarted()
+ if (!mTracking && mHeightAnimator == null
&& mExpandedHeight > 0 && mExpandedHeight != mMaxPanelHeight
&& mMaxPanelHeight > 0) {
mExpandedHeight = mMaxPanelHeight;
}
}
- setMeasuredDimension(getMeasuredWidth(), getDesiredMeasureHeight());
- }
-
- protected int getDesiredMeasureHeight() {
- return (int) mExpandedHeight;
}
-
public void setExpandedHeight(float height) {
if (DEBUG) logf("setExpandedHeight(%.1f)", height);
- if (mTimeAnimator.isStarted()) {
- post(mStopAnimator);
- }
setExpandedHeightInternal(height);
mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
}
@@ -549,43 +394,21 @@ public class PanelView extends FrameLayout {
float currentMaxPanelHeight = getMaxPanelHeight();
// If the user isn't actively poking us, let's update the height
- if (!mTracking && !mTimeAnimator.isStarted()
+ if (!mTracking && mHeightAnimator == null
&& mExpandedHeight > 0 && currentMaxPanelHeight != mExpandedHeight) {
setExpandedHeightInternal(currentMaxPanelHeight);
}
}
public void setExpandedHeightInternal(float h) {
- if (Float.isNaN(h)) {
- // If a NaN gets in here, it will freeze the Animators.
- if (DEBUG_NAN) {
- Log.v(TAG, "setExpandedHeightInternal: warning: h=NaN, using 0 instead",
- new Throwable());
- }
- h = 0;
- }
-
float fh = getMaxPanelHeight();
- if (fh == 0) {
- // Hmm, full height hasn't been computed yet
- }
-
- if (h < 0) h = 0;
- if (h > fh) h = fh;
-
mExpandedHeight = h;
if (DEBUG) {
- logf("setExpansion: height=%.1f fh=%.1f tracking=%s", h, fh,
- mTracking ? "T" : "f");
+ logf("setExpansion: height=%.1f fh=%.1f tracking=%s", h, fh, mTracking ? "T" : "f");
}
onHeightUpdated(mExpandedHeight);
-
-// FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
-// lp.height = (int) mExpandedHeight;
-// setLayoutParams(lp);
-
mExpandedFraction = Math.min(1f, (fh == 0) ? 0 : h / fh);
}
@@ -605,14 +428,6 @@ public class PanelView extends FrameLayout {
}
public void setExpandedFraction(float frac) {
- if (Float.isNaN(frac)) {
- // If a NaN gets in here, it will freeze the Animators.
- if (DEBUG_NAN) {
- Log.v(TAG, "setExpandedFraction: frac=NaN, using 0 instead",
- new Throwable());
- }
- frac = 0;
- }
setExpandedHeight(getMaxPanelHeight() * frac);
}
@@ -648,11 +463,12 @@ public class PanelView extends FrameLayout {
// TODO: abort animation or ongoing touch
if (DEBUG) logf("collapse: " + this);
if (!isFullyCollapsed()) {
- mTimeAnimator.cancel();
+ if (mHeightAnimator != null) {
+ mHeightAnimator.cancel();
+ }
mClosing = true;
onExpandingStarted();
- // collapse() should never be a rubberband, even if an animation is already running
- fling(-mSelfCollapseVelocityPx, /*always=*/ true);
+ fling(0, false /* expand */);
}
}
@@ -661,7 +477,7 @@ public class PanelView extends FrameLayout {
if (isFullyCollapsed()) {
mBar.startOpeningPanel(this);
onExpandingStarted();
- fling(mSelfExpandVelocityPx, /*always=*/ true);
+ fling(0, true /* expand */);
} else if (DEBUG) {
if (DEBUG) logf("skipping expansion: is expanded");
}
@@ -684,18 +500,7 @@ public class PanelView extends FrameLayout {
mTracking?"T":"f",
mJustPeeked?"T":"f",
mPeekAnimator, ((mPeekAnimator!=null && mPeekAnimator.isStarted())?" (started)":""),
- mTimeAnimator, ((mTimeAnimator!=null && mTimeAnimator.isStarted())?" (started)":"")
+ mHeightAnimator, ((mHeightAnimator !=null && mHeightAnimator.isStarted())?" (started)":"")
));
}
-
- private final OnHierarchyChangeListener mHierarchyListener = new OnHierarchyChangeListener() {
- @Override
- public void onChildViewAdded(View parent, View child) {
- if (DEBUG) logf("onViewAdded: " + child);
- }
-
- @Override
- public void onChildViewRemoved(View parent, View child) {
- }
- };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 3ef998e..90f3d17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -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);
}