Loading core/java/android/view/ViewRootImpl.java +36 −0 Original line number Original line Diff line number Diff line Loading @@ -108,6 +108,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV; private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV; private static final boolean DEBUG_IMF = false || LOCAL_LOGV; private static final boolean DEBUG_IMF = false || LOCAL_LOGV; private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV; private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV; private static final boolean DEBUG_FPS = false; private static final boolean WATCH_POINTER = false; private static final boolean WATCH_POINTER = false; /** /** Loading Loading @@ -274,6 +275,11 @@ public final class ViewRootImpl extends Handler implements ViewParent, private Thread mRenderProfiler; private Thread mRenderProfiler; private volatile boolean mRenderProfilingEnabled; private volatile boolean mRenderProfilingEnabled; // Variables to track frames per second, enabled via DEBUG_FPS flag private long mFpsStartTime = -1; private long mFpsPrevTime = -1; private int mFpsNumFrames; /** /** * see {@link #playSoundEffect(int)} * see {@link #playSoundEffect(int)} */ */ Loading Loading @@ -1766,12 +1772,42 @@ public final class ViewRootImpl extends Handler implements ViewParent, } } } } /** * Called from draw() when DEBUG_FPS is enabled */ private void trackFPS() { // Tracks frames per second drawn. First value in a series of draws may be bogus // because it down not account for the intervening idle time long nowTime = System.currentTimeMillis(); if (mFpsStartTime < 0) { mFpsStartTime = mFpsPrevTime = nowTime; mFpsNumFrames = 0; } else { ++mFpsNumFrames; String thisHash = Integer.toHexString(System.identityHashCode(this)); long frameTime = nowTime - mFpsPrevTime; long totalTime = nowTime - mFpsStartTime; Log.v(TAG, "0x" + thisHash + "\tFrame time:\t" + frameTime); mFpsPrevTime = nowTime; if (totalTime > 1000) { float fps = (float) mFpsNumFrames * 1000 / totalTime; Log.v(TAG, "0x" + thisHash + "\tFPS:\t" + fps); mFpsStartTime = nowTime; mFpsNumFrames = 0; } } } private void draw(boolean fullRedrawNeeded) { private void draw(boolean fullRedrawNeeded) { Surface surface = mSurface; Surface surface = mSurface; if (surface == null || !surface.isValid()) { if (surface == null || !surface.isValid()) { return; return; } } if (DEBUG_FPS) { trackFPS(); } if (!sFirstDrawComplete) { if (!sFirstDrawComplete) { synchronized (sFirstDrawHandlers) { synchronized (sFirstDrawHandlers) { sFirstDrawComplete = true; sFirstDrawComplete = true; Loading packages/SystemUI/src/com/android/systemui/SwipeHelper.java +11 −12 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui; package com.android.systemui; import android.animation.Animator; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.ObjectAnimator; import android.animation.Animator.AnimatorListener; import android.animation.Animator.AnimatorListener; import android.animation.ValueAnimator; import android.animation.ValueAnimator; Loading @@ -40,6 +41,8 @@ public class SwipeHelper { public static final int X = 0; public static final int X = 0; public static final int Y = 1; public static final int Y = 1; private static LinearInterpolator sLinearInterpolator = new LinearInterpolator(); private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms Loading Loading @@ -199,6 +202,10 @@ public class SwipeHelper { return mDragging; 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) { public void dismissChild(final View view, float velocity) { final View animView = mCallback.getChildContentView(view); final View animView = mCallback.getChildContentView(view); final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); Loading @@ -221,22 +228,14 @@ public class SwipeHelper { duration = DEFAULT_ESCAPE_ANIMATION_DURATION; duration = DEFAULT_ESCAPE_ANIMATION_DURATION; } } animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); ObjectAnimator anim = createTranslationAnimation(animView, newPos); ObjectAnimator anim = createTranslationAnimation(animView, newPos); anim.setInterpolator(new LinearInterpolator()); anim.setInterpolator(sLinearInterpolator); anim.setDuration(duration); anim.setDuration(duration); anim.addListener(new AnimatorListener() { anim.addListener(new AnimatorListenerAdapter() { public void onAnimationStart(Animator animation) { } public void onAnimationRepeat(Animator animation) { } public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) { mCallback.onChildDismissed(view); mCallback.onChildDismissed(view); } animView.setLayerType(View.LAYER_TYPE_NONE, null); public void onAnimationCancel(Animator animation) { mCallback.onChildDismissed(view); } } }); }); anim.addUpdateListener(new AnimatorUpdateListener() { anim.addUpdateListener(new AnimatorUpdateListener() { Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +50 −27 Original line number Original line Diff line number Diff line Loading @@ -50,7 +50,6 @@ import android.view.IWindowManager; import android.view.KeyEvent; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.MotionEvent; import android.view.Surface; import android.view.VelocityTracker; import android.view.VelocityTracker; import android.view.View; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup; Loading Loading @@ -213,6 +212,8 @@ public class PhoneStatusBar extends StatusBar { boolean mAnimatingReveal = false; boolean mAnimatingReveal = false; int mViewDelta; int mViewDelta; int[] mAbsPos = new int[2]; int[] mAbsPos = new int[2]; Runnable mPostCollapseCleanup = null; // for disabling the status bar // for disabling the status bar int mDisabled = 0; int mDisabled = 0; Loading Loading @@ -1238,6 +1239,10 @@ public class PhoneStatusBar extends StatusBar { return; return; } } mExpanded = false; mExpanded = false; if (mPostCollapseCleanup != null) { mPostCollapseCleanup.run(); mPostCollapseCleanup = null; } } } void doAnimation() { void doAnimation() { Loading Loading @@ -2066,49 +2071,67 @@ public class PhoneStatusBar extends StatusBar { } } public void onClick(View v) { public void onClick(View v) { synchronized (mNotificationData) { synchronized (mNotificationData) { // let's also queue up 400ms worth of animated dismissals // animate-swipe all dismissable notifications, then animate the shade closed final int N = mini(5, mPile.getChildCount()); int numChildren = mPile.getChildCount(); final ArrayList<View> snapshot = new ArrayList<View>(N); int scrollTop = mScrollView.getScrollY(); for (int i=0; i<N; i++) { 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); 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() { new Thread(new Runnable() { @Override @Override public void run() { public void run() { final int ROW_DELAY = 100; // Decrease the delay for every row we animate to give the sense of // accelerating the swipes mHandler.postDelayed(new Runnable() { final int ROW_DELAY_DECREMENT = 10; public void run() { int currentDelay = 140; animateCollapse(false, 0f); int totalDelay = 0; } }, (N-1) * ROW_DELAY); // Set the shade-animating state to avoid doing other work during // all of these animations. In particular, avoid layout and mHandler.postDelayed(new Runnable() { // redrawing when collapsing the shade. mPile.setViewRemoval(false); mPostCollapseCleanup = new Runnable() { public void run() { public void run() { try { try { mPile.setViewRemoval(true); mBarService.onClearAllNotifications(); 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) { for (View v : snapshot) { final View _v = v; final View _v = v; mHandler.post(new Runnable() { mHandler.postDelayed(new Runnable() { @Override @Override public void run() { public void run() { mPile.dismissRowAnimated(_v, (int)(ROW_DELAY*0.25f)); mPile.dismissRowAnimated(_v, velocity); } } }); }, totalDelay); try { currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT); Thread.sleep(ROW_DELAY); totalDelay += currentDelay; } catch (InterruptedException ex) { } } } // Delay the collapse animation until after all swipe animations have mPile.setAnimateBounds(true); // reenable layout animation // 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(); }).start(); } } Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java +40 −12 Original line number Original line Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.policy; import android.animation.Animator; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.content.Context; Loading @@ -29,7 +28,6 @@ import android.util.AttributeSet; import android.util.Log; import android.util.Log; import android.util.Slog; import android.util.Slog; import android.view.MotionEvent; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewGroup; Loading Loading @@ -59,6 +57,10 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call private SwipeHelper mSwipeHelper; 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) { public NotificationRowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); this(context, attrs, 0); } } Loading Loading @@ -117,7 +119,7 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call public void onChildDismissed(View v) { public void onChildDismissed(View v) { final View veto = v.findViewById(R.id.veto); 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(); veto.performClick(); } } } } Loading Loading @@ -170,7 +172,6 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call final View childF = child; final View childF = child; if (mAnimateBounds) { if (mAnimateBounds) { child.setPivotY(0); final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f); final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f); alphaFade.setDuration(APPEAR_ANIM_LEN); alphaFade.setDuration(APPEAR_ANIM_LEN); alphaFade.addListener(new AnimatorListenerAdapter() { alphaFade.addListener(new AnimatorListenerAdapter() { Loading @@ -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) { public void dismissRowAnimated(View child) { dismissRowAnimated(child, 0); dismissRowAnimated(child, 0); } } Loading @@ -199,16 +210,34 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call @Override @Override public void removeView(View child) { 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 (mAnimateBounds) { if (mAppearingViews.containsKey(child)) { if (mAppearingViews.containsKey(child)) { mAppearingViews.remove(child); mAppearingViews.remove(child); } } child.setPivotY(0); final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f); // Don't fade it out if it already has a low alpha value, but run a non-visual alphaFade.setDuration(DISAPPEAR_ANIM_LEN); // animation which is used by onLayout() to animate shrinking the gap that it left alphaFade.addListener(new AnimatorListenerAdapter() { // 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 @Override public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) { if (DEBUG) Slog.d(TAG, "actually removing child: " + childF); if (DEBUG) Slog.d(TAG, "actually removing child: " + childF); Loading @@ -218,9 +247,8 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call } } }); }); alphaFade.start(); anim.start(); mDisappearingViews.put(child, anim); mDisappearingViews.put(child, alphaFade); requestLayout(); // start the container animation requestLayout(); // start the container animation } else { } else { Loading Loading
core/java/android/view/ViewRootImpl.java +36 −0 Original line number Original line Diff line number Diff line Loading @@ -108,6 +108,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV; private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV; private static final boolean DEBUG_IMF = false || LOCAL_LOGV; private static final boolean DEBUG_IMF = false || LOCAL_LOGV; private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV; private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV; private static final boolean DEBUG_FPS = false; private static final boolean WATCH_POINTER = false; private static final boolean WATCH_POINTER = false; /** /** Loading Loading @@ -274,6 +275,11 @@ public final class ViewRootImpl extends Handler implements ViewParent, private Thread mRenderProfiler; private Thread mRenderProfiler; private volatile boolean mRenderProfilingEnabled; private volatile boolean mRenderProfilingEnabled; // Variables to track frames per second, enabled via DEBUG_FPS flag private long mFpsStartTime = -1; private long mFpsPrevTime = -1; private int mFpsNumFrames; /** /** * see {@link #playSoundEffect(int)} * see {@link #playSoundEffect(int)} */ */ Loading Loading @@ -1766,12 +1772,42 @@ public final class ViewRootImpl extends Handler implements ViewParent, } } } } /** * Called from draw() when DEBUG_FPS is enabled */ private void trackFPS() { // Tracks frames per second drawn. First value in a series of draws may be bogus // because it down not account for the intervening idle time long nowTime = System.currentTimeMillis(); if (mFpsStartTime < 0) { mFpsStartTime = mFpsPrevTime = nowTime; mFpsNumFrames = 0; } else { ++mFpsNumFrames; String thisHash = Integer.toHexString(System.identityHashCode(this)); long frameTime = nowTime - mFpsPrevTime; long totalTime = nowTime - mFpsStartTime; Log.v(TAG, "0x" + thisHash + "\tFrame time:\t" + frameTime); mFpsPrevTime = nowTime; if (totalTime > 1000) { float fps = (float) mFpsNumFrames * 1000 / totalTime; Log.v(TAG, "0x" + thisHash + "\tFPS:\t" + fps); mFpsStartTime = nowTime; mFpsNumFrames = 0; } } } private void draw(boolean fullRedrawNeeded) { private void draw(boolean fullRedrawNeeded) { Surface surface = mSurface; Surface surface = mSurface; if (surface == null || !surface.isValid()) { if (surface == null || !surface.isValid()) { return; return; } } if (DEBUG_FPS) { trackFPS(); } if (!sFirstDrawComplete) { if (!sFirstDrawComplete) { synchronized (sFirstDrawHandlers) { synchronized (sFirstDrawHandlers) { sFirstDrawComplete = true; sFirstDrawComplete = true; Loading
packages/SystemUI/src/com/android/systemui/SwipeHelper.java +11 −12 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui; package com.android.systemui; import android.animation.Animator; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.ObjectAnimator; import android.animation.Animator.AnimatorListener; import android.animation.Animator.AnimatorListener; import android.animation.ValueAnimator; import android.animation.ValueAnimator; Loading @@ -40,6 +41,8 @@ public class SwipeHelper { public static final int X = 0; public static final int X = 0; public static final int Y = 1; public static final int Y = 1; private static LinearInterpolator sLinearInterpolator = new LinearInterpolator(); private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms Loading Loading @@ -199,6 +202,10 @@ public class SwipeHelper { return mDragging; 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) { public void dismissChild(final View view, float velocity) { final View animView = mCallback.getChildContentView(view); final View animView = mCallback.getChildContentView(view); final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); Loading @@ -221,22 +228,14 @@ public class SwipeHelper { duration = DEFAULT_ESCAPE_ANIMATION_DURATION; duration = DEFAULT_ESCAPE_ANIMATION_DURATION; } } animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); ObjectAnimator anim = createTranslationAnimation(animView, newPos); ObjectAnimator anim = createTranslationAnimation(animView, newPos); anim.setInterpolator(new LinearInterpolator()); anim.setInterpolator(sLinearInterpolator); anim.setDuration(duration); anim.setDuration(duration); anim.addListener(new AnimatorListener() { anim.addListener(new AnimatorListenerAdapter() { public void onAnimationStart(Animator animation) { } public void onAnimationRepeat(Animator animation) { } public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) { mCallback.onChildDismissed(view); mCallback.onChildDismissed(view); } animView.setLayerType(View.LAYER_TYPE_NONE, null); public void onAnimationCancel(Animator animation) { mCallback.onChildDismissed(view); } } }); }); anim.addUpdateListener(new AnimatorUpdateListener() { anim.addUpdateListener(new AnimatorUpdateListener() { Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +50 −27 Original line number Original line Diff line number Diff line Loading @@ -50,7 +50,6 @@ import android.view.IWindowManager; import android.view.KeyEvent; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.MotionEvent; import android.view.Surface; import android.view.VelocityTracker; import android.view.VelocityTracker; import android.view.View; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup; Loading Loading @@ -213,6 +212,8 @@ public class PhoneStatusBar extends StatusBar { boolean mAnimatingReveal = false; boolean mAnimatingReveal = false; int mViewDelta; int mViewDelta; int[] mAbsPos = new int[2]; int[] mAbsPos = new int[2]; Runnable mPostCollapseCleanup = null; // for disabling the status bar // for disabling the status bar int mDisabled = 0; int mDisabled = 0; Loading Loading @@ -1238,6 +1239,10 @@ public class PhoneStatusBar extends StatusBar { return; return; } } mExpanded = false; mExpanded = false; if (mPostCollapseCleanup != null) { mPostCollapseCleanup.run(); mPostCollapseCleanup = null; } } } void doAnimation() { void doAnimation() { Loading Loading @@ -2066,49 +2071,67 @@ public class PhoneStatusBar extends StatusBar { } } public void onClick(View v) { public void onClick(View v) { synchronized (mNotificationData) { synchronized (mNotificationData) { // let's also queue up 400ms worth of animated dismissals // animate-swipe all dismissable notifications, then animate the shade closed final int N = mini(5, mPile.getChildCount()); int numChildren = mPile.getChildCount(); final ArrayList<View> snapshot = new ArrayList<View>(N); int scrollTop = mScrollView.getScrollY(); for (int i=0; i<N; i++) { 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); 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() { new Thread(new Runnable() { @Override @Override public void run() { public void run() { final int ROW_DELAY = 100; // Decrease the delay for every row we animate to give the sense of // accelerating the swipes mHandler.postDelayed(new Runnable() { final int ROW_DELAY_DECREMENT = 10; public void run() { int currentDelay = 140; animateCollapse(false, 0f); int totalDelay = 0; } }, (N-1) * ROW_DELAY); // Set the shade-animating state to avoid doing other work during // all of these animations. In particular, avoid layout and mHandler.postDelayed(new Runnable() { // redrawing when collapsing the shade. mPile.setViewRemoval(false); mPostCollapseCleanup = new Runnable() { public void run() { public void run() { try { try { mPile.setViewRemoval(true); mBarService.onClearAllNotifications(); 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) { for (View v : snapshot) { final View _v = v; final View _v = v; mHandler.post(new Runnable() { mHandler.postDelayed(new Runnable() { @Override @Override public void run() { public void run() { mPile.dismissRowAnimated(_v, (int)(ROW_DELAY*0.25f)); mPile.dismissRowAnimated(_v, velocity); } } }); }, totalDelay); try { currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT); Thread.sleep(ROW_DELAY); totalDelay += currentDelay; } catch (InterruptedException ex) { } } } // Delay the collapse animation until after all swipe animations have mPile.setAnimateBounds(true); // reenable layout animation // 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(); }).start(); } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java +40 −12 Original line number Original line Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.policy; import android.animation.Animator; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.content.Context; Loading @@ -29,7 +28,6 @@ import android.util.AttributeSet; import android.util.Log; import android.util.Log; import android.util.Slog; import android.util.Slog; import android.view.MotionEvent; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewGroup; Loading Loading @@ -59,6 +57,10 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call private SwipeHelper mSwipeHelper; 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) { public NotificationRowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); this(context, attrs, 0); } } Loading Loading @@ -117,7 +119,7 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call public void onChildDismissed(View v) { public void onChildDismissed(View v) { final View veto = v.findViewById(R.id.veto); 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(); veto.performClick(); } } } } Loading Loading @@ -170,7 +172,6 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call final View childF = child; final View childF = child; if (mAnimateBounds) { if (mAnimateBounds) { child.setPivotY(0); final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f); final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f); alphaFade.setDuration(APPEAR_ANIM_LEN); alphaFade.setDuration(APPEAR_ANIM_LEN); alphaFade.addListener(new AnimatorListenerAdapter() { alphaFade.addListener(new AnimatorListenerAdapter() { Loading @@ -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) { public void dismissRowAnimated(View child) { dismissRowAnimated(child, 0); dismissRowAnimated(child, 0); } } Loading @@ -199,16 +210,34 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call @Override @Override public void removeView(View child) { 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 (mAnimateBounds) { if (mAppearingViews.containsKey(child)) { if (mAppearingViews.containsKey(child)) { mAppearingViews.remove(child); mAppearingViews.remove(child); } } child.setPivotY(0); final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f); // Don't fade it out if it already has a low alpha value, but run a non-visual alphaFade.setDuration(DISAPPEAR_ANIM_LEN); // animation which is used by onLayout() to animate shrinking the gap that it left alphaFade.addListener(new AnimatorListenerAdapter() { // 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 @Override public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) { if (DEBUG) Slog.d(TAG, "actually removing child: " + childF); if (DEBUG) Slog.d(TAG, "actually removing child: " + childF); Loading @@ -218,9 +247,8 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call } } }); }); alphaFade.start(); anim.start(); mDisappearingViews.put(child, anim); mDisappearingViews.put(child, alphaFade); requestLayout(); // start the container animation requestLayout(); // start the container animation } else { } else { Loading