diff options
17 files changed, 710 insertions, 291 deletions
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 16008a32add7..42db77e12311 100644 --- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml @@ -19,70 +19,77 @@ --> <!-- android:background="@drawable/status_bar_closed_default_background" --> -<RelativeLayout +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="wrap_content" - android:layout_width="@dimen/status_bar_recents_thumbnail_view_width"> + android:layout_height="match_parent" + android:layout_width="wrap_content"> - <FrameLayout android:id="@+id/app_thumbnail" - android:layout_width="wrap_content" + <RelativeLayout android:id="@+id/recent_item" + android:layout_gravity="bottom" 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_bg" - android:foreground="@drawable/recents_thumbnail_overlay"> - <ImageView android:id="@+id/app_thumbnail_image" - android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_width="wrap_content" + android:paddingBottom="@*android:dimen/status_bar_height"> + + <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_bg" + android:foreground="@drawable/recents_thumbnail_overlay"> + <ImageView android:id="@+id/app_thumbnail_image" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="invisible" + /> + </FrameLayout> + + <ImageView android:id="@+id/app_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignLeft="@id/app_thumbnail" + android:layout_alignTop="@id/app_thumbnail" + android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin" + android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin" + android:maxWidth="@dimen/status_bar_recents_thumbnail_max_width" + android:maxHeight="@dimen/status_bar_recents_thumbnail_max_height" + android:adjustViewBounds="true" android:visibility="invisible" /> - </FrameLayout> - - <ImageView android:id="@+id/app_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignLeft="@id/app_thumbnail" - android:layout_alignTop="@id/app_thumbnail" - android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin" - android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin" - android:maxWidth="@dimen/status_bar_recents_thumbnail_max_width" - android:maxHeight="@dimen/status_bar_recents_thumbnail_max_height" - android:adjustViewBounds="true" - android:visibility="invisible" - /> - <TextView android:id="@+id/app_label" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textSize="@dimen/status_bar_recents_app_label_text_size" - android:fadingEdge="horizontal" - android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" - android:scrollHorizontally="true" - android:layout_alignLeft="@id/app_thumbnail" - android:layout_below="@id/app_thumbnail" - android:layout_marginTop="@dimen/status_bar_recents_text_description_padding" - android:layout_marginLeft="@dimen/recents_thumbnail_bg_padding_left" - android:singleLine="true" - android:ellipsize="marquee" - android:visibility="invisible" - /> + <TextView android:id="@+id/app_label" + android:layout_width="@dimen/status_bar_recents_app_label_width" + android:layout_height="wrap_content" + android:textSize="@dimen/status_bar_recents_app_label_text_size" + android:fadingEdge="horizontal" + android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" + android:scrollHorizontally="true" + android:layout_alignLeft="@id/app_thumbnail" + android:layout_below="@id/app_thumbnail" + android:layout_marginTop="@dimen/status_bar_recents_text_description_padding" + android:layout_marginLeft="@dimen/recents_thumbnail_bg_padding_left" + android:singleLine="true" + android:ellipsize="marquee" + android:visibility="invisible" + /> - <TextView android:id="@+id/app_description" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textSize="@dimen/status_bar_recents_app_description_text_size" - android:fadingEdge="horizontal" - android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" - android:scrollHorizontally="true" - android:layout_alignLeft="@id/app_thumbnail" - android:layout_below="@id/app_label" - android:layout_marginTop="@dimen/status_bar_recents_text_description_padding" - android:layout_marginLeft="@dimen/recents_thumbnail_bg_padding_left" - android:singleLine="true" - android:ellipsize="marquee" - /> + <TextView android:id="@+id/app_description" + android:layout_width="@dimen/status_bar_recents_app_label_width" + android:layout_height="wrap_content" + android:textSize="@dimen/status_bar_recents_app_description_text_size" + android:fadingEdge="horizontal" + android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" + android:scrollHorizontally="true" + android:layout_alignLeft="@id/app_thumbnail" + android:layout_below="@id/app_label" + android:layout_marginTop="@dimen/status_bar_recents_text_description_padding" + android:layout_marginLeft="@dimen/recents_thumbnail_bg_padding_left" + android:singleLine="true" + android:ellipsize="marquee" + /> -</RelativeLayout> + </RelativeLayout> +</FrameLayout> 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 20ef7cf26b37..f84cc192bba3 100644 --- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml @@ -30,13 +30,12 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentBottom="true" - android:paddingBottom="@*android:dimen/status_bar_height" android:clipToPadding="false" android:clipChildren="false"> <LinearLayout android:id="@+id/recents_glow" android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_height="match_parent" android:layout_gravity="bottom|right" android:orientation="horizontal" android:clipToPadding="false" @@ -44,7 +43,7 @@ > <com.android.systemui.recent.RecentsHorizontalScrollView android:id="@+id/recents_container" android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_height="match_parent" android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin" android:divider="@null" android:stackFromBottom="true" @@ -58,7 +57,7 @@ <LinearLayout android:id="@+id/recents_linear_layout" android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_height="match_parent" android:orientation="horizontal" android:clipToPadding="false" android:clipChildren="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 c0fce713fd3b..f6b72d43906d 100644 --- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml @@ -19,79 +19,84 @@ --> <!-- android:background="@drawable/status_bar_closed_default_background" --> -<RelativeLayout +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" - android:layout_width="@dimen/status_bar_recents_thumbnail_view_width"> + android:layout_width="match_parent"> - <FrameLayout android:id="@+id/app_thumbnail" - android:layout_width="wrap_content" + <RelativeLayout android:id="@+id/recent_item" 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_bg" - android:foreground="@drawable/recents_thumbnail_overlay"> - <ImageView android:id="@+id/app_thumbnail_image" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="invisible" - /> - </FrameLayout> + android:layout_width="match_parent"> - <ImageView android:id="@+id/app_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignLeft="@id/app_thumbnail" - android:layout_alignTop="@id/app_thumbnail" - android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin" - android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin" - android:maxWidth="@dimen/status_bar_recents_thumbnail_max_width" - android:maxHeight="@dimen/status_bar_recents_thumbnail_max_height" - android:adjustViewBounds="true" - /> + <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_bg" + android:foreground="@drawable/recents_thumbnail_overlay"> + <ImageView android:id="@+id/app_thumbnail_image" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="invisible" + /> + </FrameLayout> - <TextView android:id="@+id/app_label" - android:layout_width="@dimen/status_bar_recents_app_label_width" - android:layout_height="wrap_content" - android:textSize="@dimen/status_bar_recents_app_label_text_size" - android:fadingEdge="horizontal" - android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" - android:scrollHorizontally="true" - android:layout_alignParentLeft="true" - android:layout_alignTop="@id/app_icon" - android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin" - android:singleLine="true" - android:ellipsize="marquee" - /> + <ImageView android:id="@+id/app_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignLeft="@id/app_thumbnail" + android:layout_alignTop="@id/app_thumbnail" + android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin" + android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin" + android:maxWidth="@dimen/status_bar_recents_thumbnail_max_width" + android:maxHeight="@dimen/status_bar_recents_thumbnail_max_height" + android:adjustViewBounds="true" + /> - <View android:id="@+id/recents_callout_line" - android:layout_width="@dimen/status_bar_recents_app_label_width" - android:layout_height="1dip" - android:layout_alignParentLeft="true" - android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin" - android:layout_toLeftOf="@id/app_thumbnail" - android:layout_below="@id/app_label" - android:layout_marginRight="3dip" - android:layout_marginTop="3dip" - android:background="@drawable/recents_callout_line" - /> + <TextView android:id="@+id/app_label" + android:layout_width="@dimen/status_bar_recents_app_label_width" + android:layout_height="wrap_content" + android:textSize="@dimen/status_bar_recents_app_label_text_size" + android:fadingEdge="horizontal" + android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" + android:scrollHorizontally="true" + android:layout_alignParentLeft="true" + android:layout_alignTop="@id/app_icon" + android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin" + android:singleLine="true" + android:ellipsize="marquee" + /> - <TextView android:id="@+id/app_description" - android:layout_width="@dimen/status_bar_recents_app_label_width" - android:layout_height="wrap_content" - android:textSize="@dimen/status_bar_recents_app_description_text_size" - android:fadingEdge="horizontal" - android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" - android:scrollHorizontally="true" - android:layout_alignParentLeft="true" - android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin" - android:layout_below="@id/recents_callout_line" - android:layout_marginTop="3dip" - android:singleLine="true" - android:ellipsize="marquee" - /> + <View android:id="@+id/recents_callout_line" + android:layout_width="@dimen/status_bar_recents_app_label_width" + android:layout_height="1dip" + android:layout_alignParentLeft="true" + android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin" + android:layout_toLeftOf="@id/app_thumbnail" + android:layout_below="@id/app_label" + android:layout_marginRight="3dip" + android:layout_marginTop="3dip" + android:background="@drawable/recents_callout_line" + /> + + <TextView android:id="@+id/app_description" + android:layout_width="@dimen/status_bar_recents_app_label_width" + android:layout_height="wrap_content" + android:textSize="@dimen/status_bar_recents_app_description_text_size" + android:fadingEdge="horizontal" + android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" + android:scrollHorizontally="true" + android:layout_alignParentLeft="true" + android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin" + android:layout_below="@id/recents_callout_line" + android:layout_marginTop="3dip" + android:singleLine="true" + android:ellipsize="marquee" + /> -</RelativeLayout> + </RelativeLayout> +</FrameLayout> 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 c680b8eeeceb..dd25cf9dc9c8 100644 --- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml @@ -40,7 +40,7 @@ android:layout_marginTop="@*android:dimen/status_bar_height"> <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container" - android:layout_width="@dimen/status_bar_recents_width" + android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginRight="0dp" android:divider="@null" @@ -53,7 +53,7 @@ android:clipChildren="false"> <LinearLayout android:id="@+id/recents_linear_layout" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:clipToPadding="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 530650887927..8dab2e6ba12f 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml @@ -19,10 +19,10 @@ --> <!-- android:background="@drawable/status_bar_closed_default_background" --> -<RelativeLayout +<RelativeLayout android:id="@+id/recent_item" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" - android:layout_width="@dimen/status_bar_recents_thumbnail_view_width"> + android:layout_width="wrap_content"> <FrameLayout android:id="@+id/app_thumbnail" android:layout_width="wrap_content" diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml index 391968587c88..656c7c1d7451 100644 --- a/packages/SystemUI/res/values-land/dimens.xml +++ b/packages/SystemUI/res/values-land/dimens.xml @@ -20,8 +20,6 @@ <dimen name="navigation_bar_size">@*android:dimen/navigation_bar_width</dimen> <!-- Recent Applications parameters --> - <!-- Width of a recent app view, including all content --> - <dimen name="status_bar_recents_thumbnail_view_width">156dp</dimen> <!-- How far the thumbnail for a recent app appears from left edge --> <dimen name="status_bar_recents_thumbnail_left_margin">8dp</dimen> <!-- How far the thumbnail for a recent app appears from top edge --> @@ -31,7 +29,7 @@ <!-- Padding for text descriptions --> <dimen name="status_bar_recents_text_description_padding">8dp</dimen> <!-- Width of application label text --> - <dimen name="status_bar_recents_app_label_width">97dip</dimen> + <dimen name="status_bar_recents_app_label_width">156dip</dimen> <!-- Left margin of application label text --> <dimen name="status_bar_recents_app_label_left_margin">16dip</dimen> <!-- Margin between recents container and glow on the right --> diff --git a/packages/SystemUI/res/values-port/dimens.xml b/packages/SystemUI/res/values-port/dimens.xml index 54c25fab2704..03b17e99cbf0 100644 --- a/packages/SystemUI/res/values-port/dimens.xml +++ b/packages/SystemUI/res/values-port/dimens.xml @@ -17,8 +17,6 @@ --> <resources> <!-- Recent Applications parameters --> - <!-- Width of a recent app view, including all content --> - <dimen name="status_bar_recents_thumbnail_view_width">156dp</dimen> <!-- How far the thumbnail for a recent app appears from left edge --> <dimen name="status_bar_recents_thumbnail_left_margin">110dp</dimen> <!-- Width of scrollable area in recents --> diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml new file mode 100644 index 000000000000..3e2ec5957812 --- /dev/null +++ b/packages/SystemUI/res/values-sw600dp/config.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 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. +*/ +--> + +<resources> + + <!-- Whether we're using the tablet-optimized recents interface (we use this + value at runtime for some things) --> + <bool name="config_recents_interface_for_tablets">true</bool> +</resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index d7d7817fc15b..4ac89b2fac29 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -21,6 +21,10 @@ for different hardware and product builds. --> <resources> + <!-- Whether we're using the tablet-optimized recents interface (we use this + value at runtime for some things) --> + <bool name="config_recents_interface_for_tablets">false</bool> + <!-- Control whether status bar should distinguish HSPA data icon form UMTS data icon on devices --> <bool name="config_hspa_data_distinguishable">false</bool> diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index e7ed0528a275..6cfbc1b26768 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -33,20 +33,19 @@ public class SwipeHelper { private static final boolean DEBUG = false; private static final boolean DEBUG_INVALIDATE = false; private static final boolean SLOW_ANIMATIONS = false; // DEBUG; + private static final boolean CONSTRAIN_SWIPE = true; + private static final boolean FADE_OUT_DURING_SWIPE = true; + private static final boolean DISMISS_IF_SWIPED_FAR_ENOUGH = true; public static final int X = 0; public static final int Y = 1; - private boolean CONSTRAIN_SWIPE = true; - private boolean FADE_OUT_DURING_SWIPE = true; - private boolean DISMISS_IF_SWIPED_FAR_ENOUGH = true; - private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec private int MAX_ESCAPE_ANIMATION_DURATION = 500; // ms private int MAX_DISMISS_VELOCITY = 1000; // dp/sec private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 250; // ms - public static float ALPHA_FADE_START = 0.8f; // fraction of thumbnail width + public static float ALPHA_FADE_START = 0f; // fraction of thumbnail width // where fade starts static final float ALPHA_FADE_END = 0.5f; // fraction of thumbnail width // beyond which alpha->0 @@ -59,6 +58,8 @@ public class SwipeHelper { private float mInitialTouchPos; private boolean mDragging; private View mCurrView; + private View mCurrAnimView; + private boolean mCanCurrViewBeDimissed; private float mDensityScale; public SwipeHelper(int swipeDirection, Callback callback, float densityScale, @@ -82,8 +83,8 @@ public class SwipeHelper { return mSwipeDirection == X ? ev.getX() : ev.getY(); } - private float getPos(View v) { - return mSwipeDirection == X ? v.getX() : v.getY(); + private float getTranslation(View v) { + return mSwipeDirection == X ? v.getTranslationX() : v.getTranslationY(); } private float getVelocity(VelocityTracker vt) { @@ -115,19 +116,15 @@ public class SwipeHelper { v.getMeasuredHeight(); } - private float getContentSize(View v) { - View content = mCallback.getChildContentView(v); - return getSize(content); - } - - private float getAlphaForOffset(View view, float thumbSize) { - final float fadeSize = ALPHA_FADE_END * thumbSize; + private float getAlphaForOffset(View view) { + float viewSize = getSize(view); + final float fadeSize = ALPHA_FADE_END * viewSize; float result = 1.0f; - float pos = getPos(view); - if (pos >= thumbSize * ALPHA_FADE_START) { - result = 1.0f - (pos - thumbSize * ALPHA_FADE_START) / fadeSize; - } else if (pos < thumbSize * (1.0f - ALPHA_FADE_START)) { - result = 1.0f + (thumbSize * ALPHA_FADE_START + pos) / fadeSize; + float pos = getTranslation(view); + if (pos >= viewSize * ALPHA_FADE_START) { + result = 1.0f - (pos - viewSize * ALPHA_FADE_START) / fadeSize; + } else if (pos < viewSize * (1.0f - ALPHA_FADE_START)) { + result = 1.0f + (viewSize * ALPHA_FADE_START + pos) / fadeSize; } return result; } @@ -168,6 +165,8 @@ public class SwipeHelper { case MotionEvent.ACTION_DOWN: mDragging = false; mCurrView = mCallback.getChildAtPosition(ev); + mCurrAnimView = mCallback.getChildContentView(mCurrView); + mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView); mVelocityTracker.clear(); mVelocityTracker.addMovement(ev); mInitialTouchPos = getPos(ev); @@ -180,21 +179,24 @@ public class SwipeHelper { if (Math.abs(delta) > mPagingTouchSlop) { mCallback.onBeginDrag(mCurrView); mDragging = true; - mInitialTouchPos = getPos(ev) - getPos(mCurrView); + mInitialTouchPos = getPos(ev) - getTranslation(mCurrAnimView); } } break; case MotionEvent.ACTION_UP: mDragging = false; mCurrView = null; + mCurrAnimView = null; break; } return mDragging; } - public void dismissChild(final View animView, float velocity) { + public void dismissChild(final View view, float velocity) { + final View animView = mCallback.getChildContentView(view); + final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); float newPos; - if (velocity < 0 || (velocity == 0 && getPos(animView) < 0)) { + if (velocity < 0 || (velocity == 0 && getTranslation(animView) < 0)) { newPos = -getSize(animView); } else { newPos = getSize(animView); @@ -202,7 +204,7 @@ public class SwipeHelper { int duration = MAX_ESCAPE_ANIMATION_DURATION; if (velocity != 0) { duration = Math.min(duration, - (int) (Math.abs(newPos - getPos(animView)) * 1000f / Math + (int) (Math.abs(newPos - getTranslation(animView)) * 1000f / Math .abs(velocity))); } ObjectAnimator anim = createTranslationAnimation(animView, newPos); @@ -216,17 +218,17 @@ public class SwipeHelper { } public void onAnimationEnd(Animator animation) { - mCallback.onChildDismissed(animView); + mCallback.onChildDismissed(view); } public void onAnimationCancel(Animator animation) { - mCallback.onChildDismissed(animView); + mCallback.onChildDismissed(view); } }); anim.addUpdateListener(new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { - if (FADE_OUT_DURING_SWIPE) { - animView.setAlpha(getAlphaForOffset(animView, getContentSize(animView))); + if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) { + animView.setAlpha(getAlphaForOffset(animView)); } invalidateGlobalRegion(animView); } @@ -234,14 +236,16 @@ public class SwipeHelper { anim.start(); } - public void snapChild(final View animView, float velocity) { + public void snapChild(final View view, float velocity) { + final View animView = mCallback.getChildContentView(view); + final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(animView); ObjectAnimator anim = createTranslationAnimation(animView, 0); int duration = SNAP_ANIM_LEN; anim.setDuration(duration); anim.addUpdateListener(new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { - if (FADE_OUT_DURING_SWIPE) { - animView.setAlpha(getAlphaForOffset(animView, getContentSize(animView))); + if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) { + animView.setAlpha(getAlphaForOffset(animView)); } invalidateGlobalRegion(animView); } @@ -264,7 +268,7 @@ public class SwipeHelper { // don't let items that can't be dismissed be dragged more than // maxScrollDistance if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) { - float size = getSize(mCurrView); + float size = getSize(mCurrAnimView); float maxScrollDistance = 0.15f * size; if (Math.abs(delta) >= size) { delta = delta > 0 ? maxScrollDistance : -maxScrollDistance; @@ -272,9 +276,9 @@ public class SwipeHelper { delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2)); } } - setTranslation(mCurrView, delta); - if (FADE_OUT_DURING_SWIPE) { - mCurrView.setAlpha(getAlphaForOffset(mCurrView, getContentSize(mCurrView))); + setTranslation(mCurrAnimView, delta); + if (FADE_OUT_DURING_SWIPE && mCanCurrViewBeDimissed) { + mCurrAnimView.setAlpha(getAlphaForOffset(mCurrAnimView)); } invalidateGlobalRegion(mCurrView); } @@ -290,10 +294,10 @@ public class SwipeHelper { // Decide whether to dismiss the current view boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH && - Math.abs(getPos(mCurrView)) > 0.4 * getSize(mCurrView); + Math.abs(getTranslation(mCurrAnimView)) > 0.4 * getSize(mCurrAnimView); boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) && (Math.abs(velocity) > Math.abs(perpendicularVelocity)) && - (velocity > 0) == (getPos(mCurrView) > 0); + (velocity > 0) == (getTranslation(mCurrAnimView) > 0); boolean dismissChild = mCallback.canChildBeDismissed(mCurrView) && (childSwipedFastEnough || childSwipedFarEnough); diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java index 5609ead6e284..2de4185fd108 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java @@ -27,4 +27,8 @@ public interface RecentsCallback { void handleOnClick(View selectedView); void handleSwipe(View selectedView); void handleLongPress(View selectedView, View anchorView); + void handleShowBackground(boolean show); + + // TODO: find another way to get this info from RecentsPanelView + boolean isRecentsVisible(); } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java index 8da2db641867..7ad7484a3f3d 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 android.animation.LayoutTransition; import android.content.Context; import android.content.res.Configuration; import android.database.DataSetObserver; +import android.graphics.Canvas; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; @@ -41,6 +42,8 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView private RecentsCallback mCallback; protected int mLastScrollPosition; private SwipeHelper mSwipeHelper; + private RecentsScrollViewPerformanceHelper mPerformanceHelper; + private OnLongClickListener mOnLongClick = new OnLongClickListener() { public boolean onLongClick(View v) { final View anchorView = v.findViewById(R.id.app_description); @@ -49,15 +52,12 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } }; - public RecentsHorizontalScrollView(Context context) { - this(context, null); - } - public RecentsHorizontalScrollView(Context context, AttributeSet attrs) { super(context, attrs, 0); float densityScale = getResources().getDisplayMetrics().density; float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); mSwipeHelper = new SwipeHelper(SwipeHelper.Y, this, densityScale, pagingTouchSlop); + mPerformanceHelper = RecentsScrollViewPerformanceHelper.create(context, attrs, this, false); } private int scrollPositionOfMostRecent() { @@ -71,7 +71,11 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView view.setLongClickable(true); view.setOnLongClickListener(mOnLongClick); - final View thumbnail = getChildContentView(view); + if (mPerformanceHelper != null) { + mPerformanceHelper.addViewCallback(view); + } + + final View thumbnail = view.findViewById(R.id.app_thumbnail); // thumbnail is set to clickable in the layout file thumbnail.setOnClickListener(new OnClickListener() { public void onClick(View v) { @@ -139,7 +143,60 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } public View getChildContentView(View v) { - return v.findViewById(R.id.app_thumbnail); + return v.findViewById(R.id.recent_item); + } + + @Override + protected void onLayout (boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (mPerformanceHelper != null) { + mPerformanceHelper.onLayoutCallback(); + } + } + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + + if (mPerformanceHelper != null) { + int paddingLeft = mPaddingLeft; + final boolean offsetRequired = isPaddingOffsetRequired(); + if (offsetRequired) { + paddingLeft += getLeftPaddingOffset(); + } + + int left = mScrollX + paddingLeft; + int right = left + mRight - mLeft - mPaddingRight - paddingLeft; + int top = mScrollY + getFadeTop(offsetRequired); + int bottom = top + getFadeHeight(offsetRequired); + + if (offsetRequired) { + right += getRightPaddingOffset(); + bottom += getBottomPaddingOffset(); + } + mPerformanceHelper.drawCallback(canvas, + left, right, top, bottom, mScrollX, mScrollY, + 0, 0, + getLeftFadingEdgeStrength(), getRightFadingEdgeStrength()); + } + } + + @Override + public int getVerticalFadingEdgeLength() { + if (mPerformanceHelper != null) { + return mPerformanceHelper.getVerticalFadingEdgeLengthCallback(); + } else { + return super.getVerticalFadingEdgeLength(); + } + } + + @Override + public int getHorizontalFadingEdgeLength() { + if (mPerformanceHelper != null) { + return mPerformanceHelper.getHorizontalFadingEdgeLengthCallback(); + } else { + return super.getHorizontalFadingEdgeLength(); + } } @Override @@ -153,6 +210,14 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } @Override + public void onAttachedToWindow() { + if (mPerformanceHelper != null) { + mPerformanceHelper.onAttachedToWindowCallback( + mCallback, mLinearLayout, isHardwareAccelerated()); + } + } + + @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); float densityScale = getResources().getDisplayMetrics().density; @@ -192,6 +257,12 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView }); } + public void onRecentsVisibilityChanged() { + if (mPerformanceHelper != null) { + mPerformanceHelper.updateShowBackground(); + } + } + @Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); @@ -220,6 +291,9 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView @Override public void setLayoutTransition(LayoutTransition transition) { + if (mPerformanceHelper != null) { + mPerformanceHelper.setLayoutTransitionCallback(transition); + } // The layout transition applies to our embedded LinearLayout mLinearLayout.setLayoutTransition(transition); } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsListView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsListView.java deleted file mode 100644 index d8b086b6c3cb..000000000000 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsListView.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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. - */ - -package com.android.systemui.recent; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ListView; - -import com.android.systemui.R; - -public class RecentsListView extends ListView { - private int mLastVisiblePosition; - private RecentsCallback mCallback; - - public RecentsListView(Context context) { - this(context, null); - } - - public RecentsListView(Context context, AttributeSet attrs) { - super(context, attrs, 0); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - LayoutInflater inflater = (LayoutInflater) - mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - - View footer = inflater.inflate(R.layout.status_bar_recent_panel_footer, this, false); - setScrollbarFadingEnabled(true); - addFooterView(footer, null, false); - final int leftPadding = mContext.getResources() - .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin); - setOverScrollEffectPadding(leftPadding, 0); - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - // Keep track of the last visible item in the list so we can restore it - // to the bottom when the orientation changes. - final int childCount = getChildCount(); - if (childCount > 0) { - mLastVisiblePosition = getFirstVisiblePosition() + childCount - 1; - View view = getChildAt(childCount - 1); - final int distanceFromBottom = getHeight() - view.getTop(); - - // This has to happen post-layout, so run it "in the future" - post(new Runnable() { - public void run() { - setSelectionFromTop(mLastVisiblePosition, getHeight() - distanceFromBottom); - } - }); - } - } - - @Override - protected void onVisibilityChanged(View changedView, int visibility) { - super.onVisibilityChanged(changedView, visibility); - // scroll to bottom after reloading - int count = getAdapter().getCount(); - mLastVisiblePosition = count - 1; - if (visibility == View.VISIBLE && changedView == this) { - post(new Runnable() { - public void run() { - setSelection(mLastVisiblePosition); - } - }); - } - } - - public void setCallback(RecentsCallback callback) { - mCallback = callback; - } - -} diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 9cc2c29129b2..233ed6ccb785 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -56,7 +56,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.HorizontalScrollView; import android.widget.ImageView; @@ -64,6 +63,7 @@ import android.widget.PopupMenu; import android.widget.RelativeLayout; import android.widget.ScrollView; import android.widget.TextView; +import android.widget.AdapterView.OnItemClickListener; import com.android.systemui.R; import com.android.systemui.statusbar.StatusBar; @@ -73,7 +73,7 @@ import com.android.systemui.statusbar.tablet.TabletStatusBar; public class RecentsPanelView extends RelativeLayout implements OnItemClickListener, RecentsCallback, StatusBarPanel, Animator.AnimatorListener { - static final String TAG = "RecentsListView"; + static final String TAG = "RecentsPanelView"; static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false; private static final int DISPLAY_TASKS = 20; private static final int MAX_TASKS = DISPLAY_TASKS + 1; // allow extra for non-apps @@ -178,7 +178,7 @@ public class RecentsPanelView extends RelativeLayout public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { - convertView = mInflater.inflate(R.layout.status_bar_recent_item, null); + convertView = mInflater.inflate(R.layout.status_bar_recent_item, parent, false); holder = new ViewHolder(); holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail); holder.thumbnailViewImage = (ImageView) convertView.findViewById( @@ -247,6 +247,18 @@ public class RecentsPanelView extends RelativeLayout } } + public void handleShowBackground(boolean show) { + if (show) { + mRecentsScrim.setBackgroundResource(R.drawable.status_bar_recents_background); + } else { + mRecentsScrim.setBackgroundDrawable(null); + } + } + + public boolean isRecentsVisible() { + return getVisibility() == VISIBLE; + } + public void onAnimationCancel(Animator animation) { } @@ -332,12 +344,7 @@ public class RecentsPanelView extends RelativeLayout mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mRecentsContainer = (ViewGroup) findViewById(R.id.recents_container); mListAdapter = new ActivityDescriptionAdapter(mContext); - if (mRecentsContainer instanceof RecentsListView) { - RecentsListView listView = (RecentsListView) mRecentsContainer; - listView.setAdapter(mListAdapter); - listView.setOnItemClickListener(this); - listView.setCallback(this); - } else if (mRecentsContainer instanceof RecentsHorizontalScrollView){ + if (mRecentsContainer instanceof RecentsHorizontalScrollView){ RecentsHorizontalScrollView scrollView = (RecentsHorizontalScrollView) mRecentsContainer; scrollView.setAdapter(mListAdapter); @@ -349,7 +356,7 @@ public class RecentsPanelView extends RelativeLayout scrollView.setCallback(this); } else { - throw new IllegalArgumentException("missing RecentsListView/RecentsScrollView"); + throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView"); } @@ -382,6 +389,14 @@ public class RecentsPanelView extends RelativeLayout if (visibility == View.VISIBLE && changedView == this) { refreshApplicationList(); } + + if (mRecentsContainer instanceof RecentsHorizontalScrollView) { + ((RecentsHorizontalScrollView) mRecentsContainer).onRecentsVisibilityChanged(); + } else if (mRecentsContainer instanceof RecentsVerticalScrollView) { + ((RecentsVerticalScrollView) mRecentsContainer).onRecentsVisibilityChanged(); + } else { + throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView"); + } } Drawable getFullResDefaultActivityIcon() { diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java new file mode 100644 index 000000000000..b7e656ea47f4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java @@ -0,0 +1,304 @@ +/* + * 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. + */ + +package com.android.systemui.recent; + +import android.animation.LayoutTransition; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Shader; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import com.android.systemui.R; + +public class RecentsScrollViewPerformanceHelper { + public static final boolean OPTIMIZE_SW_RENDERED_RECENTS = true; + public static final boolean USE_DARK_FADE_IN_HW_ACCELERATED_MODE = true; + private View mScrollView; + private LinearLayout mLinearLayout; + private RecentsCallback mCallback; + + private boolean mShowBackground = false; + private int mFadingEdgeLength; + private Drawable.ConstantState mBackgroundDrawable; + private Context mContext; + private boolean mIsVertical; + private boolean mFirstTime = true; + private boolean mSoftwareRendered = false; + private boolean mAttachedToWindow = false; + + public static RecentsScrollViewPerformanceHelper create(Context context, + AttributeSet attrs, View scrollView, boolean isVertical) { + boolean isTablet = context.getResources(). + getBoolean(R.bool.config_recents_interface_for_tablets); + if (!isTablet && (OPTIMIZE_SW_RENDERED_RECENTS || USE_DARK_FADE_IN_HW_ACCELERATED_MODE)) { + return new RecentsScrollViewPerformanceHelper(context, attrs, scrollView, isVertical); + } else { + return null; + } + } + + public RecentsScrollViewPerformanceHelper(Context context, + AttributeSet attrs, View scrollView, boolean isVertical) { + mScrollView = scrollView; + mContext = context; + TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View); + mFadingEdgeLength = a.getDimensionPixelSize(android.R.styleable.View_fadingEdgeLength, + ViewConfiguration.get(context).getScaledFadingEdgeLength()); + mIsVertical = isVertical; + } + + public void onAttachedToWindowCallback( + RecentsCallback callback, LinearLayout layout, boolean hardwareAccelerated) { + mSoftwareRendered = !hardwareAccelerated; + if ((mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) + || USE_DARK_FADE_IN_HW_ACCELERATED_MODE) { + mScrollView.setVerticalFadingEdgeEnabled(false); + mScrollView.setHorizontalFadingEdgeEnabled(false); + } + if (mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) { + mCallback = callback; + mLinearLayout = layout; + mAttachedToWindow = true; + mBackgroundDrawable = mContext.getResources() + .getDrawable(R.drawable.status_bar_recents_background).getConstantState(); + updateShowBackground(); + } + + } + + public void addViewCallback(View newLinearLayoutChild) { + if (mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) { + final View view = newLinearLayoutChild; + if (mShowBackground) { + view.setBackgroundDrawable(mBackgroundDrawable.newDrawable()); + view.setDrawingCacheEnabled(true); + view.buildDrawingCache(); + } else { + view.setBackgroundDrawable(null); + view.setDrawingCacheEnabled(false); + view.destroyDrawingCache(); + } + } + } + + public void onLayoutCallback() { + if (mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) { + mScrollView.post(new Runnable() { + public void run() { + updateShowBackground(); + } + }); + } + } + + public void drawCallback(Canvas canvas, + int left, int right, int top, int bottom, int scrollX, int scrollY, + float topFadingEdgeStrength, float bottomFadingEdgeStrength, + float leftFadingEdgeStrength, float rightFadingEdgeStrength) { + if (mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) { + if (mIsVertical) { + if (scrollY < 0) { + Drawable d = mBackgroundDrawable.newDrawable().getCurrent(); + d.setBounds(0, scrollY, mScrollView.getWidth(), 0); + d.draw(canvas); + } else { + final int childHeight = mLinearLayout.getHeight(); + if (scrollY + mScrollView.getHeight() > childHeight) { + Drawable d = mBackgroundDrawable.newDrawable().getCurrent(); + d.setBounds(0, childHeight, mScrollView.getWidth(), + scrollY + mScrollView.getHeight()); + d.draw(canvas); + } + } + } else { + if (scrollX < 0) { + Drawable d = mBackgroundDrawable.newDrawable().getCurrent(); + d.setBounds(scrollX, 0, 0, mScrollView.getHeight()); + d.draw(canvas); + } else { + final int childWidth = mLinearLayout.getWidth(); + if (scrollX + mScrollView.getWidth() > childWidth) { + Drawable d = mBackgroundDrawable.newDrawable().getCurrent(); + d.setBounds(childWidth, 0, + scrollX + mScrollView.getWidth(), mScrollView.getHeight()); + d.draw(canvas); + } + } + } + } + + if ((mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) + || USE_DARK_FADE_IN_HW_ACCELERATED_MODE) { + Paint p = new Paint(); + Matrix matrix = new Matrix(); + // use use a height of 1, and then wack the matrix each time we + // actually use it. + Shader fade = new LinearGradient(0, 0, 0, 1, 0xCC000000, 0, Shader.TileMode.CLAMP); + // PULL OUT THIS CONSTANT + + p.setShader(fade); + + // draw the fade effect + boolean drawTop = false; + boolean drawBottom = false; + boolean drawLeft = false; + boolean drawRight = false; + + float topFadeStrength = 0.0f; + float bottomFadeStrength = 0.0f; + float leftFadeStrength = 0.0f; + float rightFadeStrength = 0.0f; + + final float fadeHeight = mFadingEdgeLength; + int length = (int) fadeHeight; + + // clip the fade length if top and bottom fades overlap + // overlapping fades produce odd-looking artifacts + if (mIsVertical && (top + length > bottom - length)) { + length = (bottom - top) / 2; + } + + // also clip horizontal fades if necessary + if (!mIsVertical && (left + length > right - length)) { + length = (right - left) / 2; + } + + if (mIsVertical) { + topFadeStrength = Math.max(0.0f, Math.min(1.0f, topFadingEdgeStrength)); + drawTop = topFadeStrength * fadeHeight > 1.0f; + bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, bottomFadingEdgeStrength)); + drawBottom = bottomFadeStrength * fadeHeight > 1.0f; + } + + if (!mIsVertical) { + leftFadeStrength = Math.max(0.0f, Math.min(1.0f, leftFadingEdgeStrength)); + drawLeft = leftFadeStrength * fadeHeight > 1.0f; + rightFadeStrength = Math.max(0.0f, Math.min(1.0f, rightFadingEdgeStrength)); + drawRight = rightFadeStrength * fadeHeight > 1.0f; + } + + if (drawTop) { + matrix.setScale(1, fadeHeight * topFadeStrength); + matrix.postTranslate(left, top); + fade.setLocalMatrix(matrix); + canvas.drawRect(left, top, right, top + length, p); + } + + if (drawBottom) { + matrix.setScale(1, fadeHeight * bottomFadeStrength); + matrix.postRotate(180); + matrix.postTranslate(left, bottom); + fade.setLocalMatrix(matrix); + canvas.drawRect(left, bottom - length, right, bottom, p); + } + + if (drawLeft) { + matrix.setScale(1, fadeHeight * leftFadeStrength); + matrix.postRotate(-90); + matrix.postTranslate(left, top); + fade.setLocalMatrix(matrix); + canvas.drawRect(left, top, left + length, bottom, p); + } + + if (drawRight) { + matrix.setScale(1, fadeHeight * rightFadeStrength); + matrix.postRotate(90); + matrix.postTranslate(right, top); + fade.setLocalMatrix(matrix); + canvas.drawRect(right - length, top, right, bottom, p); + } + } + } + + public int getVerticalFadingEdgeLengthCallback() { + return mFadingEdgeLength; + } + + public int getHorizontalFadingEdgeLengthCallback() { + return mFadingEdgeLength; + } + + public void setLayoutTransitionCallback(LayoutTransition transition) { + if (mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) { + if (transition != null) { + transition.addTransitionListener(new LayoutTransition.TransitionListener() { + @Override + public void startTransition(LayoutTransition transition, + ViewGroup container, View view, int transitionType) { + updateShowBackground(); + } + + @Override + public void endTransition(LayoutTransition transition, + ViewGroup container, View view, int transitionType) { + updateShowBackground(); + } + }); + } + } + } + + // Turn on/off drawing the background in our ancestor, and turn on/off drawing + // in the items in LinearLayout contained by this scrollview. + // Moving the background drawing to our children, and turning on a drawing cache + // for each of them, gives us a ~20fps gain when Recents is rendered in software + public void updateShowBackground() { + if (!mAttachedToWindow) { + // We haven't been initialized yet-- we'll get called again when we are + return; + } + if (mSoftwareRendered && OPTIMIZE_SW_RENDERED_RECENTS) { + LayoutTransition transition = mLinearLayout.getLayoutTransition(); + int linearLayoutSize = + mIsVertical ? mLinearLayout.getHeight() : mLinearLayout.getWidth(); + int scrollViewSize = + mIsVertical ? mScrollView.getHeight() : mScrollView.getWidth(); + boolean show = !mScrollView.isHardwareAccelerated() && + (linearLayoutSize > scrollViewSize) && + !(transition != null && transition.isRunning()) && + mCallback.isRecentsVisible(); + + if (!mFirstTime && show == mShowBackground) return; + mShowBackground = show; + mFirstTime = false; + + mCallback.handleShowBackground(!show); + for (int i = 0; i < mLinearLayout.getChildCount(); i++) { + View v = mLinearLayout.getChildAt(i); + if (show) { + v.setBackgroundDrawable(mBackgroundDrawable.newDrawable()); + v.setDrawingCacheEnabled(true); + v.buildDrawingCache(); + } else { + v.setDrawingCacheEnabled(false); + v.destroyDrawingCache(); + v.setBackgroundDrawable(null); + } + } + } + } + +} diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java index b1a30d9e0407..1b6daa57c7c2 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 android.animation.LayoutTransition; import android.content.Context; import android.content.res.Configuration; import android.database.DataSetObserver; +import android.graphics.Canvas; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; @@ -40,6 +41,7 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper private RecentsCallback mCallback; protected int mLastScrollPosition; private SwipeHelper mSwipeHelper; + private RecentsScrollViewPerformanceHelper mPerformanceHelper; private OnLongClickListener mOnLongClick = new OnLongClickListener() { public boolean onLongClick(View v) { @@ -49,15 +51,13 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper } }; - public RecentsVerticalScrollView(Context context) { - this(context, null); - } - public RecentsVerticalScrollView(Context context, AttributeSet attrs) { super(context, attrs, 0); float densityScale = getResources().getDisplayMetrics().density; float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop); + + mPerformanceHelper = RecentsScrollViewPerformanceHelper.create(context, attrs, this, true); } private int scrollPositionOfMostRecent() { @@ -77,11 +77,15 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper } final View view = mAdapter.getView(i, old, mLinearLayout); + if (mPerformanceHelper != null) { + mPerformanceHelper.addViewCallback(view); + } + if (old == null) { view.setClickable(true); view.setOnLongClickListener(mOnLongClick); - final View thumbnail = getChildContentView(view); + final View thumbnail = view.findViewById(R.id.app_thumbnail); // thumbnail is set to clickable in the layout file thumbnail.setOnClickListener(new OnClickListener() { public void onClick(View v) { @@ -155,7 +159,60 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper } public View getChildContentView(View v) { - return v.findViewById(R.id.app_thumbnail); + return v.findViewById(R.id.recent_item); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (mPerformanceHelper != null) { + mPerformanceHelper.onLayoutCallback(); + } + } + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + + if (mPerformanceHelper != null) { + int paddingLeft = mPaddingLeft; + final boolean offsetRequired = isPaddingOffsetRequired(); + if (offsetRequired) { + paddingLeft += getLeftPaddingOffset(); + } + + int left = mScrollX + paddingLeft; + int right = left + mRight - mLeft - mPaddingRight - paddingLeft; + int top = mScrollY + getFadeTop(offsetRequired); + int bottom = top + getFadeHeight(offsetRequired); + + if (offsetRequired) { + right += getRightPaddingOffset(); + bottom += getBottomPaddingOffset(); + } + mPerformanceHelper.drawCallback(canvas, + left, right, top, bottom, mScrollX, mScrollY, + getTopFadingEdgeStrength(), getBottomFadingEdgeStrength(), + 0, 0); + } + } + + @Override + public int getVerticalFadingEdgeLength() { + if (mPerformanceHelper != null) { + return mPerformanceHelper.getVerticalFadingEdgeLengthCallback(); + } else { + return super.getVerticalFadingEdgeLength(); + } + } + + @Override + public int getHorizontalFadingEdgeLength() { + if (mPerformanceHelper != null) { + return mPerformanceHelper.getHorizontalFadingEdgeLengthCallback(); + } else { + return super.getHorizontalFadingEdgeLength(); + } } @Override @@ -169,6 +226,14 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper } @Override + public void onAttachedToWindow() { + if (mPerformanceHelper != null) { + mPerformanceHelper.onAttachedToWindowCallback( + mCallback, mLinearLayout, isHardwareAccelerated()); + } + } + + @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); float densityScale = getResources().getDisplayMetrics().density; @@ -208,6 +273,12 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper }); } + public void onRecentsVisibilityChanged() { + if (mPerformanceHelper != null) { + mPerformanceHelper.updateShowBackground(); + } + } + @Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); @@ -236,6 +307,9 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper @Override public void setLayoutTransition(LayoutTransition transition) { + if (mPerformanceHelper != null) { + mPerformanceHelper.setLayoutTransitionCallback(transition); + } // The layout transition applies to our embedded LinearLayout mLinearLayout.setLayoutTransition(transition); } 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 e3ea0de5d606..7868626f81f6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -380,7 +380,7 @@ public class PhoneStatusBar extends StatusBar { } protected WindowManager.LayoutParams getRecentsLayoutParams(LayoutParams layoutParams) { - boolean translucent = false; + boolean opaque = false; WindowManager.LayoutParams lp = new WindowManager.LayoutParams( layoutParams.width, layoutParams.height, @@ -388,7 +388,7 @@ public class PhoneStatusBar extends StatusBar { WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - (translucent ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT)); + (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT)); if (ActivityManager.isHighEndGfx(mDisplay)) { lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; } |