diff options
| author | Chet Haase <chet@google.com> | 2011-10-18 13:45:00 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-10-18 13:45:00 -0700 |
| commit | 87bc53de2adf479ad5a5e226bf3d8fd31af6dc21 (patch) | |
| tree | 3263f7de99691f1cd305efa6ef4a5402e3d866c8 /packages | |
| parent | 07848843b23e10e4728fa779cc79fc38a341cf6b (diff) | |
| parent | 2f2022afa1eb85018368398bd150e9575fc099c9 (diff) | |
| download | frameworks_base-87bc53de2adf479ad5a5e226bf3d8fd31af6dc21.zip frameworks_base-87bc53de2adf479ad5a5e226bf3d8fd31af6dc21.tar.gz frameworks_base-87bc53de2adf479ad5a5e226bf3d8fd31af6dc21.tar.bz2 | |
Merge "Make notification panel delete-all animation smoother" into ics-mr0
Diffstat (limited to 'packages')
3 files changed, 101 insertions, 51 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index 07281d4..14ce266 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -17,6 +17,7 @@ package com.android.systemui; import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.Animator.AnimatorListener; import android.animation.ValueAnimator; @@ -40,6 +41,8 @@ public class SwipeHelper { public static final int X = 0; public static final int Y = 1; + private static LinearInterpolator sLinearInterpolator = new LinearInterpolator(); + private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms @@ -199,6 +202,10 @@ public class SwipeHelper { return mDragging; } + /** + * @param view The view to be dismissed + * @param velocity The desired pixels/second speed at which the view should move + */ public void dismissChild(final View view, float velocity) { final View animView = mCallback.getChildContentView(view); final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); @@ -221,22 +228,14 @@ public class SwipeHelper { duration = DEFAULT_ESCAPE_ANIMATION_DURATION; } + animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); ObjectAnimator anim = createTranslationAnimation(animView, newPos); - anim.setInterpolator(new LinearInterpolator()); + anim.setInterpolator(sLinearInterpolator); anim.setDuration(duration); - anim.addListener(new AnimatorListener() { - public void onAnimationStart(Animator animation) { - } - - public void onAnimationRepeat(Animator animation) { - } - + anim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { mCallback.onChildDismissed(view); - } - - public void onAnimationCancel(Animator animation) { - mCallback.onChildDismissed(view); + animView.setLayerType(View.LAYER_TYPE_NONE, null); } }); anim.addUpdateListener(new AnimatorUpdateListener() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 4e9b411..b724552 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -50,7 +50,6 @@ import android.view.IWindowManager; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; -import android.view.Surface; import android.view.VelocityTracker; import android.view.View; import android.view.ViewGroup; @@ -213,6 +212,8 @@ public class PhoneStatusBar extends StatusBar { boolean mAnimatingReveal = false; int mViewDelta; int[] mAbsPos = new int[2]; + Runnable mPostCollapseCleanup = null; + // for disabling the status bar int mDisabled = 0; @@ -1238,6 +1239,10 @@ public class PhoneStatusBar extends StatusBar { return; } mExpanded = false; + if (mPostCollapseCleanup != null) { + mPostCollapseCleanup.run(); + mPostCollapseCleanup = null; + } } void doAnimation() { @@ -2066,49 +2071,67 @@ public class PhoneStatusBar extends StatusBar { } public void onClick(View v) { synchronized (mNotificationData) { - // let's also queue up 400ms worth of animated dismissals - final int N = mini(5, mPile.getChildCount()); + // animate-swipe all dismissable notifications, then animate the shade closed + int numChildren = mPile.getChildCount(); - final ArrayList<View> snapshot = new ArrayList<View>(N); - for (int i=0; i<N; i++) { + int scrollTop = mScrollView.getScrollY(); + int scrollBottom = scrollTop + mScrollView.getHeight(); + final ArrayList<View> snapshot = new ArrayList<View>(numChildren); + for (int i=0; i<numChildren; i++) { final View child = mPile.getChildAt(i); - if (mPile.canChildBeDismissed(child)) snapshot.add(child); + if (mPile.canChildBeDismissed(child) && child.getBottom() > scrollTop && + child.getTop() < scrollBottom) { + snapshot.add(child); + } } + final int N = snapshot.size(); new Thread(new Runnable() { @Override public void run() { - final int ROW_DELAY = 100; - - mHandler.postDelayed(new Runnable() { - public void run() { - animateCollapse(false, 0f); - } - }, (N-1) * ROW_DELAY); - - mHandler.postDelayed(new Runnable() { + // Decrease the delay for every row we animate to give the sense of + // accelerating the swipes + final int ROW_DELAY_DECREMENT = 10; + int currentDelay = 140; + int totalDelay = 0; + + // Set the shade-animating state to avoid doing other work during + // all of these animations. In particular, avoid layout and + // redrawing when collapsing the shade. + mPile.setViewRemoval(false); + + mPostCollapseCleanup = new Runnable() { public void run() { try { + mPile.setViewRemoval(true); mBarService.onClearAllNotifications(); - } catch (RemoteException ex) { } + } catch (Exception ex) { } } - }, N * ROW_DELAY + 500); - - mPile.setAnimateBounds(false); // temporarily disable some re-layouts + }; + View sampleView = snapshot.get(0); + int width = sampleView.getWidth(); + final int velocity = (int)(width * 8); // 1000/8 = 125 ms duration for (View v : snapshot) { final View _v = v; - mHandler.post(new Runnable() { + mHandler.postDelayed(new Runnable() { @Override public void run() { - mPile.dismissRowAnimated(_v, (int)(ROW_DELAY*0.25f)); + mPile.dismissRowAnimated(_v, velocity); } - }); - try { - Thread.sleep(ROW_DELAY); - } catch (InterruptedException ex) { } + }, totalDelay); + currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT); + totalDelay += currentDelay; } - - mPile.setAnimateBounds(true); // reenable layout animation + // Delay the collapse animation until after all swipe animations have + // finished. Provide some buffer because there may be some extra delay + // before actually starting each swipe animation. Ideally, we'd + // synchronize the end of those animations with the start of the collaps + // exactly. + mHandler.postDelayed(new Runnable() { + public void run() { + animateCollapse(false); + } + }, totalDelay + 225); } }).start(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java index a7342dc..3649f75 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.policy; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; @@ -29,7 +28,6 @@ import android.util.AttributeSet; import android.util.Log; import android.util.Slog; import android.view.MotionEvent; -import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; @@ -59,6 +57,10 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call private SwipeHelper mSwipeHelper; + // Flag set during notification removal animation to avoid causing too much work until + // animation is done + boolean mRemoveViews = true; + public NotificationRowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } @@ -117,7 +119,7 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call public void onChildDismissed(View v) { final View veto = v.findViewById(R.id.veto); - if (veto != null && veto.getVisibility() != View.GONE) { + if (veto != null && veto.getVisibility() != View.GONE && mRemoveViews) { veto.performClick(); } } @@ -170,7 +172,6 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call final View childF = child; if (mAnimateBounds) { - child.setPivotY(0); final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f); alphaFade.setDuration(APPEAR_ANIM_LEN); alphaFade.addListener(new AnimatorListenerAdapter() { @@ -189,6 +190,16 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call } } + /** + * Sets a flag to tell us whether to actually remove views. Removal is delayed by setting this + * to false during some animations to smooth out performance. Callers should restore the + * flag to true after the animation is done, and then they should make sure that the views + * get removed properly. + */ + public void setViewRemoval(boolean removeViews) { + mRemoveViews = removeViews; + } + public void dismissRowAnimated(View child) { dismissRowAnimated(child, 0); } @@ -199,16 +210,34 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call @Override public void removeView(View child) { - final View childF = child; + if (!mRemoveViews) { + // This flag is cleared during an animation that removes all notifications. There + // should be a call to remove all notifications when the animation is done, at which + // time the view will be removed. + return; + } if (mAnimateBounds) { if (mAppearingViews.containsKey(child)) { mAppearingViews.remove(child); } - child.setPivotY(0); - final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f); - alphaFade.setDuration(DISAPPEAR_ANIM_LEN); - alphaFade.addListener(new AnimatorListenerAdapter() { + // Don't fade it out if it already has a low alpha value, but run a non-visual + // animation which is used by onLayout() to animate shrinking the gap that it left + // in the list + ValueAnimator anim; + float currentAlpha = child.getAlpha(); + if (currentAlpha > .1) { + anim = ObjectAnimator.ofFloat(child, "alpha", currentAlpha, 0); + } else { + if (currentAlpha > 0) { + // Just make it go away - no need to render it anymore + child.setAlpha(0); + } + anim = ValueAnimator.ofFloat(0, 1); + } + anim.setDuration(DISAPPEAR_ANIM_LEN); + final View childF = child; + anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (DEBUG) Slog.d(TAG, "actually removing child: " + childF); @@ -218,9 +247,8 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call } }); - alphaFade.start(); - - mDisappearingViews.put(child, alphaFade); + anim.start(); + mDisappearingViews.put(child, anim); requestLayout(); // start the container animation } else { |
