diff options
author | Jim Miller <jaggies@google.com> | 2011-01-12 20:07:36 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-01-12 20:07:36 -0800 |
commit | 66707eee84ee874f60ff5d25c5d2d00769e79616 (patch) | |
tree | 81225805aa0dd004f07bbea37f4096a96d366568 /packages/SystemUI/src/com/android/systemui/statusbar | |
parent | ef9932c2505eaf5a4256c6c398aa640bee3b47ea (diff) | |
parent | 85babff4a30d1baf8841749b706bd31dcaa1a73a (diff) | |
download | frameworks_base-66707eee84ee874f60ff5d25c5d2d00769e79616.zip frameworks_base-66707eee84ee874f60ff5d25c5d2d00769e79616.tar.gz frameworks_base-66707eee84ee874f60ff5d25c5d2d00769e79616.tar.bz2 |
Merge "Fix 3253629: Tweaks to recent apps" into honeycomb
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui/statusbar')
3 files changed, 204 insertions, 91 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java index ffbc0e3..a2f6e3a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java @@ -194,10 +194,11 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel, AnimatorSet mContentAnim; // should group this into a multi-property animation - final int OPEN_DURATION = 250; + final int OPEN_DURATION = 136; + final int CLOSE_DURATION = 250; // the panel will start to appear this many px from the end - final int HYPERSPACE_OFFRAMP = 120; + final int HYPERSPACE_OFFRAMP = 30; Choreographer() { } @@ -223,13 +224,13 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel, end = y + HYPERSPACE_OFFRAMP; } Animator posAnim = ObjectAnimator.ofFloat(mContentParent, "translationY", start, end); - posAnim.setInterpolator(appearing + posAnim.setInterpolator(appearing ? new android.view.animation.DecelerateInterpolator(2.0f) : new android.view.animation.AccelerateInterpolator(2.0f)); Animator glowAnim = ObjectAnimator.ofFloat(mGlow, "alpha", mGlow.getAlpha(), appearing ? 1.0f : 0.0f); - glowAnim.setInterpolator(appearing + glowAnim.setInterpolator(appearing ? new android.view.animation.AccelerateInterpolator(1.0f) : new android.view.animation.DecelerateInterpolator(1.0f)); @@ -241,7 +242,7 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel, .with(bgAnim) .with(posAnim) ; - mContentAnim.setDuration(OPEN_DURATION); + mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION); mContentAnim.addListener(this); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java index 53c30fe..bab8ed3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java @@ -43,32 +43,33 @@ import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; +import android.util.Slog; import android.view.View; import android.view.View.OnClickListener; import android.view.animation.DecelerateInterpolator; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.RelativeLayout; import android.widget.TextView; import com.android.systemui.R; -public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnClickListener { +public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, OnClickListener { private static final int GLOW_PADDING = 15; private static final String TAG = "RecentAppsPanel"; private static final boolean DEBUG = TabletStatusBar.DEBUG; private static final int DISPLAY_TASKS_PORTRAIT = 7; // Limited by max binder transaction size private static final int DISPLAY_TASKS_LANDSCAPE = 5; // number of recent tasks to display private static final int MAX_TASKS = DISPLAY_TASKS_PORTRAIT + 1; // allow extra for non-apps - private static final int STAGGER_ANIMATION_DELAY = 30; - private static final long ALPHA_ANIMATION_DURATION = 120; private TabletStatusBar mBar; - private LinearLayout mRecentsContainer; - private View mRecentsGlowView; private ArrayList<ActivityDescription> mActivityDescriptions; private int mIconDpi; - private AnimatorSet mAnimationSet; - private View mBackgroundProtector; + private View mRecentsScrim; + private View mRecentsGlowView; + private LinearLayout mRecentsContainer; private Bitmap mGlowBitmap; + private boolean mShowing; + private Choreographer mChoreo; static class ActivityDescription { int id; @@ -104,6 +105,145 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC return x >= l && x < r && y >= t && y < b; } + public void show(boolean show, boolean animate) { + if (animate) { + if (mShowing != show) { + mShowing = show; + if (show) { + setVisibility(View.VISIBLE); + } + mChoreo.startAnimation(show); + } + } else { + mShowing = show; + setVisibility(show ? View.VISIBLE : View.GONE); + mChoreo.jumpTo(show); + } + } + + /** + * We need to be aligned at the bottom. LinearLayout can't do this, so instead, + * let LinearLayout do all the hard work, and then shift everything down to the bottom. + */ + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + mChoreo.setPanelHeight(mRecentsContainer.getHeight()); + } + + /** + * Whether the panel is showing, or, if it's animating, whether it will be + * when the animation is done. + */ + public boolean isShowing() { + return mShowing; + } + + private static class Choreographer implements Animator.AnimatorListener { + // should group this into a multi-property animation + private static final int OPEN_DURATION = 136; + private static final int CLOSE_DURATION = 250; + + boolean mVisible; + int mPanelHeight; + View mRootView; + View mScrimView; + View mContentView; + AnimatorSet mContentAnim; + + // the panel will start to appear this many px from the end + final int HYPERSPACE_OFFRAMP = 200; + + public Choreographer(View root, View scrim, View content) { + mRootView = root; + mScrimView = scrim; + mContentView = content; + } + + void createAnimation(boolean appearing) { + float start, end; + + if (DEBUG) Log.e(TAG, "createAnimation()", new Exception()); + + // 0: on-screen + // height: off-screen + float y = mContentView.getTranslationY(); + if (appearing) { + // we want to go from near-the-top to the top, unless we're half-open in the right + // general vicinity + start = (y < HYPERSPACE_OFFRAMP) ? y : HYPERSPACE_OFFRAMP; + end = 0; + } else { + start = y; + end = y + HYPERSPACE_OFFRAMP; + } + + Animator posAnim = ObjectAnimator.ofFloat(mContentView, "translationY", + start, end); + posAnim.setInterpolator(appearing + ? new android.view.animation.DecelerateInterpolator(2.5f) + : new android.view.animation.AccelerateInterpolator(2.5f)); + + Animator glowAnim = ObjectAnimator.ofFloat(mContentView, "alpha", + mContentView.getAlpha(), appearing ? 1.0f : 0.0f); + glowAnim.setInterpolator(appearing + ? new android.view.animation.AccelerateInterpolator(1.0f) + : new android.view.animation.DecelerateInterpolator(1.0f)); + + Animator bgAnim = ObjectAnimator.ofInt(mScrimView.getBackground(), + "alpha", appearing ? 0 : 255, appearing ? 255 : 0); + + mContentAnim = new AnimatorSet(); + mContentAnim + .play(bgAnim) + .with(glowAnim) + .with(posAnim); + mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION); + mContentAnim.addListener(this); + } + + void startAnimation(boolean appearing) { + if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")"); + + createAnimation(appearing); + + mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + mContentAnim.start(); + + mVisible = appearing; + } + + void jumpTo(boolean appearing) { + mContentView.setTranslationY(appearing ? 0 : mPanelHeight); + } + + public void setPanelHeight(int h) { + if (DEBUG) Slog.d(TAG, "panelHeight=" + h); + mPanelHeight = h; + } + + public void onAnimationCancel(Animator animation) { + if (DEBUG) Slog.d(TAG, "onAnimationCancel"); + // force this to zero so we close the window + mVisible = false; + } + + public void onAnimationEnd(Animator animation) { + if (DEBUG) Slog.d(TAG, "onAnimationEnd"); + if (!mVisible) { + mRootView.setVisibility(View.GONE); + } + mContentView.setLayerType(View.LAYER_TYPE_NONE, null); + mContentAnim = null; + } + + public void onAnimationRepeat(Animator animation) { + } + + public void onAnimationStart(Animator animation) { + } + } + public void setBar(TabletStatusBar bar) { mBar = bar; } @@ -128,12 +268,12 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC super.onFinishInflate(); mRecentsContainer = (LinearLayout) findViewById(R.id.recents_container); mRecentsGlowView = findViewById(R.id.recents_glow); - mBackgroundProtector = (View) findViewById(R.id.recents_bg_protect); + mRecentsScrim = (View) findViewById(R.id.recents_bg_protect); + mChoreo = new Choreographer(this, mRecentsScrim, mRecentsGlowView); // In order to save space, we make the background texture repeat in the Y direction - View view = findViewById(R.id.recents_bg_protect); - if (view != null && view.getBackground() instanceof BitmapDrawable) { - ((BitmapDrawable) view.getBackground()).setTileModeY(TileMode.REPEAT); + if (mRecentsScrim != null && mRecentsScrim.getBackground() instanceof BitmapDrawable) { + ((BitmapDrawable) mRecentsScrim.getBackground()).setTileModeY(TileMode.REPEAT); } } @@ -255,7 +395,10 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC if (mActivityDescriptions.size() > 0) { updateUiElements(getResources().getConfiguration(), true); } else { - mBar.animateCollapse(); + // Immediately hide this panel + mShowing = false; + setVisibility(View.GONE); + // mBar.animateCollapse(); } } @@ -284,13 +427,10 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC private void updateUiElements(Configuration config, boolean animate) { mRecentsContainer.removeAllViews(); - final float initialAlpha = 0.0f; final int first = 0; final boolean isPortrait = config.orientation == Configuration.ORIENTATION_PORTRAIT; final int taskCount = isPortrait ? DISPLAY_TASKS_PORTRAIT : DISPLAY_TASKS_LANDSCAPE; final int last = Math.min(mActivityDescriptions.size(), taskCount) - 1; - ArrayList<Animator> anims = new ArrayList<Animator>(last+1); - DecelerateInterpolator interp = new DecelerateInterpolator(); for (int i = last; i >= first; i--) { ActivityDescription activityDescription = mActivityDescriptions.get(i); View view = View.inflate(mContext, R.layout.status_bar_recent_item, null); @@ -306,40 +446,11 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC view.setOnClickListener(this); view.setTag(activityDescription); mRecentsContainer.addView(view); - - if (animate) { - view.setAlpha(initialAlpha); - ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", initialAlpha, 1.0f); - anim.setDuration(ALPHA_ANIMATION_DURATION); - anim.setStartDelay((last-i) * STAGGER_ANIMATION_DELAY); - anim.setInterpolator(interp); - anims.add(anim); - } } int views = mRecentsContainer.getChildCount(); mRecentsContainer.setVisibility(views > 0 ? View.VISIBLE : View.GONE); mRecentsGlowView.setVisibility(views > 0 ? View.VISIBLE : View.GONE); - - if (animate && views > 0) { - ObjectAnimator anim = ObjectAnimator.ofFloat(mRecentsGlowView, "alpha", - initialAlpha, 1.0f); - anim.setDuration((last-first) * STAGGER_ANIMATION_DELAY); - anim.setInterpolator(interp); - anims.add(anim); - - anim = ObjectAnimator.ofFloat(mBackgroundProtector, "alpha", - initialAlpha, 1.0f); - anim.setDuration(last * STAGGER_ANIMATION_DELAY); - anim.setInterpolator(interp); - anims.add(anim); - } - - if (anims.size() > 0) { - mAnimationSet = new AnimatorSet(); - mAnimationSet.playTogether(anims); - mAnimationSet.start(); - } } public void onClick(View v) { @@ -356,6 +467,7 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC if (DEBUG) Log.v(TAG, "Starting activity " + intent); getContext().startActivity(intent); } + setVisibility(View.GONE); mBar.animateCollapse(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index dc1dbe2..020b955 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -93,9 +93,6 @@ public class TabletStatusBar extends StatusBar implements // Fitts' Law assistance for LatinIME; TODO: replace with a more general approach private static final boolean FAKE_SPACE_BAR = true; - private static final int MAX_IMAGE_LEVEL = 10000; - private static final boolean USE_2D_RECENTS = true; - public static final int LIGHTS_ON_DELAY = 5000; // The height of the bar, as definied by the build. It may be taller if we're plugged @@ -212,16 +209,16 @@ public class TabletStatusBar extends StatusBar implements mNotificationPeekWindow.setOnTouchListener( new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PEEK, mNotificationPeekWindow)); mNotificationPeekScrubRight = new LayoutTransition(); - mNotificationPeekScrubRight.setAnimator(LayoutTransition.APPEARING, + mNotificationPeekScrubRight.setAnimator(LayoutTransition.APPEARING, ObjectAnimator.ofInt(null, "left", -512, 0)); - mNotificationPeekScrubRight.setAnimator(LayoutTransition.DISAPPEARING, + mNotificationPeekScrubRight.setAnimator(LayoutTransition.DISAPPEARING, ObjectAnimator.ofInt(null, "left", -512, 0)); mNotificationPeekScrubRight.setDuration(500); mNotificationPeekScrubLeft = new LayoutTransition(); - mNotificationPeekScrubLeft.setAnimator(LayoutTransition.APPEARING, + mNotificationPeekScrubLeft.setAnimator(LayoutTransition.APPEARING, ObjectAnimator.ofInt(null, "left", 512, 0)); - mNotificationPeekScrubLeft.setAnimator(LayoutTransition.DISAPPEARING, + mNotificationPeekScrubLeft.setAnimator(LayoutTransition.DISAPPEARING, ObjectAnimator.ofInt(null, "left", 512, 0)); mNotificationPeekScrubLeft.setDuration(500); @@ -241,30 +238,28 @@ public class TabletStatusBar extends StatusBar implements WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp); // Recents Panel - if (USE_2D_RECENTS) { - mRecentsPanel = (RecentAppsPanel) View.inflate(context, - R.layout.status_bar_recent_panel, null); - mRecentsPanel.setVisibility(View.GONE); - mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL, - mRecentsPanel)); - mStatusBarView.setIgnoreChildren(2, mRecentButton, mRecentsPanel); - - lp = new WindowManager.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT, - WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH - | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, - PixelFormat.TRANSLUCENT); - lp.gravity = Gravity.BOTTOM | Gravity.LEFT; - lp.setTitle("RecentsPanel"); - lp.windowAnimations = R.style.Animation_RecentPanel; - - WindowManagerImpl.getDefault().addView(mRecentsPanel, lp); - mRecentsPanel.setBar(this); - } + mRecentsPanel = (RecentAppsPanel) View.inflate(context, + R.layout.status_bar_recent_panel, null); + mRecentsPanel.setVisibility(View.GONE); + mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL, + mRecentsPanel)); + mStatusBarView.setIgnoreChildren(2, mRecentButton, mRecentsPanel); + + lp = new WindowManager.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH + | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, + PixelFormat.TRANSLUCENT); + lp.gravity = Gravity.BOTTOM | Gravity.LEFT; + lp.setTitle("RecentsPanel"); + lp.windowAnimations = R.style.Animation_RecentPanel; + + WindowManagerImpl.getDefault().addView(mRecentsPanel, lp); + mRecentsPanel.setBar(this); } @Override @@ -298,7 +293,7 @@ public class TabletStatusBar extends StatusBar implements protected View makeStatusBarView() { final Context context = mContext; - + mWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService(Context.WINDOW_SERVICE)); @@ -462,15 +457,15 @@ public class TabletStatusBar extends StatusBar implements //Slog.d(TAG, "loading peek: " + peekIndex); NotificationData.Entry entry = mNotns.get(N-1-peekIndex); NotificationData.Entry copy = new NotificationData.Entry( - entry.key, - entry.notification, + entry.key, + entry.notification, entry.icon); inflateViews(copy, mNotificationPeekRow); entry.icon.setBackgroundColor(0x20FFFFFF); // mNotificationPeekRow.setLayoutTransition( -// peekIndex < mNotificationPeekIndex +// peekIndex < mNotificationPeekIndex // ? mNotificationPeekScrubLeft // : mNotificationPeekScrubRight); @@ -516,11 +511,16 @@ public class TabletStatusBar extends StatusBar implements break; case MSG_OPEN_RECENTS_PANEL: if (DEBUG) Slog.d(TAG, "opening recents panel"); - if (mRecentsPanel != null) mRecentsPanel.setVisibility(View.VISIBLE); + if (mRecentsPanel != null) { + mRecentsPanel.setVisibility(View.VISIBLE); + mRecentsPanel.show(true, true); + } break; case MSG_CLOSE_RECENTS_PANEL: if (DEBUG) Slog.d(TAG, "closing recents panel"); - if (mRecentsPanel != null) mRecentsPanel.setVisibility(View.GONE); + if (mRecentsPanel != null && mRecentsPanel.isShowing()) { + mRecentsPanel.show(false, true); + } break; case MSG_SHOW_CHROME: if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)"); @@ -631,7 +631,7 @@ public class TabletStatusBar extends StatusBar implements handleNotificationError(key, notification, "Couldn't update icon: " + ic); return; } - + if (key == mNotificationPeekKey) { // must update the peek window Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK); @@ -820,7 +820,7 @@ public class TabletStatusBar extends StatusBar implements return false; } } - + private void setAreThereNotifications() { final boolean hasClearable = mNotns.hasClearableItems(); } @@ -1265,11 +1265,11 @@ public class TabletStatusBar extends StatusBar implements mElementTransition.setDuration(LayoutTransition.DISAPPEARING, 400); mShadowTransition = new LayoutTransition(); - mShadowTransition.setAnimator(LayoutTransition.APPEARING, + mShadowTransition.setAnimator(LayoutTransition.APPEARING, ObjectAnimator.ofFloat(null, "alpha", 0f, 1f)); mShadowTransition.setDuration(LayoutTransition.APPEARING, 200); mShadowTransition.setStartDelay(LayoutTransition.APPEARING, 100); - mShadowTransition.setAnimator(LayoutTransition.DISAPPEARING, + mShadowTransition.setAnimator(LayoutTransition.DISAPPEARING, ObjectAnimator.ofFloat(null, "alpha", 1f, 0f)); mShadowTransition.setDuration(LayoutTransition.DISAPPEARING, 100); @@ -1310,7 +1310,7 @@ public class TabletStatusBar extends StatusBar implements case MotionEvent.ACTION_UP: mHandler.removeMessages(MSG_RESTORE_SHADOWS); if (mShowShadows) { - mHandler.sendEmptyMessageDelayed(MSG_RESTORE_SHADOWS, + mHandler.sendEmptyMessageDelayed(MSG_RESTORE_SHADOWS, v == mNotificationShadow ? 5000 : 500); } last = true; |