summaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
authorJim Miller <jaggies@google.com>2011-05-18 17:49:32 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-05-18 17:49:32 -0700
commit7a1eb5cf961b6ceaa54295f37843b47b73baa8d8 (patch)
tree521e740fe3e3c5e7d1eda8d51cf723d5863c27e2 /packages
parent8904c3d814b5959b17a0523177f4142db6a18f1e (diff)
parent9f0f0e0e3100caec459a5b5ef836317844c83b3f (diff)
downloadframeworks_base-7a1eb5cf961b6ceaa54295f37843b47b73baa8d8.zip
frameworks_base-7a1eb5cf961b6ceaa54295f37843b47b73baa8d8.tar.gz
frameworks_base-7a1eb5cf961b6ceaa54295f37843b47b73baa8d8.tar.bz2
Merge "First pass at integrating new ScrollView-based recents panel. - added layout transitions - now calls removeTask() for selected activity."
Diffstat (limited to 'packages')
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_bg_protect_tile.pngbin0 -> 7927 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_blue_glow.9.pngbin0 -> 9784 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_callout_line.pngbin0 -> 114 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg.pngbin0 -> 3981 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_bg_protect_tile.pngbin0 -> 7927 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_blue_glow.9.pngbin0 -> 9784 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_callout_line.pngbin0 -> 114 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg.pngbin0 -> 3981 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_press.pngbin0 -> 2056 bytes
-rw-r--r--packages/SystemUI/res/layout-land/status_bar_recent_item.xml79
-rw-r--r--packages/SystemUI/res/layout-land/status_bar_recent_panel.xml84
-rw-r--r--packages/SystemUI/res/layout-large/status_bar_recent_item.xml8
-rw-r--r--packages/SystemUI/res/layout-large/status_bar_recent_panel.xml45
-rw-r--r--packages/SystemUI/res/layout/status_bar_recent_item.xml90
-rw-r--r--packages/SystemUI/res/layout/status_bar_recent_panel.xml84
-rw-r--r--packages/SystemUI/res/values-land/dimens.xml16
-rw-r--r--packages/SystemUI/res/values-large/dimens.xml26
-rw-r--r--packages/SystemUI/res/values/dimens.xml14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/Choreographer.java131
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java307
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsListView.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java)294
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java309
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsActivity.java (renamed from packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsActivity.java)2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsCarouselView.java (renamed from packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsCarouselView.java)2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java11
27 files changed, 1387 insertions, 237 deletions
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-hdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..87c7be6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-hdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..4f4ae78
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-hdpi/recents_callout_line.png
new file mode 100644
index 0000000..5f4c035
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..87a67c9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-mdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..87c7be6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-mdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..4f4ae78
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-mdpi/recents_callout_line.png
new file mode 100644
index 0000000..5f4c035
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..87a67c9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..a1c39e6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
new file mode 100644
index 0000000..ce72f04
--- /dev/null
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+
+<!-- android:background="@drawable/status_bar_closed_default_background" -->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="@dimen/status_bar_recents_thumbnail_view_width">
+
+ <ImageView android:id="@+id/app_thumbnail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
+ android:scaleType="center"
+ android:background="@drawable/recents_thumbnail_bg_selector"
+ />
+
+ <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_thumbnail_border_width"
+ android:layout_marginTop="@dimen/status_bar_recents_thumbnail_border_height"
+ 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="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/status_bar_recents_thumbnail_border_width"
+ 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/status_bar_recents_thumbnail_border_width"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ />
+
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
new file mode 100644
index 0000000..75f5ee4
--- /dev/null
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<com.android.systemui.recent.RecentsPanelView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/recents_root"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content">
+
+ <FrameLayout
+ android:id="@+id/recents_bg_protect"
+ android:background="@drawable/recents_bg_protect_tile"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="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_gravity="bottom|right"
+ android:background="@drawable/recents_blue_glow"
+ android:orientation="horizontal"
+ android:clipToPadding="false"
+ android:clipChildren="false"
+ >
+ <com.android.systemui.recent.RecentsHorizontalScrollView android:id="@+id/recents_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
+ android:divider="@null"
+ android:stackFromBottom="true"
+ android:fadingEdge="horizontal"
+ android:scrollbars="none"
+ android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
+ android:listSelector="@drawable/recents_thumbnail_bg_selector"
+ android:layout_gravity="bottom|left"
+ android:orientation="horizontal"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+
+ <LinearLayout android:id="@+id/recents_linear_layout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+ </LinearLayout>
+
+ </com.android.systemui.recent.RecentsHorizontalScrollView>
+
+ </LinearLayout>
+
+ </FrameLayout>
+
+ <View android:id="@+id/recents_dismiss_button"
+ android:layout_width="80px"
+ android:layout_height="@*android:dimen/status_bar_height"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:background="@drawable/ic_sysbar_back_ime"
+ />
+
+</com.android.systemui.recent.RecentsPanelView>
diff --git a/packages/SystemUI/res/layout-large/status_bar_recent_item.xml b/packages/SystemUI/res/layout-large/status_bar_recent_item.xml
index 3f172e6..cd42d7e 100644
--- a/packages/SystemUI/res/layout-large/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-large/status_bar_recent_item.xml
@@ -60,9 +60,9 @@
<TextView android:id="@+id/app_label"
android:layout_width="97dip"
android:layout_height="wrap_content"
- android:textSize="18dip"
+ android:textSize="@dimen/status_bar_recents_app_description_text_size"
android:fadingEdge="horizontal"
- android:fadingEdgeLength="10dip"
+ android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
android:scrollHorizontally="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
@@ -75,9 +75,9 @@
<TextView android:id="@+id/app_description"
android:layout_width="97dip"
android:layout_height="wrap_content"
- android:textSize="18dip"
+ android:textSize="@dimen/status_bar_recents_app_description_text_size"
android:fadingEdge="horizontal"
- android:fadingEdgeLength="10dip"
+ android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
android:scrollHorizontally="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
diff --git a/packages/SystemUI/res/layout-large/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-large/status_bar_recent_panel.xml
index f019e2d..75fdc67 100644
--- a/packages/SystemUI/res/layout-large/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-large/status_bar_recent_panel.xml
@@ -18,32 +18,23 @@
*/
-->
-<com.android.systemui.statusbar.tablet.RecentAppsPanel
+<com.android.systemui.recent.RecentsPanelView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recents_root"
android:layout_height="match_parent"
- android:layout_width="wrap_content">
-
- <CheckBox android:id="@+id/recents_compat_mode"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentRight="true"
- android:layout_marginLeft="16dp"
- android:layout_marginBottom="@*android:dimen/status_bar_height"
- android:background="@drawable/hd"
- android:button="@null"
- />
+ android:layout_width="wrap_content"
+ android:clipToPadding="false"
+ android:clipChildren="false">
<FrameLayout
android:id="@+id/recents_bg_protect"
android:background="@drawable/recents_bg_protect_tile"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_toLeftOf="@id/recents_compat_mode"
android:layout_alignParentBottom="true"
android:paddingBottom="@*android:dimen/status_bar_height"
- android:clipToPadding="false">
+ android:clipToPadding="false"
+ android:clipChildren="false">
<LinearLayout android:id="@+id/recents_glow"
android:layout_width="wrap_content"
@@ -52,20 +43,32 @@
android:layout_gravity="bottom"
android:background="@drawable/recents_blue_glow"
android:orientation="horizontal"
+ android:clipToPadding="false"
+ android:clipChildren="false"
>
-
- <ListView android:id="@+id/recents_container"
+ <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container"
android:layout_width="@dimen/status_bar_recents_width"
android:layout_height="wrap_content"
- android:layout_marginRight="100dip"
+ android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
android:divider="@null"
- android:scrollingCache="true"
android:stackFromBottom="true"
android:fadingEdge="vertical"
android:scrollbars="none"
android:fadingEdgeLength="20dip"
+ android:layout_gravity="bottom|left"
android:listSelector="@drawable/recents_thumbnail_bg_selector"
- />
+ android:clipToPadding="false"
+ android:clipChildren="false">
+
+ <LinearLayout android:id="@+id/recents_linear_layout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+ </LinearLayout>
+
+ </com.android.systemui.recent.RecentsVerticalScrollView>
</LinearLayout>
@@ -79,4 +82,4 @@
android:background="@drawable/ic_sysbar_back_ime"
/>
-</com.android.systemui.statusbar.tablet.RecentAppsPanel>
+</com.android.systemui.recent.RecentsPanelView>
diff --git a/packages/SystemUI/res/layout/status_bar_recent_item.xml b/packages/SystemUI/res/layout/status_bar_recent_item.xml
new file mode 100644
index 0000000..cd42d7e
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_recent_item.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+
+<!-- android:background="@drawable/status_bar_closed_default_background" -->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="@dimen/status_bar_recents_thumbnail_view_width">
+
+ <ImageView 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"
+ />
+
+ <ImageView android:id="@+id/app_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginLeft="131dip"
+ android:layout_marginTop="13dip"
+ 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="97dip"
+ android:layout_height="1dip"
+ android:layout_alignParentTop="true"
+ android:layout_marginTop="61dip"
+ android:layout_alignParentLeft="true"
+ android:layout_marginLeft="16dip"
+ android:layout_toLeftOf="@id/app_thumbnail"
+ android:layout_marginRight="3dip"
+ android:background="@drawable/recents_callout_line"
+ />
+
+ <TextView android:id="@+id/app_label"
+ android:layout_width="97dip"
+ 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_alignParentTop="true"
+ android:layout_marginLeft="16dip"
+ android:layout_marginTop="32dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ />
+
+ <TextView android:id="@+id/app_description"
+ android:layout_width="97dip"
+ 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_alignParentTop="true"
+ android:layout_marginLeft="16dip"
+ android:layout_marginTop="61dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ />
+
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_recent_panel.xml b/packages/SystemUI/res/layout/status_bar_recent_panel.xml
new file mode 100644
index 0000000..703cbc1
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_recent_panel.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<com.android.systemui.recent.RecentsPanelView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/recents_root"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content">
+
+ <FrameLayout
+ android:id="@+id/recents_bg_protect"
+ android:background="@drawable/recents_bg_protect_tile"
+ android:layout_width="wrap_content"
+ 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_marginBottom="-49dip"
+ android:layout_gravity="bottom"
+ android:background="@drawable/recents_blue_glow"
+ android:orientation="horizontal"
+ android:clipToPadding="false"
+ android:clipChildren="false"
+ >
+ <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container"
+ android:layout_width="@dimen/status_bar_recents_width"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
+ android:divider="@null"
+ android:stackFromBottom="true"
+ android:fadingEdge="vertical"
+ android:scrollbars="none"
+ android:fadingEdgeLength="20dip"
+ android:listSelector="@drawable/recents_thumbnail_bg_selector"
+ android:layout_gravity="bottom|left"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+
+ <LinearLayout android:id="@+id/recents_linear_layout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+ </LinearLayout>
+
+ </com.android.systemui.recent.RecentsVerticalScrollView>
+
+
+ </LinearLayout>
+
+ </FrameLayout>
+
+ <View android:id="@+id/recents_dismiss_button"
+ android:layout_width="80px"
+ android:layout_height="@*android:dimen/status_bar_height"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:background="@drawable/ic_sysbar_back_ime"
+ />
+
+</com.android.systemui.recent.RecentsPanelView>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index bcc8da1..6f1453e 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -18,4 +18,20 @@
<resources>
<!-- thickness (width) of the navigation bar on phones that require it -->
<dimen name="navigation_bar_size">42dp</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">0dp</dimen>
+ <!-- Width of scrollable area in recents -->
+ <dimen name="status_bar_recents_width">128dp</dimen>
+ <!-- Thumbnail border width -->
+ <dimen name="status_bar_recents_thumbnail_border_width">8dp</dimen>
+ <!-- Thumbnail border height -->
+ <dimen name="status_bar_recents_thumbnail_border_height">12dp</dimen>
+ <!-- Padding for text descriptions -->
+ <dimen name="status_bar_recents_text_description_padding">8dp</dimen>
+ <!-- Margin between recents container and glow on the right -->
+ <dimen name="status_bar_recents_right_glow_margin">0dip</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-large/dimens.xml b/packages/SystemUI/res/values-large/dimens.xml
index 9d89e21..f8a4a1c 100644
--- a/packages/SystemUI/res/values-large/dimens.xml
+++ b/packages/SystemUI/res/values-large/dimens.xml
@@ -22,6 +22,32 @@
<dimen name="status_bar_panel_bottom_offset">36dp</dimen>
<!-- gap on either side of status bar notification icons -->
<dimen name="status_bar_icon_padding">8dp</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">110dp</dimen>
+ <!-- Upper width limit for application icon -->
+ <dimen name="status_bar_recents_thumbnail_max_width">64dp</dimen>
+ <!-- Upper height limit for application icon -->
+ <dimen name="status_bar_recents_thumbnail_max_height">64dp</dimen>
+ <!-- Width of scrollable area in recents -->
+ <dimen name="status_bar_recents_width">356dp</dimen>
+ <!-- Thumbnail border width -->
+ <dimen name="status_bar_recents_thumbnail_border_width">12dp</dimen>
+ <!-- Thumbnail border height -->
+ <dimen name="status_bar_recents_thumbnail_border_height">12dp</dimen>
+ <!-- Padding for text descriptions -->
+ <dimen name="status_bar_recents_text_description_padding">8dp</dimen>
+ <!-- Size of application label text -->
+ <dimen name="status_bar_recents_app_label_text_size">18dip</dimen>
+ <!-- Size of application description text -->
+ <dimen name="status_bar_recents_app_description_text_size">18dip</dimen>
+ <!-- Size of fading edge for scroll effect -->
+ <dimen name="status_bar_recents_fading_edge_length">20dip</dimen>
+ <!-- Margin between recents container and glow on the right -->
+ <dimen name="status_bar_recents_right_glow_margin">100dip</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a2577cb..657dc46 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -30,6 +30,20 @@
<dimen name="status_bar_recents_thumbnail_max_height">64dp</dimen>
<!-- Width of scrollable area in recents -->
<dimen name="status_bar_recents_width">356dp</dimen>
+ <!-- Thumbnail border width -->
+ <dimen name="status_bar_recents_thumbnail_border_width">12dp</dimen>
+ <!-- Thumbnail border height -->
+ <dimen name="status_bar_recents_thumbnail_border_height">12dp</dimen>
+ <!-- Padding for text descriptions -->
+ <dimen name="status_bar_recents_text_description_padding">8dp</dimen>
+ <!-- Size of application label text -->
+ <dimen name="status_bar_recents_app_label_text_size">18dip</dimen>
+ <!-- Size of application description text -->
+ <dimen name="status_bar_recents_app_description_text_size">18dip</dimen>
+ <!-- Size of fading edge for scroll effect -->
+ <dimen name="status_bar_recents_fading_edge_length">20dip</dimen>
+ <!-- Margin between recents container and glow on the right -->
+ <dimen name="status_bar_recents_right_glow_margin">100dip</dimen>
<!-- thickness (height) of the navigation bar on phones that require it -->
<dimen name="navigation_bar_size">42dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
new file mode 100644
index 0000000..b876075
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
@@ -0,0 +1,131 @@
+/*
+ * 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.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.util.Log;
+import android.util.Slog;
+import android.view.View;
+
+/* package */ class Choreographer implements Animator.AnimatorListener {
+ // should group this into a multi-property animation
+ private static final int OPEN_DURATION = 136;
+ private static final int CLOSE_DURATION = 250;
+ private static final String TAG = RecentsPanelView.TAG;
+ private static final boolean DEBUG = RecentsPanelView.DEBUG;
+
+ boolean mVisible;
+ int mPanelHeight;
+ View mRootView;
+ View mScrimView;
+ View mContentView;
+ AnimatorSet mContentAnim;
+
+ // the panel will start to appear this many px from the end
+ final int HYPERSPACE_OFFRAMP = 200;
+
+ public Choreographer(View root, View scrim, View content) {
+ mRootView = root;
+ mScrimView = scrim;
+ mContentView = content;
+ }
+
+ void createAnimation(boolean appearing) {
+ float start, end;
+
+ if (RecentsPanelView.DEBUG) Log.e(TAG, "createAnimation()", new Exception());
+
+ // 0: on-screen
+ // height: off-screen
+ float y = mContentView.getTranslationY();
+ if (appearing) {
+ // we want to go from near-the-top to the top, unless we're half-open in the right
+ // general vicinity
+ start = (y < HYPERSPACE_OFFRAMP) ? y : HYPERSPACE_OFFRAMP;
+ end = 0;
+ } else {
+ start = y;
+ end = y + HYPERSPACE_OFFRAMP;
+ }
+
+ Animator posAnim = ObjectAnimator.ofFloat(mContentView, "translationY",
+ start, end);
+ posAnim.setInterpolator(appearing
+ ? new android.view.animation.DecelerateInterpolator(2.5f)
+ : new android.view.animation.AccelerateInterpolator(2.5f));
+
+ Animator glowAnim = ObjectAnimator.ofFloat(mContentView, "alpha",
+ mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
+ glowAnim.setInterpolator(appearing
+ ? new android.view.animation.AccelerateInterpolator(1.0f)
+ : new android.view.animation.DecelerateInterpolator(1.0f));
+
+ Animator bgAnim = ObjectAnimator.ofInt(mScrimView.getBackground(),
+ "alpha", appearing ? 0 : 255, appearing ? 255 : 0);
+
+ mContentAnim = new AnimatorSet();
+ mContentAnim
+ .play(bgAnim)
+ .with(glowAnim)
+ .with(posAnim);
+ mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
+ mContentAnim.addListener(this);
+ }
+
+ void startAnimation(boolean appearing) {
+ if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
+
+ createAnimation(appearing);
+
+ mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ mContentAnim.start();
+
+ mVisible = appearing;
+ }
+
+ void jumpTo(boolean appearing) {
+ mContentView.setTranslationY(appearing ? 0 : mPanelHeight);
+ }
+
+ public void setPanelHeight(int h) {
+ if (DEBUG) Slog.d(TAG, "panelHeight=" + h);
+ mPanelHeight = h;
+ }
+
+ public void onAnimationCancel(Animator animation) {
+ if (DEBUG) Slog.d(TAG, "onAnimationCancel");
+ // force this to zero so we close the window
+ mVisible = false;
+ }
+
+ public void onAnimationEnd(Animator animation) {
+ if (DEBUG) Slog.d(TAG, "onAnimationEnd");
+ if (!mVisible) {
+ mRootView.setVisibility(View.GONE);
+ }
+ mContentView.setLayerType(View.LAYER_TYPE_NONE, null);
+ mContentAnim = null;
+ }
+
+ public void onAnimationRepeat(Animator animation) {
+ }
+
+ public void onAnimationStart(Animator animation) {
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java
new file mode 100644
index 0000000..5d29e2a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java
@@ -0,0 +1,30 @@
+/*
+ * 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.view.View;
+
+public interface RecentsCallback {
+ static final int SWIPE_LEFT = 0;
+ static final int SWIPE_RIGHT = 1;
+ static final int SWIPE_UP = 2;
+ static final int SWIPE_DOWN = 3;
+
+ void handleOnClick(View selectedView);
+ void handleSwipe(View selectedView, int direction);
+ void handleLongPress(View selectedView);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
new file mode 100644
index 0000000..194c9d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -0,0 +1,307 @@
+/*
+ * 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 com.android.systemui.recent.RecentsPanelView.ActvityDescriptionAdapter;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.LayoutTransition;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.Context;
+import android.database.DataSetObserver;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+import android.widget.HorizontalScrollView;
+import android.widget.LinearLayout;
+
+import com.android.systemui.R;
+
+public class RecentsHorizontalScrollView extends HorizontalScrollView
+ implements View.OnClickListener, View.OnTouchListener {
+ private static final float FADE_CONSTANT = 0.5f;
+ private static final int SNAP_BACK_DURATION = 250;
+ private static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it
+ private static final String TAG = RecentsPanelView.TAG;
+ private static final float THRESHHOLD = 50;
+ private static final boolean DEBUG_INVALIDATE = false;
+ private LinearLayout mLinearLayout;
+ private ActvityDescriptionAdapter mAdapter;
+ private RecentsCallback mCallback;
+ protected int mLastScrollPosition;
+ private View mCurrentView;
+ private float mLastY;
+ private boolean mDragging;
+ private VelocityTracker mVelocityTracker;
+
+ public RecentsHorizontalScrollView(Context context) {
+ this(context, null);
+ }
+
+ public RecentsHorizontalScrollView(Context context, AttributeSet attrs) {
+ super(context, attrs, 0);
+ }
+
+ private int scrollPositionOfMostRecent() {
+ return mLinearLayout.getWidth() - getWidth();
+ }
+
+ public void update() {
+ mLinearLayout.removeAllViews();
+ for (int i = 0; i < mAdapter.getCount(); i++) {
+ View view = mAdapter.getView(i, null, mLinearLayout);
+ view.setClickable(true);
+ view.setOnClickListener(this);
+ view.setOnTouchListener(this);
+ mLinearLayout.addView(view);
+ }
+ // Scroll to end after layout.
+ post(new Runnable() {
+ public void run() {
+ mLastScrollPosition = scrollPositionOfMostRecent();
+ scrollTo(mLastScrollPosition, 0);
+ }
+ });
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ mVelocityTracker.addMovement(ev);
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mDragging = false;
+ mLastY = ev.getY();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ float delta = ev.getY() - mLastY;
+ if (Math.abs(delta) > THRESHHOLD) {
+ mDragging = true;
+ }
+ break;
+
+ case MotionEvent.ACTION_UP:
+ mDragging = false;
+ break;
+ }
+ return mDragging ? true : super.onInterceptTouchEvent(ev);
+ }
+
+ private float getAlphaForOffset(View view, float thumbHeight) {
+ final float fadeHeight = FADE_CONSTANT * thumbHeight;
+ float result = 1.0f;
+ if (view.getY() >= thumbHeight) {
+ result = 1.0f - (view.getY() - thumbHeight) / fadeHeight;
+ } else if (view.getY() < 0.0f) {
+ result = 1.0f + (thumbHeight + view.getY()) / fadeHeight;
+ }
+ return result;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (!mDragging) {
+ return super.onTouchEvent(ev);
+ }
+
+ mVelocityTracker.addMovement(ev);
+
+ final View animView = mCurrentView;
+ // TODO: Cache thumbnail
+ final View thumb = animView.findViewById(R.id.app_thumbnail);
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_MOVE:
+ if (animView != null) {
+ final float delta = ev.getY() - mLastY;
+ animView.setY(animView.getY() + delta);
+ animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight()));
+ invalidateGlobalRegion(animView);
+ }
+ mLastY = ev.getY();
+ break;
+
+ case MotionEvent.ACTION_UP:
+ final ObjectAnimator anim;
+ if (animView != null) {
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, 10000);
+ final float velocityX = velocityTracker.getXVelocity();
+ final float velocityY = velocityTracker.getYVelocity();
+ final float curY = animView.getY();
+ final float newY = (velocityY >= 0.0f ? 1 : -1) * animView.getHeight();
+
+ if (Math.abs(velocityY) > Math.abs(velocityX)
+ && Math.abs(velocityY) > ESCAPE_VELOCITY
+ && (velocityY >= 0.0f) == (animView.getY() >= 0)) {
+ final long duration =
+ (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY));
+ anim = ObjectAnimator.ofFloat(animView, "y", curY, newY);
+ anim.setInterpolator(new LinearInterpolator());
+ final int swipeDirection = animView.getY() >= 0.0f ?
+ RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT;
+ anim.addListener(new AnimatorListener() {
+ public void onAnimationStart(Animator animation) {
+ }
+ public void onAnimationRepeat(Animator animation) {
+ }
+ public void onAnimationEnd(Animator animation) {
+ mLinearLayout.removeView(mCurrentView);
+ mCallback.handleSwipe(animView, swipeDirection);
+ }
+ public void onAnimationCancel(Animator animation) {
+ mLinearLayout.removeView(mCurrentView);
+ mCallback.handleSwipe(animView, swipeDirection);
+ }
+ });
+ anim.setDuration(duration);
+ } else { // Animate back to position
+ final long duration = Math.abs(velocityY) > 0.0f ?
+ (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY))
+ : SNAP_BACK_DURATION;
+ anim = ObjectAnimator.ofFloat(animView, "y", animView.getY(), 0.0f);
+ anim.setInterpolator(new DecelerateInterpolator(2.0f));
+ anim.setDuration(duration);
+ }
+
+ anim.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight()));
+ invalidateGlobalRegion(animView);
+ }
+ });
+ anim.start();
+ }
+
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ break;
+ }
+ return true;
+ }
+
+ void invalidateGlobalRegion(View view) {
+ RectF childBounds
+ = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
+ childBounds.offset(view.getX(), view.getY());
+ if (DEBUG_INVALIDATE) Log.v(TAG, "-------------");
+ while (view.getParent() != null && view.getParent() instanceof View) {
+ view = (View) view.getParent();
+ view.getMatrix().mapRect(childBounds);
+ view.invalidate((int) Math.floor(childBounds.left),
+ (int) Math.floor(childBounds.top),
+ (int) Math.ceil(childBounds.right),
+ (int) Math.ceil(childBounds.bottom));
+ if (DEBUG_INVALIDATE) {
+ Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left)
+ + "," + (int) Math.floor(childBounds.top)
+ + "," + (int) Math.ceil(childBounds.right)
+ + "," + (int) Math.ceil(childBounds.bottom));
+ }
+ }
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ LayoutInflater inflater = (LayoutInflater)
+ mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ setScrollbarFadingEnabled(true);
+
+ mLinearLayout = (LinearLayout) findViewById(R.id.recents_linear_layout);
+
+ final int leftPadding = mContext.getResources()
+ .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin);
+ setOverScrollEffectPadding(leftPadding, 0);
+ }
+
+ private void setOverScrollEffectPadding(int leftPadding, int i) {
+ // TODO Add to RecentsHorizontalScrollView
+ }
+
+ @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.
+ mLastScrollPosition = scrollPositionOfMostRecent();
+
+ // This has to happen post-layout, so run it "in the future"
+ post(new Runnable() {
+ public void run() {
+ scrollTo(0, mLastScrollPosition);
+ }
+ });
+ }
+
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+ // scroll to bottom after reloading
+ if (visibility == View.VISIBLE && changedView == this) {
+ post(new Runnable() {
+ public void run() {
+ update();
+ }
+ });
+ }
+ }
+
+ public void setAdapter(ActvityDescriptionAdapter adapter) {
+ mAdapter = adapter;
+ mAdapter.registerDataSetObserver(new DataSetObserver() {
+ public void onChanged() {
+ update();
+ }
+
+ public void onInvalidated() {
+ update();
+ }
+ });
+ }
+
+ @Override
+ public void setLayoutTransition(LayoutTransition transition) {
+ // The layout transition applies to our embedded LinearLayout
+ mLinearLayout.setLayoutTransition(transition);
+ }
+
+ public void onClick(View view) {
+ mCallback.handleOnClick(view);
+ }
+
+ public void setCallback(RecentsCallback callback) {
+ mCallback = callback;
+ }
+
+ public boolean onTouch(View v, MotionEvent event) {
+ mCurrentView = v;
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsListView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsListView.java
new file mode 100644
index 0000000..d8b086b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsListView.java
@@ -0,0 +1,92 @@
+/*
+ * 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/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index d0e6551..e2b3446 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.tablet;
+package com.android.systemui.recent;
import java.util.ArrayList;
import java.util.List;
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
+import android.animation.LayoutTransition;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -43,25 +41,25 @@ import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
-import android.widget.CheckBox;
import android.widget.ImageView;
-import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.statusbar.tablet.StatusBarPanel;
+import com.android.systemui.statusbar.tablet.TabletStatusBar;
-public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, OnItemClickListener {
+public class RecentsPanelView extends RelativeLayout
+ implements OnItemClickListener, RecentsCallback, StatusBarPanel {
private static final int GLOW_PADDING = 15;
- private static final String TAG = "RecentAppsPanel";
- private static final boolean DEBUG = TabletStatusBar.DEBUG;
+ static final String TAG = "RecentsListView";
+ static final boolean DEBUG = TabletStatusBar.DEBUG;
private static final int DISPLAY_TASKS = 20;
private static final int MAX_TASKS = DISPLAY_TASKS + 1; // allow extra for non-apps
private TabletStatusBar mBar;
@@ -69,17 +67,15 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
private int mIconDpi;
private View mRecentsScrim;
private View mRecentsGlowView;
- private ListView mRecentsContainer;
- private CheckBox mCompatMode;
+ private View mRecentsContainer;
private Bitmap mGlowBitmap;
private boolean mShowing;
private Choreographer mChoreo;
private View mRecentsDismissButton;
private ActvityDescriptionAdapter mListAdapter;
- protected int mLastVisibleItem;
- static class ActivityDescription {
- int id;
+ /* package */ final static class ActivityDescription {
+ int taskId; // application task id for curating apps
Bitmap thumbnail; // generated by Activity.onCreateThumbnail()
Drawable icon; // application package icon
String label; // application package label
@@ -98,18 +94,18 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
label = _label;
description = _desc;
intent = _intent;
- id = _id;
+ taskId = _id;
position = _pos;
packageName = _packageName;
}
};
/* package */ final static class ViewHolder {
- private ImageView thumbnailView;
- private ImageView iconView;
- private TextView labelView;
- private TextView descriptionView;
- private ActivityDescription activityDescription;
+ ImageView thumbnailView;
+ ImageView iconView;
+ TextView labelView;
+ TextView descriptionView;
+ ActivityDescription activityDescription;
}
/* package */ final class ActvityDescriptionAdapter extends BaseAdapter {
@@ -205,120 +201,15 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
return mShowing;
}
- private static class Choreographer implements Animator.AnimatorListener {
- // should group this into a multi-property animation
- private static final int OPEN_DURATION = 136;
- private static final int CLOSE_DURATION = 250;
-
- boolean mVisible;
- int mPanelHeight;
- View mRootView;
- View mScrimView;
- View mContentView;
- AnimatorSet mContentAnim;
-
- // the panel will start to appear this many px from the end
- final int HYPERSPACE_OFFRAMP = 200;
-
- public Choreographer(View root, View scrim, View content) {
- mRootView = root;
- mScrimView = scrim;
- mContentView = content;
- }
-
- void createAnimation(boolean appearing) {
- float start, end;
-
- if (DEBUG) Log.e(TAG, "createAnimation()", new Exception());
-
- // 0: on-screen
- // height: off-screen
- float y = mContentView.getTranslationY();
- if (appearing) {
- // we want to go from near-the-top to the top, unless we're half-open in the right
- // general vicinity
- start = (y < HYPERSPACE_OFFRAMP) ? y : HYPERSPACE_OFFRAMP;
- end = 0;
- } else {
- start = y;
- end = y + HYPERSPACE_OFFRAMP;
- }
-
- Animator posAnim = ObjectAnimator.ofFloat(mContentView, "translationY",
- start, end);
- posAnim.setInterpolator(appearing
- ? new android.view.animation.DecelerateInterpolator(2.5f)
- : new android.view.animation.AccelerateInterpolator(2.5f));
-
- Animator glowAnim = ObjectAnimator.ofFloat(mContentView, "alpha",
- mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
- glowAnim.setInterpolator(appearing
- ? new android.view.animation.AccelerateInterpolator(1.0f)
- : new android.view.animation.DecelerateInterpolator(1.0f));
-
- Animator bgAnim = ObjectAnimator.ofInt(mScrimView.getBackground(),
- "alpha", appearing ? 0 : 255, appearing ? 255 : 0);
-
- mContentAnim = new AnimatorSet();
- mContentAnim
- .play(bgAnim)
- .with(glowAnim)
- .with(posAnim);
- mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
- mContentAnim.addListener(this);
- }
-
- void startAnimation(boolean appearing) {
- if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
-
- createAnimation(appearing);
-
- mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- mContentAnim.start();
-
- mVisible = appearing;
- }
-
- void jumpTo(boolean appearing) {
- mContentView.setTranslationY(appearing ? 0 : mPanelHeight);
- }
-
- public void setPanelHeight(int h) {
- if (DEBUG) Slog.d(TAG, "panelHeight=" + h);
- mPanelHeight = h;
- }
-
- public void onAnimationCancel(Animator animation) {
- if (DEBUG) Slog.d(TAG, "onAnimationCancel");
- // force this to zero so we close the window
- mVisible = false;
- }
-
- public void onAnimationEnd(Animator animation) {
- if (DEBUG) Slog.d(TAG, "onAnimationEnd");
- if (!mVisible) {
- mRootView.setVisibility(View.GONE);
- }
- mContentView.setLayerType(View.LAYER_TYPE_NONE, null);
- mContentAnim = null;
- }
-
- public void onAnimationRepeat(Animator animation) {
- }
-
- public void onAnimationStart(Animator animation) {
- }
- }
-
public void setBar(TabletStatusBar bar) {
mBar = bar;
}
- public RecentAppsPanel(Context context, AttributeSet attrs) {
+ public RecentsPanelView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
- public RecentAppsPanel(Context context, AttributeSet attrs, int defStyle) {
+ public RecentsPanelView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
Resources res = context.getResources();
@@ -330,52 +221,34 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
}
@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.
- int childCount = mRecentsContainer.getChildCount();
- if (childCount > 0) {
- mLastVisibleItem = mRecentsContainer.getFirstVisiblePosition() + childCount - 1;
- View view = mRecentsContainer.getChildAt(childCount - 1);
- final int distanceFromBottom = mRecentsContainer.getHeight() - view.getTop();
- //final int distanceFromBottom = view.getHeight() + BOTTOM_OFFSET;
-
- // This has to happen post-layout, so run it "in the future"
- post(new Runnable() {
- public void run() {
- mRecentsContainer.setSelectionFromTop(mLastVisibleItem,
- mRecentsContainer.getHeight() - distanceFromBottom);
- }
- });
- }
- }
-
- @Override
protected void onFinishInflate() {
super.onFinishInflate();
- LayoutInflater inflater = (LayoutInflater)
mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mRecentsContainer = findViewById(R.id.recents_container);
+ mListAdapter = new ActvityDescriptionAdapter(mContext);
+ if (mRecentsContainer instanceof RecentsListView) {
+ RecentsListView listView = (RecentsListView) mRecentsContainer;
+ listView.setAdapter(mListAdapter);
+ listView.setOnItemClickListener(this);
+ listView.setCallback(this);
+ } else if (mRecentsContainer instanceof RecentsHorizontalScrollView){
+ RecentsHorizontalScrollView scrollView
+ = (RecentsHorizontalScrollView) mRecentsContainer;
+ scrollView.setAdapter(mListAdapter);
+ scrollView.setCallback(this);
+ } else if (mRecentsContainer instanceof RecentsVerticalScrollView){
+ RecentsVerticalScrollView scrollView
+ = (RecentsVerticalScrollView) mRecentsContainer;
+ scrollView.setAdapter(mListAdapter);
+ scrollView.setCallback(this);
+ }
+ else {
+ throw new IllegalArgumentException("missing RecentsListView/RecentsScrollView");
+ }
- mRecentsContainer = (ListView) findViewById(R.id.recents_container);
- mCompatMode = (CheckBox) findViewById(R.id.recents_compat_mode);
- mCompatMode.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- final ActivityManager am = (ActivityManager)
- mContext.getSystemService(Context.ACTIVITY_SERVICE);
- am.setFrontActivityScreenCompatMode(ActivityManager.COMPAT_MODE_TOGGLE);
- hide(true);
- }
- });
- View footer = inflater.inflate(R.layout.status_bar_recent_panel_footer,
- mRecentsContainer, false);
- mRecentsContainer.setScrollbarFadingEnabled(true);
- mRecentsContainer.addFooterView(footer, null, false);
- mRecentsContainer.setAdapter(mListAdapter = new ActvityDescriptionAdapter(mContext));
- mRecentsContainer.setOnItemClickListener(this);
- final int leftPadding = mContext.getResources()
- .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin);
- mRecentsContainer.setOverScrollEffectPadding(leftPadding, 0);
+ final LayoutTransition transitioner = new LayoutTransition();
+ ((ViewGroup)mRecentsContainer).setLayoutTransition(transitioner);
+ createCustomAnimations(transitioner);
mRecentsGlowView = findViewById(R.id.recents_glow);
mRecentsScrim = (View) findViewById(R.id.recents_bg_protect);
@@ -393,17 +266,16 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
}
}
+ private void createCustomAnimations(LayoutTransition transitioner) {
+ transitioner.setDuration(LayoutTransition.DISAPPEARING, 250);
+ }
+
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + changedView + ", " + visibility + ")");
if (visibility == View.VISIBLE && changedView == this) {
refreshApplicationList();
- post(new Runnable() {
- public void run() {
- mRecentsContainer.setSelection(mActivityDescriptions.size() - 1);
- }
- });
}
}
@@ -496,7 +368,7 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
ActivityDescription desc = null;
for (int i = 0; i < mActivityDescriptions.size(); i++) {
ActivityDescription item = mActivityDescriptions.get(i);
- if (item != null && item.id == id) {
+ if (item != null && item.taskId == id) {
desc = item;
break;
}
@@ -504,34 +376,15 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
return desc;
}
- private void updateShownCompatMode() {
- final ActivityManager am = (ActivityManager)
- mContext.getSystemService(Context.ACTIVITY_SERVICE);
- int mode = am.getFrontActivityScreenCompatMode();
- switch (mode) {
- case ActivityManager.COMPAT_MODE_DISABLED:
- mCompatMode.setVisibility(View.VISIBLE);
- mCompatMode.setChecked(true);
- break;
- case ActivityManager.COMPAT_MODE_ENABLED:
- mCompatMode.setVisibility(View.VISIBLE);
- mCompatMode.setChecked(false);
- break;
- default:
- mCompatMode.setVisibility(View.GONE);
- break;
- }
- }
-
private void refreshApplicationList() {
mActivityDescriptions = getRecentTasks();
mListAdapter.notifyDataSetInvalidated();
if (mActivityDescriptions.size() > 0) {
- mLastVisibleItem = mActivityDescriptions.size() - 1; // scroll to bottom after reloading
+ Log.v(TAG, "Showing " + mActivityDescriptions.size() + " apps");
updateUiElements(getResources().getConfiguration());
- updateShownCompatMode();
} else {
// Immediately hide this panel
+ Log.v(TAG, "Nothing to show");
hide(false);
}
}
@@ -546,6 +399,7 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
paint.setAlpha(255);
final int srcWidth = thumbnail.getWidth();
final int srcHeight = thumbnail.getHeight();
+ Log.v(TAG, "Source thumb: " + srcWidth + "x" + srcHeight);
canvas.drawBitmap(thumbnail,
new Rect(0, 0, srcWidth-1, srcHeight-1),
new RectF(GLOW_PADDING,
@@ -563,27 +417,57 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
mRecentsGlowView.setVisibility(items > 0 ? View.VISIBLE : View.GONE);
}
- private void hide(boolean animate) {
+ public void hide(boolean animate) {
if (!animate) {
setVisibility(View.GONE);
}
- mBar.animateCollapse();
+ if (mBar != null) {
+ mBar.animateCollapse();
+ }
}
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ public void handleOnClick(View view) {
ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription;
+ final Context context = view.getContext();
final ActivityManager am = (ActivityManager)
- getContext().getSystemService(Context.ACTIVITY_SERVICE);
- if (ad.id >= 0) {
+ context.getSystemService(Context.ACTIVITY_SERVICE);
+ if (ad.taskId >= 0) {
// This is an active task; it should just go to the foreground.
- am.moveTaskToFront(ad.id, ActivityManager.MOVE_TASK_WITH_HOME);
+ am.moveTaskToFront(ad.taskId, ActivityManager.MOVE_TASK_WITH_HOME);
} else {
Intent intent = ad.intent;
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
| Intent.FLAG_ACTIVITY_TASK_ON_HOME);
if (DEBUG) Log.v(TAG, "Starting activity " + intent);
- getContext().startActivity(intent);
+ context.startActivity(intent);
}
hide(true);
}
+
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ handleOnClick(view);
+ }
+
+ public void handleSwipe(View view, int direction) {
+ ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription;
+ Log.v(TAG, "Jettison " + ad.label);
+ mActivityDescriptions.remove(ad);
+
+ // Handled by widget containers to enable LayoutTransitions properly
+ // mListAdapter.notifyDataSetChanged();
+
+ if (mActivityDescriptions.size() == 0) {
+ hide(false);
+ }
+
+ // Currently, either direction means the same thing, so ignore direction and remove
+ // the task.
+ final ActivityManager am = (ActivityManager)
+ mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ am.removeTask(ad.taskId, 0);
+ }
+
+ public void handleLongPress(View selectedView) {
+ // TODO show context menu : "Remove from list", "Show properties"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
new file mode 100644
index 0000000..54ec6b5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -0,0 +1,309 @@
+/*
+ * 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 com.android.systemui.recent.RecentsPanelView.ActvityDescriptionAdapter;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.LayoutTransition;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.Context;
+import android.database.DataSetObserver;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+
+import com.android.systemui.R;
+
+public class RecentsVerticalScrollView extends ScrollView
+ implements View.OnClickListener, View.OnTouchListener {
+ private static final float FADE_CONSTANT = 0.5f;
+ private static final int SNAP_BACK_DURATION = 250;
+ private static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it
+ private static final String TAG = RecentsPanelView.TAG;
+ private static final float THRESHHOLD = 50;
+ private static final boolean DEBUG_INVALIDATE = false;
+ private LinearLayout mLinearLayout;
+ private ActvityDescriptionAdapter mAdapter;
+ private RecentsCallback mCallback;
+ protected int mLastScrollPosition;
+ private View mCurrentView;
+ private float mLastX;
+ private boolean mDragging;
+ private VelocityTracker mVelocityTracker;
+
+ public RecentsVerticalScrollView(Context context) {
+ this(context, null);
+ }
+
+ public RecentsVerticalScrollView(Context context, AttributeSet attrs) {
+ super(context, attrs, 0);
+ }
+
+ private int scrollPositionOfMostRecent() {
+ return mLinearLayout.getHeight() - getHeight();
+ }
+
+ public void update() {
+ mLinearLayout.removeAllViews();
+ for (int i = 0; i < mAdapter.getCount(); i++) {
+ View view = mAdapter.getView(i, null, mLinearLayout);
+ view.setClickable(true);
+ view.setOnClickListener(this);
+ view.setOnTouchListener(this);
+ mLinearLayout.addView(view);
+ }
+ // Scroll to end after layout.
+ post(new Runnable() {
+ public void run() {
+ mLastScrollPosition = scrollPositionOfMostRecent();
+ scrollTo(0, mLastScrollPosition);
+ }
+ });
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ mVelocityTracker.addMovement(ev);
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mDragging = false;
+ mLastX = ev.getX();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ float delta = ev.getX() - mLastX;
+ Log.v(TAG, "ACTION_MOVE : " + delta);
+ if (Math.abs(delta) > THRESHHOLD) {
+ mDragging = true;
+ }
+ break;
+
+ case MotionEvent.ACTION_UP:
+ mDragging = false;
+ break;
+ }
+ return mDragging ? true : super.onInterceptTouchEvent(ev);
+ }
+
+ private float getAlphaForOffset(View view, float thumbWidth) {
+ final float fadeWidth = FADE_CONSTANT * thumbWidth;
+ float result = 1.0f;
+ if (view.getX() >= thumbWidth) {
+ result = 1.0f - (view.getX() - thumbWidth) / fadeWidth;
+ } else if (view.getX() < 0.0f) {
+ result = 1.0f + (thumbWidth + view.getX()) / fadeWidth;
+ }
+ Log.v(TAG, "FADE AMOUNT: " + result);
+ return result;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (!mDragging) {
+ return super.onTouchEvent(ev);
+ }
+
+ mVelocityTracker.addMovement(ev);
+
+ final View animView = mCurrentView;
+ // TODO: Cache thumbnail
+ final View thumb = animView.findViewById(R.id.app_thumbnail);
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_MOVE:
+ if (animView != null) {
+ final float delta = ev.getX() - mLastX;
+ animView.setX(animView.getX() + delta);
+ animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth()));
+ invalidateGlobalRegion(animView);
+ }
+ mLastX = ev.getX();
+ break;
+
+ case MotionEvent.ACTION_UP:
+ final ObjectAnimator anim;
+ if (animView != null) {
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, 10000);
+ final float velocityX = velocityTracker.getXVelocity();
+ final float velocityY = velocityTracker.getYVelocity();
+ final float curX = animView.getX();
+ final float newX = (velocityX >= 0.0f ? 1 : -1) * animView.getWidth();
+
+ if (Math.abs(velocityX) > Math.abs(velocityY)
+ && Math.abs(velocityX) > ESCAPE_VELOCITY
+ && (velocityX > 0.0f) == (animView.getX() >= 0)) {
+ final long duration =
+ (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX));
+ anim = ObjectAnimator.ofFloat(animView, "x", curX, newX);
+ anim.setInterpolator(new LinearInterpolator());
+ final int swipeDirection = animView.getX() >= 0.0f ?
+ RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT;
+ anim.addListener(new AnimatorListener() {
+ public void onAnimationStart(Animator animation) {
+ }
+ public void onAnimationRepeat(Animator animation) {
+ }
+ public void onAnimationEnd(Animator animation) {
+ mLinearLayout.removeView(mCurrentView);
+ mCallback.handleSwipe(animView, swipeDirection);
+ }
+ public void onAnimationCancel(Animator animation) {
+ mLinearLayout.removeView(mCurrentView);
+ mCallback.handleSwipe(animView, swipeDirection);
+ }
+ });
+ anim.setDuration(duration);
+ } else { // Animate back to position
+ final long duration = Math.abs(velocityX) > 0.0f ?
+ (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX))
+ : SNAP_BACK_DURATION;
+ anim = ObjectAnimator.ofFloat(animView, "x", animView.getX(), 0.0f);
+ anim.setInterpolator(new DecelerateInterpolator(4.0f));
+ anim.setDuration(duration);
+ }
+
+ anim.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth()));
+ invalidateGlobalRegion(animView);
+ }
+ });
+ anim.start();
+ }
+
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ break;
+ }
+ return true;
+ }
+
+ void invalidateGlobalRegion(View view) {
+ RectF childBounds
+ = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
+ childBounds.offset(view.getX(), view.getY());
+ if (DEBUG_INVALIDATE) Log.v(TAG, "-------------");
+ while (view.getParent() != null && view.getParent() instanceof View) {
+ view = (View) view.getParent();
+ view.getMatrix().mapRect(childBounds);
+ view.invalidate((int) Math.floor(childBounds.left),
+ (int) Math.floor(childBounds.top),
+ (int) Math.ceil(childBounds.right),
+ (int) Math.ceil(childBounds.bottom));
+ if (DEBUG_INVALIDATE) {
+ Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left)
+ + "," + (int) Math.floor(childBounds.top)
+ + "," + (int) Math.ceil(childBounds.right)
+ + "," + (int) Math.ceil(childBounds.bottom));
+ }
+ }
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ LayoutInflater inflater = (LayoutInflater)
+ mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ setScrollbarFadingEnabled(true);
+
+ mLinearLayout = (LinearLayout) findViewById(R.id.recents_linear_layout);
+
+ final int leftPadding = mContext.getResources()
+ .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin);
+ setOverScrollEffectPadding(leftPadding, 0);
+ }
+
+ private void setOverScrollEffectPadding(int leftPadding, int i) {
+ // TODO Add to (Vertical)ScrollView
+ }
+
+ @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.
+ mLastScrollPosition = scrollPositionOfMostRecent();
+
+ // This has to happen post-layout, so run it "in the future"
+ post(new Runnable() {
+ public void run() {
+ scrollTo(0, mLastScrollPosition);
+ }
+ });
+ }
+
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+ // scroll to bottom after reloading
+ if (visibility == View.VISIBLE && changedView == this) {
+ post(new Runnable() {
+ public void run() {
+ update();
+ }
+ });
+ }
+ }
+
+ public void setAdapter(ActvityDescriptionAdapter adapter) {
+ mAdapter = adapter;
+ mAdapter.registerDataSetObserver(new DataSetObserver() {
+ public void onChanged() {
+ update();
+ }
+
+ public void onInvalidated() {
+ update();
+ }
+ });
+ }
+
+ @Override
+ public void setLayoutTransition(LayoutTransition transition) {
+ // The layout transition applies to our embedded LinearLayout
+ mLinearLayout.setLayoutTransition(transition);
+ }
+
+ public void onClick(View view) {
+ mCallback.handleOnClick(view);
+ }
+
+ public void setCallback(RecentsCallback callback) {
+ mCallback = callback;
+ }
+
+ public boolean onTouch(View v, MotionEvent event) {
+ mCurrentView = v;
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsActivity.java b/packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsActivity.java
index 7d4629e..45e230f 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsActivity.java
@@ -15,7 +15,7 @@
*/
-package com.android.systemui.recent;
+package com.android.systemui.recent.carousel;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsCarouselView.java b/packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsCarouselView.java
index 1c8ec95..1afb086 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsCarouselView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsCarouselView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.recent;
+package com.android.systemui.recent.carousel;
import android.content.Context;
import android.util.AttributeSet;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index f74fcc6..91c3cc1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -71,7 +71,8 @@ import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.Prefs;
-import com.android.systemui.recent.RecentApplicationsActivity;
+import com.android.systemui.recent.RecentsPanelView;
+import com.android.systemui.recent.carousel.RecentApplicationsActivity;
public class TabletStatusBar extends StatusBar implements
HeightReceiver.OnBarHeightChangedListener,
@@ -162,7 +163,7 @@ public class TabletStatusBar extends StatusBar implements
// for disabling the status bar
int mDisabled = 0;
- private RecentAppsPanel mRecentsPanel;
+ private RecentsPanelView mRecentsPanel;
private InputMethodsPanel mInputMethodsPanel;
public Context getContext() { return mContext; }
@@ -253,7 +254,7 @@ public class TabletStatusBar extends StatusBar implements
WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp);
// Recents Panel
- mRecentsPanel = (RecentAppsPanel) View.inflate(context,
+ mRecentsPanel = (RecentsPanelView) View.inflate(context,
R.layout.status_bar_recent_panel, null);
mRecentsPanel.setVisibility(View.GONE);
mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
@@ -1195,7 +1196,7 @@ public class TabletStatusBar extends StatusBar implements
if (mVT != null) {
if (action == MotionEvent.ACTION_UP
// was this a sloppy tap?
- && Math.abs(event.getX() - mInitialTouchX) < mTouchSlop
+ && Math.abs(event.getX() - mInitialTouchX) < mTouchSlop
&& Math.abs(event.getY() - mInitialTouchY) < (mTouchSlop / 3)
// dragging off the bottom doesn't count
&& (int)event.getY() < v.getBottom()) {
@@ -1298,7 +1299,7 @@ public class TabletStatusBar extends StatusBar implements
if (!peeking) {
if (action == MotionEvent.ACTION_UP
// was this a sloppy tap?
- && Math.abs(event.getX() - mInitialTouchX) < mTouchSlop
+ && Math.abs(event.getX() - mInitialTouchX) < mTouchSlop
&& Math.abs(event.getY() - mInitialTouchY) < (mTouchSlop / 3)
// dragging off the bottom doesn't count
&& (int)event.getY() < v.getBottom()) {