diff options
| author | Jim Miller <jaggies@google.com> | 2010-12-03 19:18:38 -0800 |
|---|---|---|
| committer | Jim Miller <jaggies@google.com> | 2010-12-08 16:42:12 -0800 |
| commit | e5c16ab5a8b4e12aff03a88d3c3c6eac03b609c3 (patch) | |
| tree | a95ae7e19dc307cf5d64224c3ff684b69ddcaa92 /packages | |
| parent | b119b6cfcfc4cad6e5c0a80f09607ba6967a911d (diff) | |
| download | frameworks_base-e5c16ab5a8b4e12aff03a88d3c3c6eac03b609c3.zip frameworks_base-e5c16ab5a8b4e12aff03a88d3c3c6eac03b609c3.tar.gz frameworks_base-e5c16ab5a8b4e12aff03a88d3c3c6eac03b609c3.tar.bz2 | |
Fix 3253629: Initial pass at updating RecentsPanel UI
Change-Id: I578d0efd9f4b67675ff531494259f54182851e0e
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png | bin | 0 -> 21287 bytes | |||
| -rw-r--r-- | packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png | bin | 0 -> 9784 bytes | |||
| -rw-r--r-- | packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png | bin | 0 -> 114 bytes | |||
| -rw-r--r-- | packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png | bin | 0 -> 1564 bytes | |||
| -rw-r--r-- | packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml | 78 | ||||
| -rw-r--r-- | packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml | 31 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java | 199 |
7 files changed, 229 insertions, 79 deletions
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png Binary files differnew file mode 100644 index 0000000..66a54f0 --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png Binary files differnew file mode 100644 index 0000000..4f4ae78 --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png Binary files differnew file mode 100644 index 0000000..5f4c035 --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png Binary files differnew file mode 100644 index 0000000..9f72549 --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml index e7a3a61..2989be0 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml @@ -19,41 +19,63 @@ --> <!-- android:background="@drawable/status_bar_closed_default_background" --> -<LinearLayout +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:orientation="horizontal" - android:layout_margin="10dip"> + android:layout_width="156dip"> <ImageView android:id="@+id/app_thumbnail" - android:layout_width="88dip" - android:layout_height="56dip" - android:layout_margin="10dip" - android:background="#80808080"> - </ImageView> - - <LinearLayout + android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:layout_marginLeft="105dip" + android:scaleType="center" + android:background="@drawable/recents_thumbnail_bg" + /> + + <ImageView android:id="@+id/app_icon" android:layout_width="wrap_content" - android:orientation="horizontal" - android:layout_marginTop="10dip" - android:layout_marginBottom="10dip" - android:layout_marginRight="10dip"> + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:layout_marginLeft="123dip" + android:layout_marginTop="16dip" + /> - <ImageView android:id="@+id/app_icon" - android:layout_width="23dip" - android:layout_height="23dip" - android:gravity="bottom" - android:layout_margin="5dip" - /> + <View android:id="@+id/recents_callout_line" + android:layout_width="97dip" + android:layout_height="1dip" + android:layout_alignParentTop="true" + android:layout_marginTop="61dip" + android:layout_alignParentLeft="true" + android:layout_marginLeft="16dip" + android:layout_toLeftOf="@id/app_thumbnail" + android:layout_marginRight="3dip" + android:background="@drawable/recents_callout_line" + /> - <TextView android:id="@+id/app_label" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textSize="22dip" - /> + <TextView android:id="@+id/app_label" + android:layout_width="113dip" + android:layout_height="wrap_content" + android:textSize="18dip" + android:fadingEdge="none" + android:fadingEdgeLength="0dp" + android:scrollHorizontally="true" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:layout_marginLeft="16dip" + android:layout_marginTop="32dip" + /> - </LinearLayout> + <TextView android:id="@+id/app_description" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="18dip" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:layout_marginLeft="16dip" + android:layout_marginTop="61dip" + /> -</LinearLayout> +</RelativeLayout> diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml index ac038a7..c7e6dbd 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml @@ -20,34 +20,37 @@ <com.android.systemui.statusbar.tablet.RecentAppsPanel xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="wrap_content" + android:layout_height="match_parent" android:layout_width="wrap_content" - android:background="@drawable/sysbar_panel_recents_bg" + android:layout_marginBottom="48dip" + android:background="@drawable/recents_bg_protect_tile" + android:id="@+id/recents_bg_protect" android:orientation="vertical"> - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/recent_tasks_app_label" - android:textSize="22dip" - android:drawableLeft="@drawable/app_icon" - android:layout_margin="10dip" - /> - <TextView android:id="@+id/recents_no_recents" android:layout_width="match_parent" android:layout_height="match_parent" android:text="@string/recent_tasks_empty" android:textSize="22dip" android:gravity="center_horizontal|center_vertical" - android:visibility="gone" - android:layout_margin="10dip"> + android:visibility="gone"> </TextView> + <View + android:layout_width="match_parent" + android:layout_height="0dip" + android:layout_weight="1" + /> + <LinearLayout android:id="@+id/recents_container" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" + android:layout_alignParentBottom="true" + android:layout_marginBottom="16dip" + android:layout_alignParentLeft="true" + android:layout_marginRight="100dip" + android:background="@drawable/recents_blue_glow" /> </com.android.systemui.statusbar.tablet.RecentAppsPanel> 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 546750b..25a2f2b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java @@ -19,9 +19,14 @@ package com.android.systemui.statusbar.tablet; import java.util.ArrayList; import java.util.List; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.LayoutTransition; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; import android.app.ActivityManager; import android.app.ActivityManagerNative; -import android.app.IActivityManager; import android.app.IThumbnailReceiver; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; @@ -29,30 +34,44 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.res.Configuration; +import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.Canvas; import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.Shader.TileMode; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.RemoteException; import android.util.AttributeSet; +import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; +import android.view.animation.AnimationSet; +import android.view.animation.DecelerateInterpolator; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import android.widget.ImageView.ScaleType; import com.android.systemui.R; public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnClickListener { private static final String TAG = "RecentAppsPanel"; private static final boolean DEBUG = TabletStatusBar.DEBUG; - private static final int DISPLAY_TASKS = 4; // number of recent tasks to display - private static final int MAX_TASKS = 2 * DISPLAY_TASKS; // give some slack for non-apps - private static final boolean DBG = true; + private static final int DISPLAY_TASKS_PORTRAIT = 8; + private static final int DISPLAY_TASKS_LANDSCAPE = 5; // number of recent tasks to display + private static final int MAX_TASKS = 2 * DISPLAY_TASKS_PORTRAIT; // allow extra for non-apps private TabletStatusBar mBar; private TextView mNoRecents; private LinearLayout mRecentsContainer; private ArrayList<ActivityDescription> mActivityDescriptions; + private int mIconDpi; + private AnimatorSet mAnimationSet; + private View mBackgroundProtector; static class ActivityDescription { int id; @@ -62,10 +81,12 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC CharSequence description; // generated by Activity.onCreateDescription() Intent intent; // launch intent for application Matrix matrix; // arbitrary rotation matrix to correct orientation + String packageName; // used to override animations (see onClick()) int position; // position in list public ActivityDescription(Bitmap _thumbnail, - Drawable _icon, String _label, String _desc, Intent _intent, int _id, int _pos) + Drawable _icon, String _label, String _desc, Intent _intent, int _id, int _pos, + String _packageName) { thumbnail = _thumbnail; icon = _icon; @@ -74,6 +95,7 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC intent = _intent; id = _id; position = _pos; + packageName = _packageName; } }; @@ -93,10 +115,10 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC }; public boolean isInContentArea(int x, int y) { - final int l = getPaddingLeft(); - final int r = getWidth() - getPaddingRight(); - final int t = getPaddingTop(); - final int b = getHeight() - getPaddingBottom(); + final int l = mRecentsContainer.getPaddingLeft(); + final int r = mRecentsContainer.getWidth() - mRecentsContainer.getPaddingRight(); + final int t = mRecentsContainer.getPaddingTop(); + final int b = mRecentsContainer.getHeight() - mRecentsContainer.getPaddingBottom(); return x >= l && x < r && y >= t && y < b; } @@ -110,6 +132,12 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC public RecentAppsPanel(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + + Resources res = context.getResources(); + boolean xlarge = (res.getConfiguration().screenLayout + & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE; + + mIconDpi = xlarge ? DisplayMetrics.DENSITY_HIGH : res.getDisplayMetrics().densityDpi; } @Override @@ -117,12 +145,26 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC super.onFinishInflate(); mNoRecents = (TextView) findViewById(R.id.recents_no_recents); mRecentsContainer = (LinearLayout) findViewById(R.id.recents_container); + mBackgroundProtector = (View) findViewById(R.id.recents_bg_protect); + + // 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); + } + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + // we show more in portrait mode, so update UI if orientation changes + updateUiElements(newConfig, false); } @Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); - Log.v(TAG, "onVisibilityChanged(" + changedView + ", " + visibility + ")"); + if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + changedView + ", " + visibility + ")"); if (visibility == View.VISIBLE && changedView == this) { refreshApplicationList(); mRecentsContainer.setScrollbarFadingEnabled(true); @@ -130,6 +172,32 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC } } + private Drawable getFullResDefaultActivityIcon() { + return getFullResIcon(Resources.getSystem(), + com.android.internal.R.drawable.sym_def_app_icon); + } + + private Drawable getFullResIcon(Resources resources, int iconId) { + return resources.getDrawableForDensity(iconId, mIconDpi); + } + + private Drawable getFullResIcon(ResolveInfo info, PackageManager packageManager) { + Resources resources; + try { + resources = packageManager.getResourcesForApplication( + info.activityInfo.applicationInfo); + } catch (PackageManager.NameNotFoundException e) { + resources = null; + } + if (resources != null) { + int iconId = info.activityInfo.getIconResource(); + if (iconId != 0) { + return getFullResIcon(resources, iconId); + } + } + return getFullResDefaultActivityIcon(); + } + private ArrayList<ActivityDescription> getRecentTasks() { ArrayList<ActivityDescription> activityDescriptions = new ArrayList<ActivityDescription>(); final PackageManager pm = mContext.getPackageManager(); @@ -164,16 +232,17 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC if (resolveInfo != null) { final ActivityInfo info = resolveInfo.activityInfo; final String title = info.loadLabel(pm).toString(); - Drawable icon = info.loadIcon(pm); + // Drawable icon = info.loadIcon(pm); + Drawable icon = getFullResIcon(resolveInfo, pm); int id = recentTasks.get(i).id; if (title != null && title.length() > 0 && icon != null) { - Log.v(TAG, "creating activity desc for id=" + id + ", label=" + title); + if (DEBUG) Log.v(TAG, "creating activity desc for id=" + id + ", label=" + title); ActivityDescription item = new ActivityDescription( - null, icon, title, null, intent, id, index); + null, icon, title, null, intent, id, index, info.packageName); activityDescriptions.add(item); ++index; } else { - if (DBG) Log.v(TAG, "SKIPPING item " + id); + if (DEBUG) Log.v(TAG, "SKIPPING item " + id); } } } @@ -196,18 +265,18 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC private void getThumbnails(ArrayList<ActivityDescription> tasks) { ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); List<RunningTaskInfo> runningTasks = am.getRunningTasks(MAX_TASKS, 0, mThumbnailReceiver); - for (RunningTaskInfo r : runningTasks) { + for (RunningTaskInfo runningTaskInfo : runningTasks) { // Find the activity description associted with the given id - ActivityDescription desc = findActivityDescription(r.id); + ActivityDescription desc = findActivityDescription(runningTaskInfo.id); if (desc != null) { - if (r.thumbnail != null) { - desc.thumbnail = r.thumbnail; - desc.description = r.description; + if (runningTaskInfo.thumbnail != null) { + desc.thumbnail = crop(runningTaskInfo.thumbnail); + desc.description = runningTaskInfo.description; } else { - if (DBG) Log.v(TAG, "*** RUNNING THUMBNAIL WAS NULL ***"); + if (DEBUG) Log.v(TAG, "*** RUNNING THUMBNAIL WAS NULL ***"); } } else { - if (DBG) Log.v(TAG, "Couldn't find ActivityDesc for id=" + r.id); + if (DEBUG) Log.v(TAG, "Couldn't find ActivityDesc for id=" + runningTaskInfo.id); } } } @@ -215,45 +284,101 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC private void refreshApplicationList() { mActivityDescriptions = getRecentTasks(); getThumbnails(mActivityDescriptions); - updateUiElements(); + updateUiElements(getResources().getConfiguration(), true); + } + + private Bitmap crop(Bitmap bitmap) { + if (bitmap == null || bitmap.getWidth() >= bitmap.getHeight()) { + return bitmap; + } + final int width = bitmap.getWidth(); + final int height = bitmap.getHeight(); + Bitmap outBitmap = Bitmap.createBitmap(height, width, bitmap.getConfig()); + Canvas canvas = new Canvas(outBitmap); + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setFilterBitmap(true); + canvas.drawBitmap(bitmap, + new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight() - height * width / height), + new Rect(0, 0, outBitmap.getWidth(), outBitmap.getHeight()), + paint); + return outBitmap; } - private void updateUiElements() { + private void updateUiElements(Configuration config, boolean animate) { mRecentsContainer.removeAllViews(); + + + // TODO: disabled until I have a chance to tune animations with UX + animate = false; + + + final float initialAlpha = 0.0f; final int first = 0; - final int last = Math.min(mActivityDescriptions.size(), DISPLAY_TASKS) - 1; + 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); ImageView appThumbnail = (ImageView) view.findViewById(R.id.app_thumbnail); ImageView appIcon = (ImageView) view.findViewById(R.id.app_icon); - TextView appDescription = (TextView) view.findViewById(R.id.app_label); - if (activityDescription.thumbnail != null) { - Log.v(TAG, "thumbnail res = " + activityDescription.thumbnail.getWidth() - + "x" + activityDescription.thumbnail.getHeight()); - } else { - Log.v(TAG, "thumbnail for " + activityDescription.label + " was null"); - } - appThumbnail.setImageBitmap(activityDescription.thumbnail); + TextView appLabel = (TextView) view.findViewById(R.id.app_label); + TextView appDesc = (TextView) view.findViewById(R.id.app_description); + final Bitmap thumb = activityDescription.thumbnail; + appThumbnail.setImageBitmap(crop(thumb)); appIcon.setImageDrawable(activityDescription.icon); - appDescription.setText(activityDescription.label); + appLabel.setText(activityDescription.label); + appDesc.setText(activityDescription.description); view.setOnClickListener(this); view.setTag(activityDescription); - Log.v(TAG, "Adding task: " + activityDescription.label); mRecentsContainer.addView(view); + + if (animate) { + view.setAlpha(initialAlpha); + ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", initialAlpha, 1.0f); + anim.setDuration(25); + anim.setStartDelay((last-i)*25); + anim.setInterpolator(interp); + anims.add(anim); + } } int views = mRecentsContainer.getChildCount(); - mNoRecents.setVisibility(views == 0 ? View.VISIBLE : View.GONE); + mNoRecents.setVisibility(View.GONE); // views == 0 ? View.VISIBLE : View.GONE); mRecentsContainer.setVisibility(views > 0 ? View.VISIBLE : View.GONE); + + if (animate) { + ObjectAnimator anim = ObjectAnimator.ofFloat(mRecentsContainer, "alpha", + initialAlpha, 1.0f); + anim.setDuration(last*25); + anim.setInterpolator(interp); + anims.add(anim); + } + + if (animate) { + ObjectAnimator anim = ObjectAnimator.ofFloat(mBackgroundProtector, "alpha", + initialAlpha, 1.0f); + anim.setDuration(last*25); + anim.setInterpolator(interp); + anims.add(anim); + } + + if (anims.size() > 0) { + mAnimationSet = new AnimatorSet(); + mAnimationSet.playTogether(anims); + mAnimationSet.start(); + } } public void onClick(View v) { ActivityDescription ad = (ActivityDescription)v.getTag(); + final ActivityManager am = (ActivityManager) + getContext().getSystemService(Context.ACTIVITY_SERVICE); if (ad.id >= 0) { // This is an active task; it should just go to the foreground. - final ActivityManager am = (ActivityManager) - getContext().getSystemService(Context.ACTIVITY_SERVICE); am.moveTaskToFront(ad.id, ActivityManager.MOVE_TASK_WITH_HOME); } else { Intent intent = ad.intent; |
