diff options
16 files changed, 262 insertions, 136 deletions
diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_bg_selector.xml b/packages/SystemUI/res/drawable/recents_thumbnail_bg_selector.xml deleted file mode 100644 index 0e58e12..0000000 --- a/packages/SystemUI/res/drawable/recents_thumbnail_bg_selector.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2011 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android" - android:exitFadeDuration="@android:integer/config_mediumAnimTime"> - - <item android:state_window_focused="false" android:drawable="@android:color/transparent" /> - - <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. --> - <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/recents_thumbnail_bg_holo" /> - <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/recents_thumbnail_bg_holo" /> - <item android:state_focused="true" android:drawable="@drawable/recents_thumbnail_bg_holo" /> -</selector> - diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_layers.xml b/packages/SystemUI/res/drawable/recents_thumbnail_layers.xml new file mode 100644 index 0000000..6cae2c4 --- /dev/null +++ b/packages/SystemUI/res/drawable/recents_thumbnail_layers.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > + <item android:drawable="@drawable/recents_thumbnail_bg" android:id="@+id/base_layer"/> + <item android:drawable="@drawable/recents_thumbnail_overlay" android:id="@+id/overlay_layer"/> +</layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_overlay.xml b/packages/SystemUI/res/drawable/recents_thumbnail_overlay.xml new file mode 100644 index 0000000..200bac4 --- /dev/null +++ b/packages/SystemUI/res/drawable/recents_thumbnail_overlay.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/recents_thumbnail_bg_press" android:state_pressed="true" /> + <item android:drawable="@*android:color/transparent"/> +</selector> 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 be4f1d7..8c29042 100644 --- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml @@ -24,14 +24,15 @@ android:layout_height="wrap_content" android:layout_width="@dimen/status_bar_recents_thumbnail_view_width"> - <ImageView android:id="@+id/app_thumbnail" + <FrameLayout android:id="@+id/app_thumbnail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin" android:scaleType="center" - android:background="@drawable/recents_thumbnail_bg_selector" + android:clickable="true" + android:background="@drawable/recents_thumbnail_layers" /> <ImageView android:id="@+id/app_icon" diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml index efdd9ac..20ef7cf 100644 --- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml @@ -51,7 +51,6 @@ android:fadingEdge="horizontal" android:scrollbars="none" android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" - android:listSelector="@drawable/recents_thumbnail_bg_selector" android:layout_gravity="bottom|left" android:orientation="horizontal" android:clipToPadding="false" 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 76965c9..c705a69 100644 --- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml @@ -24,13 +24,15 @@ android:layout_height="wrap_content" android:layout_width="@dimen/status_bar_recents_thumbnail_view_width"> - <ImageView android:id="@+id/app_thumbnail" + <FrameLayout android:id="@+id/app_thumbnail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" + android:clickable="true" android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin" android:scaleType="center" + android:background="@drawable/recents_thumbnail_layers" /> <ImageView android:id="@+id/app_icon" diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml index 28ef239..c680b8e 100644 --- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml @@ -48,7 +48,6 @@ android:fadingEdge="vertical" android:scrollbars="none" android:fadingEdgeLength="@*android:dimen/status_bar_height" - android:listSelector="@drawable/recents_thumbnail_bg_selector" android:layout_gravity="bottom|left" android:clipToPadding="false" android:clipChildren="false"> 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 9687866..386ce30 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml @@ -24,13 +24,15 @@ android:layout_height="wrap_content" android:layout_width="@dimen/status_bar_recents_thumbnail_view_width"> - <ImageView android:id="@+id/app_thumbnail" + <FrameLayout android:id="@+id/app_thumbnail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin" android:scaleType="center" + android:clickable="true" + android:background="@drawable/recents_thumbnail_layers" /> <ImageView android:id="@+id/app_icon" diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml index 75fdc67..2c9a152 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml @@ -56,7 +56,6 @@ android:scrollbars="none" android:fadingEdgeLength="20dip" android:layout_gravity="bottom|left" - android:listSelector="@drawable/recents_thumbnail_bg_selector" android:clipToPadding="false" android:clipChildren="false"> diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_bg_holo.xml b/packages/SystemUI/res/menu/recent_popup_menu.xml index f9bba2a..eecfb9a 100644 --- a/packages/SystemUI/res/drawable/recents_thumbnail_bg_holo.xml +++ b/packages/SystemUI/res/menu/recent_popup_menu.xml @@ -17,7 +17,7 @@ ** limitations under the License. */ --> -<transition xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:drawable="@drawable/recents_thumbnail_bg_press"/> - <item android:drawable="@drawable/recents_thumbnail_bg_press"/> -</transition> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/recent_remove_item" android:title="@string/status_bar_recent_remove_item_title" /> + <item android:id="@+id/recent_inspect_item" android:title="@string/status_bar_recent_inspect_item_title" /> +</menu> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 882455e..01cf2dc 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -35,6 +35,14 @@ shown again. [CHAR LIMIT=25] --> <string name="status_bar_please_disturb_button">Show notifications</string> + <!-- Title shown in recents popup for removing an application from the list --> + <string name="status_bar_recent_remove_item_title">Remove</string> + + <!-- Title shown in recents popup for inspecting an application's properties --> + <string name="status_bar_recent_inspect_item_title">Inspect</string> + + + <!-- The label in the bar at the top of the status bar when there are no notifications showing. [CHAR LIMIT=40]--> diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java index 37a9913..2d327c4 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java +++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java @@ -53,8 +53,6 @@ import android.view.View; void createAnimation(boolean appearing) { float start, end; - if (RecentsPanelView.DEBUG) Log.e(TAG, "createAnimation()", new Exception()); - // 0: on-screen // height: off-screen float y = mContentView.getTranslationY(); diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java index 5d29e2a..797f94c 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java @@ -26,5 +26,5 @@ public interface RecentsCallback { void handleOnClick(View selectedView); void handleSwipe(View selectedView, int direction); - void handleLongPress(View selectedView); + void handleLongPress(View selectedView, View anchorView); } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java index f984aac..12d6cd9 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java @@ -20,6 +20,7 @@ import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter; import android.animation.Animator; import android.animation.Animator.AnimatorListener; +import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; @@ -30,7 +31,6 @@ import android.database.DataSetObserver; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; @@ -42,10 +42,9 @@ import android.widget.LinearLayout; import com.android.systemui.R; -public class RecentsHorizontalScrollView extends HorizontalScrollView - implements View.OnClickListener, View.OnTouchListener { - private static final boolean DEBUG_INVALIDATE = false; +public class RecentsHorizontalScrollView extends HorizontalScrollView { private static final String TAG = RecentsPanelView.TAG; + private static final boolean DEBUG_INVALIDATE = false; private static final boolean DEBUG = RecentsPanelView.DEBUG; private LinearLayout mLinearLayout; private ActivityDescriptionAdapter mAdapter; @@ -57,6 +56,15 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView private VelocityTracker mVelocityTracker; private float mDensityScale; private float mPagingTouchSlop; + private OnLongClickListener mOnLongClick = new OnLongClickListener() { + public boolean onLongClick(View v) { + final View anchorView = v.findViewById(R.id.app_description); + mCurrentView = v; + mCallback.handleLongPress(v, anchorView); + mCurrentView = null; // make sure we don't accept the return click from this + return true; + } + }; public RecentsHorizontalScrollView(Context context) { this(context, null); @@ -72,13 +80,12 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView return mLinearLayout.getWidth() - getWidth(); } - public void update() { + private void update() { mLinearLayout.removeAllViews(); for (int i = 0; i < mAdapter.getCount(); i++) { - View view = mAdapter.getView(i, null, mLinearLayout); + final View view = mAdapter.getView(i, null, mLinearLayout); view.setClickable(true); - view.setOnClickListener(this); - view.setOnTouchListener(this); + view.setOnLongClickListener(mOnLongClick); mLinearLayout.addView(view); } // Scroll to end after layout. @@ -91,7 +98,20 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } @Override + public void removeViewInLayout(final View view) { + ObjectAnimator anim = animateClosed(view, Constants.MAX_ESCAPE_ANIMATION_DURATION, + "y", view.getY(), view.getY() + view.getHeight()); + anim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + RecentsHorizontalScrollView.super.removeViewInLayout(view); + } + }); + anim.start(); + } + + @Override public boolean onInterceptTouchEvent(MotionEvent ev) { + if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()"); if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } @@ -100,6 +120,18 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView case MotionEvent.ACTION_DOWN: mDragging = false; mLastY = ev.getY(); + final float x = ev.getX() + getScrollX(); + final float y = ev.getY() + getScrollY(); + mCurrentView = null; + for (int i = 0; i < mLinearLayout.getChildCount(); i++) { + View item = mLinearLayout.getChildAt(i); + if (x >= item.getLeft() && x < item.getRight() + && y >= item.getTop() && y < item.getBottom()) { + mCurrentView = item; + if (DEBUG) Log.v(TAG, "Hit item " + item); + break; + } + } break; case MotionEvent.ACTION_MOVE: @@ -111,6 +143,9 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView break; case MotionEvent.ACTION_UP: + if (mCurrentView != null) { + mCallback.handleOnClick(mCurrentView); + } mDragging = false; break; } @@ -125,7 +160,6 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } else if (view.getY() < thumbHeight * (1.0f - Constants.ALPHA_FADE_START)) { result = 1.0f + (thumbHeight * Constants.ALPHA_FADE_START + view.getY()) / fadeHeight; } - if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result); return result; } @@ -138,12 +172,12 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView mVelocityTracker.addMovement(ev); final View animView = mCurrentView; - // TODO: Cache thumbnail - final View thumb = animView.findViewById(R.id.app_thumbnail); + switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: if (animView != null) { final float delta = ev.getY() - mLastY; + final View thumb = animView.findViewById(R.id.app_thumbnail); animView.setY(animView.getY() + delta); animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight())); invalidateGlobalRegion(animView); @@ -167,35 +201,18 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView long duration = (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY)); duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION); - anim = ObjectAnimator.ofFloat(animView, "y", curY, newY); - anim.setInterpolator(new LinearInterpolator()); - final int swipeDirection = animView.getY() >= 0.0f ? - RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; - anim.addListener(new AnimatorListener() { - public void onAnimationStart(Animator animation) { - } - public void onAnimationRepeat(Animator animation) { - } - public void onAnimationEnd(Animator animation) { - mLinearLayout.removeView(mCurrentView); - mCallback.handleSwipe(animView, swipeDirection); - } - public void onAnimationCancel(Animator animation) { - mLinearLayout.removeView(mCurrentView); - mCallback.handleSwipe(animView, swipeDirection); - } - }); - anim.setDuration(duration); + anim = animateClosed(animView, duration, "y", curY, newY); } else { // Animate back to position long duration = Math.abs(velocityY) > 0.0f ? (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY)) : Constants.SNAP_BACK_DURATION; duration = Math.min(duration, Constants.SNAP_BACK_DURATION); anim = ObjectAnimator.ofFloat(animView, "y", animView.getY(), 0.0f); - anim.setInterpolator(new DecelerateInterpolator(2.0f)); + anim.setInterpolator(new DecelerateInterpolator(4.0f)); anim.setDuration(duration); } + final View thumb = animView.findViewById(R.id.app_thumbnail); anim.addUpdateListener(new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight())); @@ -212,6 +229,26 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView return true; } + private ObjectAnimator animateClosed(final View animView, long duration, + String attr, float from, float to) { + ObjectAnimator anim = ObjectAnimator.ofFloat(animView, attr, from, to); + anim.setInterpolator(new LinearInterpolator()); + final int swipeDirection = animView.getX() >= 0.0f ? + RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; + anim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + mLinearLayout.removeView(animView); + mCallback.handleSwipe(animView, swipeDirection); + } + public void onAnimationCancel(Animator animation) { + mLinearLayout.removeView(animView); + mCallback.handleSwipe(animView, swipeDirection); + } + }); + anim.setDuration(duration); + return anim; + } + void invalidateGlobalRegion(View view) { RectF childBounds = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); @@ -236,13 +273,8 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView @Override protected void onFinishInflate() { super.onFinishInflate(); - LayoutInflater inflater = (LayoutInflater) - mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - setScrollbarFadingEnabled(true); - mLinearLayout = (LinearLayout) findViewById(R.id.recents_linear_layout); - final int leftPadding = mContext.getResources() .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin); setOverScrollEffectPadding(leftPadding, 0); @@ -306,16 +338,7 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView mLinearLayout.setLayoutTransition(transition); } - public void onClick(View view) { - mCallback.handleOnClick(view); - } - public void setCallback(RecentsCallback callback) { mCallback = callback; } - - public boolean onTouch(View v, MotionEvent event) { - mCurrentView = v; - return false; - } } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index a55fe9c..bc0a508 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -22,6 +22,7 @@ import java.util.List; import android.animation.Animator; import android.animation.LayoutTransition; import android.app.ActivityManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -39,16 +40,22 @@ import android.graphics.RectF; import android.graphics.Shader.TileMode; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.net.Uri; +import android.provider.Settings; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; +import android.widget.Button; import android.widget.ImageView; +import android.widget.PopupMenu; import android.widget.RelativeLayout; import android.widget.TextView; @@ -69,7 +76,7 @@ public class RecentsPanelView extends RelativeLayout private int mIconDpi; private View mRecentsScrim; private View mRecentsGlowView; - private View mRecentsContainer; + private ViewGroup mRecentsContainer; private Bitmap mGlowBitmap; // TODO: add these widgets attributes to the layout file private int mGlowBitmapPaddingLeftPx; @@ -107,8 +114,18 @@ public class RecentsPanelView extends RelativeLayout } }; + private final class OnLongClickDelegate implements View.OnLongClickListener { + View mOtherView; + OnLongClickDelegate(View other) { + mOtherView = other; + } + public boolean onLongClick(View v) { + return mOtherView.performLongClick(); + } + } + /* package */ final static class ViewHolder { - ImageView thumbnailView; + View thumbnailView; ImageView iconView; TextView labelView; TextView descriptionView; @@ -139,7 +156,7 @@ public class RecentsPanelView extends RelativeLayout if (convertView == null) { convertView = mInflater.inflate(R.layout.status_bar_recent_item, null); holder = new ViewHolder(); - holder.thumbnailView = (ImageView) convertView.findViewById(R.id.app_thumbnail); + holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail); 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); @@ -153,11 +170,12 @@ public class RecentsPanelView extends RelativeLayout final ActivityDescription activityDescription = mActivityDescriptions.get(activityId); final Bitmap thumb = activityDescription.thumbnail; - holder.thumbnailView.setImageBitmap(compositeBitmap(mGlowBitmap, thumb)); + updateDrawable(holder.thumbnailView, compositeBitmap(mGlowBitmap, thumb)); holder.iconView.setImageDrawable(activityDescription.icon); holder.labelView.setText(activityDescription.label); holder.descriptionView.setText(activityDescription.description); holder.thumbnailView.setTag(activityDescription); + holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView)); holder.activityDescription = activityDescription; return convertView; @@ -174,6 +192,20 @@ public class RecentsPanelView extends RelativeLayout return x >= l && x < r && y >= t && y < b; } + private void updateDrawable(View thumbnailView, Bitmap bitmap) { + Drawable d = thumbnailView.getBackground(); + if (d instanceof LayerDrawable) { + LayerDrawable layerD = (LayerDrawable) d; + Drawable thumb = layerD.findDrawableByLayerId(R.id.base_layer); + if (thumb != null) { + layerD.setDrawableByLayerId(R.id.base_layer, + new BitmapDrawable(getResources(), bitmap)); + return; + } + } + Log.w(TAG, "Failed to update drawable"); + } + public void show(boolean show, boolean animate) { if (animate) { if (mShowing != show) { @@ -260,7 +292,7 @@ public class RecentsPanelView extends RelativeLayout protected void onFinishInflate() { super.onFinishInflate(); mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mRecentsContainer = findViewById(R.id.recents_container); + mRecentsContainer = (ViewGroup) findViewById(R.id.recents_container); mListAdapter = new ActivityDescriptionAdapter(mContext); if (mRecentsContainer instanceof RecentsListView) { RecentsListView listView = (RecentsListView) mRecentsContainer; @@ -503,7 +535,35 @@ public class RecentsPanelView extends RelativeLayout am.removeTask(ad.taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS); } - public void handleLongPress(View selectedView) { - // TODO show context menu : "Remove from list", "Show properties" + private void startApplicationDetailsActivity(String packageName) { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + Uri.fromParts("package", packageName, null)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + getContext().startActivity(intent); + } + + public void handleLongPress(final View selectedView, final View anchorView) { + PopupMenu popup = new PopupMenu(mContext, anchorView == null ? selectedView : anchorView); + popup.getMenuInflater().inflate(R.menu.recent_popup_menu, popup.getMenu()); + popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + if (item.getItemId() == R.id.recent_remove_item) { + mRecentsContainer.removeViewInLayout(selectedView); + } else if (item.getItemId() == R.id.recent_inspect_item) { + ViewHolder viewHolder = (ViewHolder) selectedView.getTag(); + if (viewHolder != null) { + final ActivityDescription ad = viewHolder.activityDescription; + startApplicationDetailsActivity(ad.packageName); + mBar.animateCollapse(); + } else { + throw new IllegalStateException("Oops, no tag on view " + selectedView); + } + } else { + return false; + } + return true; + } + }); + popup.show(); } } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java index 27bb0b5..9dd170c 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java @@ -20,6 +20,7 @@ import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter; import android.animation.Animator; import android.animation.Animator.AnimatorListener; +import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; @@ -42,8 +43,7 @@ import android.widget.ScrollView; import com.android.systemui.R; -public class RecentsVerticalScrollView extends ScrollView - implements View.OnClickListener, View.OnTouchListener { +public class RecentsVerticalScrollView extends ScrollView { private static final String TAG = RecentsPanelView.TAG; private static final boolean DEBUG_INVALIDATE = false; private static final boolean DEBUG = RecentsPanelView.DEBUG; @@ -57,6 +57,15 @@ public class RecentsVerticalScrollView extends ScrollView private VelocityTracker mVelocityTracker; private float mDensityScale; private float mPagingTouchSlop; + private OnLongClickListener mOnLongClick = new OnLongClickListener() { + public boolean onLongClick(View v) { + final View anchorView = v.findViewById(R.id.app_description); + mCurrentView = v; + mCallback.handleLongPress(v, anchorView); + mCurrentView = null; // make sure we don't accept the return click from this + return true; + } + }; public RecentsVerticalScrollView(Context context) { this(context, null); @@ -72,13 +81,12 @@ public class RecentsVerticalScrollView extends ScrollView return mLinearLayout.getHeight() - getHeight(); } - public void update() { + private void update() { mLinearLayout.removeAllViews(); for (int i = 0; i < mAdapter.getCount(); i++) { - View view = mAdapter.getView(i, null, mLinearLayout); + final View view = mAdapter.getView(i, null, mLinearLayout); view.setClickable(true); - view.setOnClickListener(this); - view.setOnTouchListener(this); + view.setOnLongClickListener(mOnLongClick); mLinearLayout.addView(view); } // Scroll to end after layout. @@ -91,7 +99,20 @@ public class RecentsVerticalScrollView extends ScrollView } @Override + public void removeViewInLayout(final View view) { + ObjectAnimator anim = animateClosed(view, Constants.MAX_ESCAPE_ANIMATION_DURATION, + "x", view.getX(), view.getX() + view.getWidth()); + anim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + RecentsVerticalScrollView.super.removeViewInLayout(view); + } + }); + anim.start(); + } + + @Override public boolean onInterceptTouchEvent(MotionEvent ev) { + if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()"); if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } @@ -100,6 +121,18 @@ public class RecentsVerticalScrollView extends ScrollView case MotionEvent.ACTION_DOWN: mDragging = false; mLastX = ev.getX(); + final float x = ev.getX() + getScrollX(); + final float y = ev.getY() + getScrollY(); + mCurrentView = null; + for (int i = 0; i < mLinearLayout.getChildCount(); i++) { + View item = mLinearLayout.getChildAt(i); + if (x >= item.getLeft() && x < item.getRight() + && y >= item.getTop() && y < item.getBottom()) { + mCurrentView = item; + Log.v(TAG, "Hit item " + item); + break; + } + } break; case MotionEvent.ACTION_MOVE: @@ -111,6 +144,9 @@ public class RecentsVerticalScrollView extends ScrollView break; case MotionEvent.ACTION_UP: + if (mCurrentView != null) { + mCallback.handleOnClick(mCurrentView); + } mDragging = false; break; } @@ -125,7 +161,6 @@ public class RecentsVerticalScrollView extends ScrollView } else if (view.getX() < thumbWidth* (1.0f - Constants.ALPHA_FADE_START)) { result = 1.0f + (thumbWidth*Constants.ALPHA_FADE_START + view.getX()) / fadeWidth; } - if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result); return result; } @@ -138,12 +173,12 @@ public class RecentsVerticalScrollView extends ScrollView mVelocityTracker.addMovement(ev); final View animView = mCurrentView; - // TODO: Cache thumbnail - final View thumb = animView.findViewById(R.id.app_thumbnail); + switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: if (animView != null) { final float delta = ev.getX() - mLastX; + final View thumb = animView.findViewById(R.id.app_thumbnail); animView.setX(animView.getX() + delta); animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth())); invalidateGlobalRegion(animView); @@ -163,29 +198,11 @@ public class RecentsVerticalScrollView extends ScrollView final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale; if (Math.abs(velocityX) > Math.abs(velocityY) && Math.abs(velocityX) > maxVelocity - && (velocityX > 0.0f) == (animView.getX() >= 0)) { + && (velocityX >= 0.0f) == (animView.getX() >= 0)) { long duration = (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX)); duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION); - anim = ObjectAnimator.ofFloat(animView, "x", curX, newX); - anim.setInterpolator(new LinearInterpolator()); - final int swipeDirection = animView.getX() >= 0.0f ? - RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; - anim.addListener(new AnimatorListener() { - public void onAnimationStart(Animator animation) { - } - public void onAnimationRepeat(Animator animation) { - } - public void onAnimationEnd(Animator animation) { - mLinearLayout.removeView(mCurrentView); - mCallback.handleSwipe(animView, swipeDirection); - } - public void onAnimationCancel(Animator animation) { - mLinearLayout.removeView(mCurrentView); - mCallback.handleSwipe(animView, swipeDirection); - } - }); - anim.setDuration(duration); + anim = animateClosed(animView, duration, "x", curX, newX); } else { // Animate back to position long duration = Math.abs(velocityX) > 0.0f ? (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX)) @@ -196,6 +213,7 @@ public class RecentsVerticalScrollView extends ScrollView anim.setDuration(duration); } + final View thumb = animView.findViewById(R.id.app_thumbnail); anim.addUpdateListener(new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth())); @@ -212,6 +230,26 @@ public class RecentsVerticalScrollView extends ScrollView return true; } + private ObjectAnimator animateClosed(final View animView, long duration, + String attr, float from, float to) { + ObjectAnimator anim = ObjectAnimator.ofFloat(animView, attr, from, to); + anim.setInterpolator(new LinearInterpolator()); + final int swipeDirection = animView.getX() >= 0.0f ? + RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; + anim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + mLinearLayout.removeView(animView); + mCallback.handleSwipe(animView, swipeDirection); + } + public void onAnimationCancel(Animator animation) { + mLinearLayout.removeView(animView); + mCallback.handleSwipe(animView, swipeDirection); + } + }); + anim.setDuration(duration); + return anim; + } + void invalidateGlobalRegion(View view) { RectF childBounds = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); @@ -236,13 +274,8 @@ public class RecentsVerticalScrollView extends ScrollView @Override protected void onFinishInflate() { super.onFinishInflate(); - LayoutInflater inflater = (LayoutInflater) - mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - setScrollbarFadingEnabled(true); - mLinearLayout = (LinearLayout) findViewById(R.id.recents_linear_layout); - final int leftPadding = mContext.getResources() .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin); setOverScrollEffectPadding(leftPadding, 0); @@ -306,16 +339,7 @@ public class RecentsVerticalScrollView extends ScrollView mLinearLayout.setLayoutTransition(transition); } - public void onClick(View view) { - mCallback.handleOnClick(view); - } - public void setCallback(RecentsCallback callback) { mCallback = callback; } - - public boolean onTouch(View v, MotionEvent event) { - mCurrentView = v; - return false; - } } |