diff options
author | Michael Jurka <mikejurka@google.com> | 2011-10-17 09:05:00 -0700 |
---|---|---|
committer | Michael Jurka <mikejurka@google.com> | 2011-10-18 15:48:18 -0700 |
commit | 412cba8aa10231cdf515d9400a754e8a16a8eb3d (patch) | |
tree | a750a0c8cb1bb710fb594ed8ed1e5d9a42bf03f2 /packages | |
parent | 87bc53de2adf479ad5a5e226bf3d8fd31af6dc21 (diff) | |
download | frameworks_base-412cba8aa10231cdf515d9400a754e8a16a8eb3d.zip frameworks_base-412cba8aa10231cdf515d9400a754e8a16a8eb3d.tar.gz frameworks_base-412cba8aa10231cdf515d9400a754e8a16a8eb3d.tar.bz2 |
Make Recent Apps faster
- start loading on touch down
- avoid unneeded calls to onLayout
- don't fade in thumbnails if they've been loaded before we show recent apps
- don't pause between loading thumbnails
- fade in thumbnails+shadow (rather than just thumbnail as before)
Change-Id: I6dd4be7f52f9e8b51284ae052614719db8e71dc5
Diffstat (limited to 'packages')
8 files changed, 116 insertions, 70 deletions
diff --git a/packages/SystemUI/res/anim/recent_appear.xml b/packages/SystemUI/res/anim/recent_appear.xml index 20fe052..4400d9d 100644 --- a/packages/SystemUI/res/anim/recent_appear.xml +++ b/packages/SystemUI/res/anim/recent_appear.xml @@ -16,5 +16,5 @@ <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:fromAlpha="0.0" android:toAlpha="1.0" - android:duration="@android:integer/config_mediumAnimTime" + android:duration="@android:integer/config_shortAnimTime" /> diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml index 83c4faf..2d76455 100644 --- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml @@ -39,11 +39,11 @@ android:layout_marginTop="@dimen/status_bar_recents_thumbnail_top_margin" android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin" android:background="@drawable/recents_thumbnail_bg" - android:foreground="@drawable/recents_thumbnail_fg"> + android:foreground="@drawable/recents_thumbnail_fg" + android:visibility="invisible"> <ImageView android:id="@+id/app_thumbnail_image" android:layout_width="@dimen/status_bar_recents_thumbnail_width" android:layout_height="@dimen/status_bar_recents_thumbnail_height" - android:visibility="invisible" /> </FrameLayout> @@ -58,7 +58,6 @@ android:maxHeight="@dimen/status_bar_recents_app_icon_max_height" android:scaleType="centerInside" android:adjustViewBounds="true" - android:visibility="invisible" /> <TextView android:id="@+id/app_label" @@ -74,7 +73,6 @@ android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin" android:singleLine="true" android:ellipsize="marquee" - android:visibility="invisible" android:textColor="@color/status_bar_recents_app_label_color" /> diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml index 3d8b9d6..b653fcd 100644 --- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml @@ -52,11 +52,11 @@ android:layout_toRightOf="@id/app_label" android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin" android:background="@drawable/recents_thumbnail_bg" - android:foreground="@drawable/recents_thumbnail_fg"> + android:foreground="@drawable/recents_thumbnail_fg" + android:visibility="invisible"> <ImageView android:id="@+id/app_thumbnail_image" android:layout_width="@dimen/status_bar_recents_thumbnail_width" android:layout_height="@dimen/status_bar_recents_thumbnail_height" - android:visibility="invisible" /> </FrameLayout> <View android:id="@+id/recents_callout_line" diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml index e633671..18a31f7 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml @@ -31,11 +31,11 @@ android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin" android:scaleType="center" android:background="@drawable/recents_thumbnail_bg" - android:foreground="@drawable/recents_thumbnail_fg"> + android:foreground="@drawable/recents_thumbnail_fg" + android:visibility="invisible"> <ImageView android:id="@+id/app_thumbnail_image" android:layout_width="@dimen/status_bar_recents_thumbnail_width" android:layout_height="@dimen/status_bar_recents_thumbnail_height" - android:visibility="invisible" /> <ImageView android:id="@+id/app_icon" android:layout_width="wrap_content" diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java index 47aa849..dcda9c2 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java @@ -86,8 +86,8 @@ public class RecentTasksLoader { mIconDpi = isTablet ? DisplayMetrics.DENSITY_HIGH : res.getDisplayMetrics().densityDpi; // Render the default thumbnail background - int width = (int) res.getDimension(R.dimen.status_bar_recents_thumbnail_width); - int height = (int) res.getDimension(R.dimen.status_bar_recents_thumbnail_height); + int width = (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width); + int height = (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height); int color = res.getColor(R.drawable.status_bar_recents_app_thumbnail_background); mDefaultThumbnailBackground = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); @@ -106,6 +106,10 @@ public class RecentTasksLoader { mRecentsPanel = recentsPanel; } + public Bitmap getDefaultThumbnail() { + return mDefaultThumbnailBackground; + } + // Create an TaskDescription, returning null if the title or icon is null, or if it's the // home activity TaskDescription createTaskDescription(int taskId, int persistentTaskId, Intent baseIntent, @@ -278,7 +282,7 @@ public class RecentTasksLoader { TaskDescription td = descriptions.get(i); loadThumbnail(td); long now = SystemClock.uptimeMillis(); - nextTime += 150; + nextTime += 0; if (nextTime > now) { try { Thread.sleep(nextTime-now); diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index bd1fcfc..343b33514 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -37,6 +37,7 @@ import android.view.LayoutInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.animation.AnimationUtils; @@ -57,8 +58,8 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.tablet.StatusBarPanel; import com.android.systemui.statusbar.tablet.TabletStatusBar; -public class RecentsPanelView extends RelativeLayout - implements OnItemClickListener, RecentsCallback, StatusBarPanel, Animator.AnimatorListener { +public class RecentsPanelView extends RelativeLayout implements OnItemClickListener, RecentsCallback, + StatusBarPanel, Animator.AnimatorListener, View.OnTouchListener { static final String TAG = "RecentsPanelView"; static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false; private Context mContext; @@ -74,6 +75,7 @@ public class RecentsPanelView extends RelativeLayout private RecentTasksLoader mRecentTasksLoader; private ArrayList<TaskDescription> mRecentTaskDescriptions; + private boolean mRecentTasksDirty = true; private TaskDescriptionAdapter mListAdapter; private int mThumbnailWidth; @@ -94,6 +96,7 @@ public class RecentsPanelView extends RelativeLayout /* package */ final static class ViewHolder { View thumbnailView; ImageView thumbnailViewImage; + Bitmap thumbnailViewImageBitmap; ImageView iconView; TextView labelView; TextView descriptionView; @@ -127,6 +130,10 @@ public class RecentsPanelView extends RelativeLayout holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail); holder.thumbnailViewImage = (ImageView) convertView.findViewById( R.id.app_thumbnail_image); + // If we set the default thumbnail now, we avoid an onLayout when we update + // the thumbnail later (if they both have the same dimensions) + updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false); + holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon); holder.labelView = (TextView) convertView.findViewById(R.id.app_label); holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description); @@ -139,12 +146,15 @@ public class RecentsPanelView extends RelativeLayout // index is reverse since most recent appears at the bottom... final int index = mRecentTaskDescriptions.size() - position - 1; - final TaskDescription taskDescription = mRecentTaskDescriptions.get(index); - applyTaskDescription(holder, taskDescription, false); + final TaskDescription td = mRecentTaskDescriptions.get(index); + holder.iconView.setImageDrawable(td.getIcon()); + holder.labelView.setText(td.getLabel()); + holder.thumbnailView.setContentDescription(td.getLabel()); + updateThumbnail(holder, td.getThumbnail(), true, false); - holder.thumbnailView.setTag(taskDescription); + holder.thumbnailView.setTag(td); holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView)); - holder.taskDescription = taskDescription; + holder.taskDescription = td; return convertView; } @@ -193,6 +203,7 @@ public class RecentsPanelView extends RelativeLayout } } else { mRecentTasksLoader.cancelLoadingThumbnails(); + mRecentTasksDirty = true; } if (animate) { if (mShowing != show) { @@ -250,9 +261,7 @@ public class RecentsPanelView extends RelativeLayout createCustomAnimations(transitioner); } else { ((ViewGroup)mRecentsContainer).setLayoutTransition(null); - // Clear memory used by screenshots - mRecentTaskDescriptions.clear(); - mListAdapter.notifyDataSetInvalidated(); + clearRecentTasksList(); } } @@ -374,47 +383,33 @@ public class RecentsPanelView extends RelativeLayout } } - - void applyTaskDescription(ViewHolder h, TaskDescription td, boolean anim) { - h.iconView.setImageDrawable(td.getIcon()); - if (h.iconView.getVisibility() != View.VISIBLE) { - if (anim) { - h.iconView.setAnimation(AnimationUtils.loadAnimation( - mContext, R.anim.recent_appear)); - } - h.iconView.setVisibility(View.VISIBLE); - } - h.labelView.setText(td.getLabel()); - h.thumbnailView.setContentDescription(td.getLabel()); - if (h.labelView.getVisibility() != View.VISIBLE) { - if (anim) { - h.labelView.setAnimation(AnimationUtils.loadAnimation( - mContext, R.anim.recent_appear)); - } - h.labelView.setVisibility(View.VISIBLE); - } - Bitmap thumbnail = td.getThumbnail(); + private void updateThumbnail(ViewHolder h, Bitmap thumbnail, boolean show, boolean anim) { if (thumbnail != null) { // Should remove the default image in the frame // that this now covers, to improve scrolling speed. // That can't be done until the anim is complete though. h.thumbnailViewImage.setImageBitmap(thumbnail); - // scale to fill up the full width - Matrix scaleMatrix = new Matrix(); - float scale = mThumbnailWidth / (float) thumbnail.getWidth(); - scaleMatrix.setScale(scale, scale); - h.thumbnailViewImage.setScaleType(ScaleType.MATRIX); - h.thumbnailViewImage.setImageMatrix(scaleMatrix); - if (h.thumbnailViewImage.getVisibility() != View.VISIBLE) { + + // scale the image to fill the full width of the ImageView. do this only if + // we haven't set a bitmap before, or if the bitmap size has changed + if (h.thumbnailViewImageBitmap == null || + h.thumbnailViewImageBitmap.getWidth() != thumbnail.getWidth() || + h.thumbnailViewImageBitmap.getHeight() != thumbnail.getHeight()) { + Matrix scaleMatrix = new Matrix(); + float scale = mThumbnailWidth / (float) thumbnail.getWidth(); + scaleMatrix.setScale(scale, scale); + h.thumbnailViewImage.setScaleType(ScaleType.MATRIX); + h.thumbnailViewImage.setImageMatrix(scaleMatrix); + } + if (show && h.thumbnailView.getVisibility() != View.VISIBLE) { if (anim) { - h.thumbnailViewImage.setAnimation( - AnimationUtils.loadAnimation( - mContext, R.anim.recent_appear)); + h.thumbnailView.setAnimation( + AnimationUtils.loadAnimation(mContext, R.anim.recent_appear)); } - h.thumbnailViewImage.setVisibility(View.VISIBLE); + h.thumbnailView.setVisibility(View.VISIBLE); } + h.thumbnailViewImageBitmap = thumbnail; } - //h.descriptionView.setText(ad.description); } void onTaskThumbnailLoaded(TaskDescription ad) { @@ -432,7 +427,11 @@ public class RecentsPanelView extends RelativeLayout if (v.getTag() instanceof ViewHolder) { ViewHolder h = (ViewHolder)v.getTag(); if (h.taskDescription == ad) { - applyTaskDescription(h, ad, true); + // only fade in the thumbnail if recents is already visible-- we + // show it immediately otherwise + boolean animateShow = mShowing && + mRecentsGlowView.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD; + updateThumbnail(h, ad.getThumbnail(), true, animateShow); } } } @@ -440,14 +439,55 @@ public class RecentsPanelView extends RelativeLayout } } + // additional optimization when we have sofware system buttons - start loading the recent + // tasks on touch down + @Override + public boolean onTouch(View v, MotionEvent ev) { + if (!mShowing) { + int action = ev.getAction() & MotionEvent.ACTION_MASK; + if (action == MotionEvent.ACTION_DOWN) { + // If we set our visibility to INVISIBLE here, we avoid an extra call to onLayout + // later when we become visible + setVisibility(INVISIBLE); + refreshRecentTasksList(); + } else if (action == MotionEvent.ACTION_CANCEL) { + setVisibility(GONE); + clearRecentTasksList(); + } else if (action == MotionEvent.ACTION_UP) { + if (!v.isPressed()) { + setVisibility(GONE); + clearRecentTasksList(); + } + } + } + return false; + } + + public void clearRecentTasksList() { + // Clear memory used by screenshots + if (mRecentTaskDescriptions != null) { + mRecentTasksLoader.cancelLoadingThumbnails(); + mRecentTaskDescriptions.clear(); + mListAdapter.notifyDataSetInvalidated(); + mRecentTasksDirty = true; + } + } + + public void refreshRecentTasksList() { + refreshRecentTasksList(null); + } + private void refreshRecentTasksList(ArrayList<TaskDescription> recentTasksList) { - if (recentTasksList != null) { - mRecentTaskDescriptions = recentTasksList; - } else { - mRecentTaskDescriptions = mRecentTasksLoader.getRecentTasks(); + if (mRecentTasksDirty) { + if (recentTasksList != null) { + mRecentTaskDescriptions = recentTasksList; + } else { + mRecentTaskDescriptions = mRecentTasksLoader.getRecentTasks(); + } + mListAdapter.notifyDataSetInvalidated(); + updateUiElements(getResources().getConfiguration()); + mRecentTasksDirty = false; } - mListAdapter.notifyDataSetInvalidated(); - updateUiElements(getResources().getConfiguration()); } public ArrayList<TaskDescription> getRecentTasksList() { 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 b724552..77a7f51 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -435,13 +435,18 @@ public class PhoneStatusBar extends StatusBar { } }; + private void prepareNavigationBarView() { + mNavigationBarView.reorient(); + + mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener); + mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel); + } + // For small-screen devices (read: phones) that lack hardware navigation buttons private void addNavigationBar() { if (mNavigationBarView == null) return; - mNavigationBarView.reorient(); - - mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener); + prepareNavigationBarView(); WindowManagerImpl.getDefault().addView( mNavigationBarView, getNavigationBarLayoutParams()); @@ -450,9 +455,7 @@ public class PhoneStatusBar extends StatusBar { private void repositionNavigationBar() { if (mNavigationBarView == null) return; - mNavigationBarView.reorient(); - - mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener); + prepareNavigationBarView(); WindowManagerImpl.getDefault().updateViewLayout( mNavigationBarView, getNavigationBarLayoutParams()); @@ -2007,8 +2010,8 @@ public class PhoneStatusBar extends StatusBar { } public void toggleRecentApps() { - int msg = (mRecentsPanel.getVisibility() == View.GONE) - ? MSG_OPEN_RECENTS_PANEL : MSG_CLOSE_RECENTS_PANEL; + int msg = (mRecentsPanel.getVisibility() == View.VISIBLE) + ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL; mHandler.removeMessages(msg); mHandler.sendEmptyMessage(msg); } 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 f0a10f3..de8226b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -587,6 +587,7 @@ public class TabletStatusBar extends StatusBar implements // Add the windows addPanelWindows(); + mRecentButton.setOnTouchListener(mRecentsPanel); mPile = (ViewGroup)mNotificationPanel.findViewById(R.id.content); mPile.removeAllViews(); @@ -1805,8 +1806,8 @@ public class TabletStatusBar extends StatusBar implements } public void toggleRecentApps() { - int msg = (mRecentsPanel.getVisibility() == View.GONE) - ? MSG_OPEN_RECENTS_PANEL : MSG_CLOSE_RECENTS_PANEL; + int msg = (mRecentsPanel.getVisibility() == View.VISIBLE) + ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL; mHandler.removeMessages(msg); mHandler.sendEmptyMessage(msg); } |