am 185a251b: Merge "Improve Recent Apps scrolling performance"
* commit '185a251b08104a2f19f642d9492e75dd11680dd6':
Improve Recent Apps scrolling performance
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 16008a3..42db77e 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="@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_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_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"
+ />
- <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"
- />
-
-</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 20ef7cf..f84cc19 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 c0fce71..f6b72d4 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"
+ android:layout_width="match_parent">
+
+ <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>
+
+ <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>
- <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"
- />
+ <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_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"
- />
+ <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"
+ />
- <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"
+ />
- <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 c680b8e..dd25cf9 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 5306508..8dab2e6 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 3919685..656c7c1 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 54c25fa..03b17e9 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 0000000..3e2ec59
--- /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 d7d7817..4ac89b2 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 e7ed052..6cfbc1b 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -33,20 +33,19 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
// 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 @@
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 @@
// 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 5609ead..2de4185 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 @@
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 8da2db6..7ad7484 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.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 @@
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 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 @@
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 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 @@
}
@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 void onRecentsVisibilityChanged() {
+ if (mPerformanceHelper != null) {
+ mPerformanceHelper.updateShowBackground();
+ }
+ }
+
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
@@ -220,6 +291,9 @@
@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 d8b086b..0000000
--- 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 9cc2c29..233ed6c 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.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.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 @@
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 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 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 @@
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 @@
scrollView.setCallback(this);
}
else {
- throw new IllegalArgumentException("missing RecentsListView/RecentsScrollView");
+ throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView");
}
@@ -382,6 +389,14 @@
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 0000000..b7e656e
--- /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 b1a30d9..1b6daa5 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.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 @@
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 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 @@
}
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 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 @@
}
@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 void onRecentsVisibilityChanged() {
+ if (mPerformanceHelper != null) {
+ mPerformanceHelper.updateShowBackground();
+ }
+ }
+
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
@@ -236,6 +307,9 @@
@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 e3ea0de..7868626 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 @@
}
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 @@
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;
}