am 9b5e37a8: (-s ours) am bb46697b: am e7d4f0f9: am 41f61f09: (-s ours) Import revised translations. DO NOT MERGE
* commit '9b5e37a8881c3f352b27b6118773997491eed86b':
Import revised translations. DO NOT MERGE
diff --git a/proguard.flags b/proguard.flags
index 19c8fd5..94dd260 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -20,7 +20,7 @@
public void setHoverAlpha(float);
}
--keep class com.android.launcher2.CellLayout$LayoutParams {
+-keep class com.android.launcher2.DragLayer$LayoutParams {
public void setWidth(int);
public int getWidth();
public void setHeight(int);
diff --git a/res/drawable-xlarge-mdpi/focused_bg.9.png b/res/drawable-xlarge-mdpi/focused_bg.9.png
new file mode 100644
index 0000000..1b0d3fa
--- /dev/null
+++ b/res/drawable-xlarge-mdpi/focused_bg.9.png
Binary files differ
diff --git a/res/drawable-xlarge/button_bg.xml b/res/drawable-xlarge/button_bg.xml
index 9e6e1ff..2cb7926 100644
--- a/res/drawable-xlarge/button_bg.xml
+++ b/res/drawable-xlarge/button_bg.xml
@@ -15,6 +15,7 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:drawable="@drawable/focused_bg" />
<item android:state_pressed="true" android:drawable="@drawable/home_press" />
<item android:drawable="@android:color/transparent" />
</selector>
diff --git a/res/drawable-xlarge/focusable_view_bg.xml b/res/drawable-xlarge/focusable_view_bg.xml
new file mode 100644
index 0000000..fb36bfc
--- /dev/null
+++ b/res/drawable-xlarge/focusable_view_bg.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:drawable="@drawable/focused_bg" />
+</selector>
diff --git a/res/layout-land/user_folder.xml b/res/layout-land/user_folder.xml
index 5da4aa5..ca437bf 100644
--- a/res/layout-land/user_folder.xml
+++ b/res/layout-land/user_folder.xml
@@ -14,7 +14,9 @@
limitations under the License.
-->
-<com.android.launcher2.UserFolder xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.launcher2.UserFolder
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:orientation="vertical">
<Button
@@ -29,17 +31,24 @@
<FrameLayout
android:layout_width="match_parent"
- android:layout_height="0dip"
+ android:layout_height="0dip"
android:layout_weight="1"
android:background="@drawable/box_launcher_bottom">
- <GridView
+ <com.android.launcher2.CellLayout
android:id="@id/folder_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="#ff333333"
+ launcher:cellWidth="@dimen/folder_cell_width"
+ launcher:cellHeight="@dimen/folder_cell_height"
+ launcher:xAxisStartPadding="0dip"
+ launcher:xAxisEndPadding="0dip"
+ launcher:yAxisStartPadding="0dip"
+ launcher:yAxisEndPadding="0dip"
+
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbarStyle="insideInset"
android:drawSelectorOnTop="false"
diff --git a/res/layout-port/user_folder.xml b/res/layout-port/user_folder.xml
index 0e6df66..c00b548 100644
--- a/res/layout-port/user_folder.xml
+++ b/res/layout-port/user_folder.xml
@@ -14,7 +14,9 @@
limitations under the License.
-->
-<com.android.launcher2.UserFolder xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.launcher2.UserFolder
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:orientation="vertical">
<Button
@@ -29,16 +31,23 @@
<FrameLayout
android:layout_width="match_parent"
- android:layout_height="0dip"
+ android:layout_height="0dip"
android:layout_weight="1"
android:background="@drawable/box_launcher_bottom">
- <GridView
+ <com.android.launcher2.CellLayout
android:id="@id/folder_content"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="match_parent"
android:cacheColorHint="#ff333333"
+ launcher:cellWidth="@dimen/folder_cell_width"
+ launcher:cellHeight="@dimen/folder_cell_height"
+ launcher:xAxisStartPadding="0dip"
+ launcher:xAxisEndPadding="0dip"
+ launcher:yAxisStartPadding="0dip"
+ launcher:yAxisEndPadding="0dip"
+
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbarStyle="insideInset"
android:drawSelectorOnTop="false"
diff --git a/res/layout-xlarge-land/application.xml b/res/layout-xlarge-land/application.xml
index 2598e5a..9393f7e 100644
--- a/res/layout-xlarge-land/application.xml
+++ b/res/layout-xlarge-land/application.xml
@@ -15,4 +15,6 @@
-->
<com.android.launcher2.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/WorkspaceIcon.Landscape" />
+ style="@style/WorkspaceIcon.Landscape"
+ android:focusable="true"
+ android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-xlarge-land/customization_drawer_tab_contents.xml b/res/layout-xlarge-land/customization_drawer_tab_contents.xml
deleted file mode 100644
index 50e7b66..0000000
--- a/res/layout-xlarge-land/customization_drawer_tab_contents.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.launcher2.CustomizePagedView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
-
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- launcher:wallpaperCellSpanX="3"
- launcher:wallpaperCellCountX="12"
- launcher:widgetCellCountX="14"
- launcher:cellCountX="8"
- launcher:cellCountY="3"
- launcher:pageLayoutWidthGap="32dp"
- launcher:pageLayoutHeightGap="12dp"
- launcher:pageLayoutPaddingTop="40dp"
- launcher:pageLayoutPaddingBottom="25dp"
- launcher:pageLayoutPaddingLeft="20dp"
- launcher:pageLayoutPaddingRight="20dp" />
\ No newline at end of file
diff --git a/res/layout-xlarge-port/all_apps_tabbed.xml b/res/layout-xlarge-port/all_apps_tabbed.xml
deleted file mode 100644
index c357d2e..0000000
--- a/res/layout-xlarge-port/all_apps_tabbed.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.launcher2.AllAppsTabbed
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
- <com.android.launcher2.AllAppsBackground
- android:id="@+id/all_apps_background"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <RelativeLayout
- android:layout_width="700dp"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:background="@drawable/tab_unselected_holo">
- <TabWidget
- android:id="@android:id/tabs"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:tabStripEnabled="false" />
- <FrameLayout
- android:id="@+id/market_info_frame"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true">
- <com.android.launcher2.ApplicationInfoDropTarget
- android:id="@+id/all_apps_info_target"
- android:drawableRight="@drawable/ic_home_info_holo_dark"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:visibility="invisible"/>
- <TextView
- android:id="@+id/market_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:gravity="center"
- android:paddingRight="22dp"
- android:text="@string/market"
- android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
- android:textSize="18sp"
- android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
- android:shadowDx="0.0"
- android:shadowDy="0.0"
- android:shadowRadius="2.0" />
- </FrameLayout>
- <com.android.launcher2.DeleteZone
- android:id="@+id/all_apps_delete_zone"
- android:drawablePadding="@dimen/delete_zone_drawable_padding"
- android:drawableLeft="@drawable/delete_zone_selector"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toLeftOf="@id/market_info_frame"
- android:layout_centerVertical="true"
- android:visibility="invisible"
- android:paddingRight="22dp"
- launcher:direction="horizontal"
-
- android:gravity="center"
- android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
- android:textSize="18sp"
- android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
- android:shadowDx="0.0"
- android:shadowDy="0.0"
- android:shadowRadius="2.0" />
- </RelativeLayout>
- <FrameLayout
- android:id="@android:id/tabcontent"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <com.android.launcher2.AllAppsPagedView
- android:id="@+id/all_apps_paged_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- launcher:cellCountX="5"
- launcher:cellCountY="7"
- launcher:pageLayoutWidthGap="36dp"
- launcher:pageLayoutHeightGap="36dp"
- launcher:pageLayoutPaddingTop="25dp"
- launcher:pageLayoutPaddingBottom="10dp"
- launcher:pageLayoutPaddingLeft="20dp"
- launcher:pageLayoutPaddingRight="20dp">
- </com.android.launcher2.AllAppsPagedView>
- </FrameLayout>
- </LinearLayout>
-</com.android.launcher2.AllAppsTabbed>
diff --git a/res/layout-xlarge-port/customization_drawer_tab_contents.xml b/res/layout-xlarge-port/customization_drawer_tab_contents.xml
deleted file mode 100644
index 0381be0..0000000
--- a/res/layout-xlarge-port/customization_drawer_tab_contents.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.launcher2.CustomizePagedView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
-
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- launcher:wallpaperCellSpanX="3"
- launcher:wallpaperCellCountX="9"
- launcher:widgetCellCountX="9"
- launcher:cellCountX="5"
- launcher:cellCountY="3"
- launcher:pageLayoutWidthGap="36dp"
- launcher:pageLayoutHeightGap="12dp"
- launcher:pageLayoutPaddingTop="40dp"
- launcher:pageLayoutPaddingBottom="25dp"
- launcher:pageLayoutPaddingLeft="20dp"
- launcher:pageLayoutPaddingRight="20dp" />
diff --git a/res/layout-xlarge/all_apps_no_items_placeholder.xml b/res/layout-xlarge/all_apps_no_items_placeholder.xml
index 247870c..b766df1 100644
--- a/res/layout-xlarge/all_apps_no_items_placeholder.xml
+++ b/res/layout-xlarge/all_apps_no_items_placeholder.xml
@@ -32,4 +32,5 @@
android:drawablePadding="0dip"
android:maxLines="2"
- android:fadingEdge="horizontal" />
+ android:fadingEdge="horizontal"
+ android:focusable="false" />
diff --git a/res/layout-xlarge/all_apps_paged_view_application.xml b/res/layout-xlarge/all_apps_paged_view_application.xml
index e5f07bf..16e5d82 100644
--- a/res/layout-xlarge/all_apps_paged_view_application.xml
+++ b/res/layout-xlarge/all_apps_paged_view_application.xml
@@ -21,9 +21,12 @@
launcher:blurColor="#FF6B8CF0"
launcher:outlineColor="#FF8CD2FF"
+ style="@style/WorkspaceIcon.AllApps"
+
android:id="@+id/application_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
- style="@style/WorkspaceIcon.AllApps" />
+ android:focusable="true"
+ android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-xlarge-land/all_apps_tabbed.xml b/res/layout-xlarge/all_apps_tabbed.xml
similarity index 75%
rename from res/layout-xlarge-land/all_apps_tabbed.xml
rename to res/layout-xlarge/all_apps_tabbed.xml
index 9244213..b00b3c3 100644
--- a/res/layout-xlarge-land/all_apps_tabbed.xml
+++ b/res/layout-xlarge/all_apps_tabbed.xml
@@ -24,12 +24,15 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
+ <!-- The layout_width of this RelativeLayout gets overwritten in
+ AllAppsTabbed.onFinishInflate -->
<RelativeLayout
- android:layout_width="952dp"
+ android:id="@+id/all_apps_tab_bar"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@drawable/tab_unselected_holo">
- <TabWidget
+ <com.android.launcher2.FocusOnlyTabWidget
android:id="@android:id/tabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -47,7 +50,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:visibility="invisible"/>
+ android:visibility="invisible"
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true" />
<TextView
android:id="@+id/market_button"
android:layout_width="wrap_content"
@@ -61,7 +66,9 @@
android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
android:shadowDx="0.0"
android:shadowDy="0.0"
- android:shadowRadius="2.0" />
+ android:shadowRadius="2.0"
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true" />
</FrameLayout>
<com.android.launcher2.DeleteZone
android:id="@+id/all_apps_delete_zone"
@@ -81,7 +88,10 @@
android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
android:shadowDx="0.0"
android:shadowDy="0.0"
- android:shadowRadius="2.0" />
+ android:shadowRadius="2.0"
+
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true" />
</RelativeLayout>
<FrameLayout
android:id="@android:id/tabcontent"
@@ -91,14 +101,14 @@
android:id="@+id/all_apps_paged_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- launcher:cellCountX="7"
- launcher:cellCountY="5"
- launcher:pageLayoutWidthGap="36dp"
- launcher:pageLayoutHeightGap="6dp"
- launcher:pageLayoutPaddingTop="20dp"
- launcher:pageLayoutPaddingBottom="15dp"
- launcher:pageLayoutPaddingLeft="40dp"
- launcher:pageLayoutPaddingRight="40dp">
+ launcher:cellCountX="@integer/all_apps_view_cellCountX"
+ launcher:cellCountY="@integer/all_apps_view_cellCountY"
+ launcher:pageLayoutWidthGap="@dimen/all_apps_view_pageLayoutWidthGap"
+ launcher:pageLayoutHeightGap="@dimen/all_apps_view_pageLayoutHeightGap"
+ launcher:pageLayoutPaddingTop="@dimen/all_apps_view_pageLayoutPaddingTop"
+ launcher:pageLayoutPaddingBottom="@dimen/all_apps_view_pageLayoutPaddingBottom"
+ launcher:pageLayoutPaddingLeft="@dimen/all_apps_view_pageLayoutPaddingLeft"
+ launcher:pageLayoutPaddingRight="@dimen/all_apps_view_pageLayoutPaddingRight">
</com.android.launcher2.AllAppsPagedView>
</FrameLayout>
</LinearLayout>
diff --git a/res/layout-xlarge/button_bar.xml b/res/layout-xlarge/button_bar.xml
index 5c96c5c..62115f7 100644
--- a/res/layout-xlarge/button_bar.xml
+++ b/res/layout-xlarge/button_bar.xml
@@ -15,31 +15,34 @@
-->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+ android:focusable="false">
<!-- Global search icon -->
<ImageView
- android:id="@+id/search_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
- android:paddingRight="@dimen/toolbar_button_horizontal_padding"
- android:paddingTop="@dimen/toolbar_button_vertical_padding"
- android:paddingBottom="@dimen/toolbar_button_vertical_padding"
- android:src="@drawable/ic_generic_search"
- android:background="@drawable/button_bg"
- android:onClick="onClickSearchButton"
- android:focusable="true"
- android:clickable="true" />
+ android:id="@+id/search_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
+ android:paddingRight="@dimen/toolbar_button_horizontal_padding"
+ android:paddingTop="@dimen/toolbar_button_vertical_padding"
+ android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+ android:src="@drawable/ic_generic_search"
+ android:background="@drawable/button_bg"
+ android:onClick="onClickSearchButton"
+
+ android:focusable="true"
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_search_button" />
<ImageView
android:id="@+id/search_divider"
android:src="@drawable/divider_launcher_holo"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_toRightOf="@id/search_button"
+ android:layout_toRightOf="@+id/search_button"
android:paddingTop="@dimen/toolbar_button_vertical_padding"
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
@@ -52,7 +55,7 @@
android:id="@+id/voice_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_toRightOf="@id/search_divider"
+ android:layout_toRightOf="@+id/search_divider"
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
android:paddingTop="@dimen/toolbar_button_vertical_padding"
@@ -60,35 +63,12 @@
android:src="@drawable/ic_voice_search"
android:background="@drawable/button_bg"
android:onClick="onClickVoiceButton"
- android:focusable="true"
- android:clickable="true"/>
-
- <ImageView
- android:id="@+id/configure_button"
- android:src="@drawable/ic_home_add_holo_dark"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_alignParentRight="true"
- android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
- android:paddingRight="@dimen/toolbar_button_horizontal_padding"
- android:paddingTop="@dimen/toolbar_button_vertical_padding"
- android:paddingBottom="@dimen/toolbar_button_vertical_padding"
- android:background="@drawable/button_bg"
android:focusable="true"
- android:clickable="true" />
- <ImageView
- android:id="@+id/divider"
- android:src="@drawable/divider_launcher_holo"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_toLeftOf="@id/configure_button"
- android:paddingTop="@dimen/toolbar_button_vertical_padding"
- android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_voice_search_button" />
- android:focusable="false"
- android:clickable="true" />
+ <!-- AllApps icon -->
<com.android.launcher2.StrokedTextView
android:id="@+id/all_apps_button"
android:text="@string/all_apps_button_label"
@@ -96,7 +76,7 @@
android:drawableLeft="@drawable/ic_home_all_apps_holo_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_toLeftOf="@id/divider"
+ android:layout_toLeftOf="@+id/all_apps_divider"
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
android:paddingTop="@dimen/all_apps_button_vertical_padding"
@@ -117,16 +97,38 @@
android:shadowRadius="2.5"
android:focusable="true"
- android:clickable="true" />
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_all_apps_button" />
+
<ImageView
- android:id="@+id/divider_during_drag"
+ android:id="@+id/all_apps_divider"
android:src="@drawable/divider_launcher_holo"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_toLeftOf="@id/configure_button"
+ android:layout_toLeftOf="@+id/configure_button"
android:paddingTop="@dimen/toolbar_button_vertical_padding"
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
- android:visibility="gone" />
+
+ android:focusable="false"
+ android:clickable="true" />
+
+ <!-- Customize icon -->
+ <ImageView
+ android:id="@+id/configure_button"
+ android:src="@drawable/ic_home_add_holo_dark"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
+ android:paddingRight="@dimen/toolbar_button_horizontal_padding"
+ android:paddingTop="@dimen/toolbar_button_vertical_padding"
+ android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+ android:background="@drawable/button_bg"
+ android:focusable="true"
+ android:contentDescription="@string/accessibility_customize_button" />
+
+ <!-- Delete icon -->
<com.android.launcher2.DeleteZone
android:id="@+id/delete_zone"
android:text="@string/delete_zone_label_workspace"
@@ -134,12 +136,12 @@
android:drawableLeft="@drawable/delete_zone_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignRight="@id/configure_button"
+ android:layout_alignRight="@+id/configure_button"
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
android:paddingTop="@dimen/toolbar_button_vertical_padding"
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
- android:background="@drawable/button_bg"
+ android:background="@drawable/button_bg"
android:gravity="center_horizontal|center_vertical"
android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
@@ -150,5 +152,8 @@
android:shadowRadius="2.0"
android:visibility="gone"
- launcher:direction="horizontal" />
-</RelativeLayout>
\ No newline at end of file
+ launcher:direction="horizontal"
+
+ android:focusable="true"
+ android:contentDescription="@string/accessibility_delete_button" />
+</RelativeLayout>
diff --git a/res/layout-xlarge/customization_drawer.xml b/res/layout-xlarge/customization_drawer.xml
index dd1234c..d8db066 100644
--- a/res/layout-xlarge/customization_drawer.xml
+++ b/res/layout-xlarge/customization_drawer.xml
@@ -13,14 +13,18 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<TabHost xmlns:android="http://schemas.android.com/apk/res/android">
+<com.android.launcher2.CustomizeTrayTabHost
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <TabWidget
+ <!-- The layout_width of this RelativeLayout gets overwritten in
+ CustomizeTrayTabHost.onFinishInflate -->
+ <com.android.launcher2.FocusOnlyTabWidget
android:id="@android:id/tabs"
- android:layout_width="@dimen/customization_drawer_tab_widget_width"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@drawable/tab_unselected_holo"
@@ -28,7 +32,23 @@
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
- android:layout_height="@dimen/customization_drawer_content_height">
+ android:layout_height="match_parent">
+ <com.android.launcher2.CustomizePagedView
+ android:id="@+id/customization_drawer_tab_contents"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:wallpaperCellSpanX="@integer/customization_drawer_contents_wallpaperCellSpanX"
+ launcher:wallpaperCellCountX="@integer/customization_drawer_contents_wallpaperCellCountX"
+ launcher:widgetCellCountX="@integer/customization_drawer_contents_widgetCellCountX"
+ launcher:cellCountX="@integer/customization_drawer_contents_cellCountX"
+ launcher:cellCountY="@integer/customization_drawer_contents_cellCountY"
+ launcher:pageLayoutWidthGap="@dimen/customization_drawer_contents_pageLayoutWidthGap"
+ launcher:pageLayoutHeightGap="12dp"
+ launcher:pageLayoutPaddingTop="40dp"
+ launcher:pageLayoutPaddingBottom="25dp"
+ launcher:pageLayoutPaddingLeft="20dp"
+ launcher:pageLayoutPaddingRight="20dp"
+ launcher:pageLayoutMaxHeight="@dimen/customization_drawer_content_height" />
</FrameLayout>
</LinearLayout>
-</TabHost>
\ No newline at end of file
+</com.android.launcher2.CustomizeTrayTabHost>
\ No newline at end of file
diff --git a/res/layout-xlarge/customize_paged_view_item.xml b/res/layout-xlarge/customize_paged_view_item.xml
index b2e5f08..80d678e 100644
--- a/res/layout-xlarge/customize_paged_view_item.xml
+++ b/res/layout-xlarge/customize_paged_view_item.xml
@@ -25,4 +25,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
- style="@style/WorkspaceIcon.Landscape" />
+ style="@style/WorkspaceIcon.Landscape"
+
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true" />
diff --git a/res/layout-xlarge/customize_paged_view_wallpaper.xml b/res/layout-xlarge/customize_paged_view_wallpaper.xml
index 8c5abc8..d6284c2 100644
--- a/res/layout-xlarge/customize_paged_view_wallpaper.xml
+++ b/res/layout-xlarge/customize_paged_view_wallpaper.xml
@@ -25,7 +25,10 @@
android:paddingBottom="50dp"
launcher:blurColor="#FF6B8CF0"
- launcher:outlineColor="#FF8CD2FF">
+ launcher:outlineColor="#FF8CD2FF"
+
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true">
<!-- The preview image for the wallpaper. -->
<ImageView
diff --git a/res/layout-xlarge/customize_paged_view_widget.xml b/res/layout-xlarge/customize_paged_view_widget.xml
index c0b4552..35791f5 100644
--- a/res/layout-xlarge/customize_paged_view_widget.xml
+++ b/res/layout-xlarge/customize_paged_view_widget.xml
@@ -25,7 +25,10 @@
android:paddingBottom="50dp"
launcher:blurColor="#FF6B8CF0"
- launcher:outlineColor="#FF8CD2FF">
+ launcher:outlineColor="#FF8CD2FF"
+
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true">
<!-- The icon of the widget. -->
<ImageView
diff --git a/res/layout-xlarge/launcher.xml b/res/layout-xlarge/launcher.xml
index acf62f9..c71d131 100644
--- a/res/layout-xlarge/launcher.xml
+++ b/res/layout-xlarge/launcher.xml
@@ -20,7 +20,8 @@
android:id="@+id/drag_layer"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:focusable="false">
<!-- The workspace contains 5 screens of cells -->
<com.android.launcher2.Workspace
@@ -41,6 +42,12 @@
<include android:id="@+id/cell5" layout="@layout/workspace_screen" />
</com.android.launcher2.Workspace>
+ <include layout="@layout/button_bar"
+ android:id="@+id/all_apps_button_cluster"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/actionBarSize"
+ android:layout_gravity="top" />
+
<include
layout="@layout/all_apps_tabbed"
android:id="@+id/all_apps_view"
@@ -48,12 +55,6 @@
android:layout_height="match_parent"
android:layout_gravity="top" />
- <include layout="@layout/button_bar"
- android:id="@+id/all_apps_button_cluster"
- android:layout_width="fill_parent"
- android:layout_height="?android:attr/actionBarSize"
- android:layout_gravity="top" />
-
<include layout="@layout/customization_drawer"
android:id="@+id/customization_drawer"
android:layout_width="match_parent"
diff --git a/res/layout-xlarge/tab_widget_indicator.xml b/res/layout-xlarge/tab_widget_indicator.xml
index 7794e29..8968c2a 100644
--- a/res/layout-xlarge/tab_widget_indicator.xml
+++ b/res/layout-xlarge/tab_widget_indicator.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
-<TextView
+<com.android.launcher2.AccessibleTabView
xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/TabIndicator" />
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index df0a210..d4eecfd 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"الرئيسية"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"إزالة"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"إزالة"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"إزالة التحديث"</string>
<string name="menu_add" msgid="3065046628354640854">"إضافة"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"إدارة التطبيقات"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 5be82f1..49e86d3 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Начало"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Премахване"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Деинсталиране"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Деинстал. на актуализацията"</string>
<string name="menu_add" msgid="3065046628354640854">"Добавяне"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Управление на приложенията"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 56ada67..6a1fecb 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Pàgina d\'inici"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Elimina"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstal·la"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstal·la l\'actualització"</string>
<string name="menu_add" msgid="3065046628354640854">"Afegeix"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gestiona les aplicacions"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 47fb726..919488d 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Plocha"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odebrat"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinstalovat"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinstalovat aktualizaci"</string>
<string name="menu_add" msgid="3065046628354640854">"Přidat"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Spravovat aplikace"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index f481234..ae7da8a 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Start"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Fjern"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Afinstaller"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Afinstaller opdatering"</string>
<string name="menu_add" msgid="3065046628354640854">"Tilføj"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Administrer programmer"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index f69ee43..21d020d 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -25,7 +25,7 @@
<string name="chooser_wallpaper" msgid="5988031014201479733">"Hintergrund auswählen"</string>
<string name="wallpaper_instructions" msgid="4215640646180727542">"Hintergrund festlegen"</string>
<string name="pick_wallpaper" msgid="5630222540525626723">"Hintergrundbilder"</string>
- <string name="activity_not_found" msgid="5591731020063337696">"Die Anwendung ist nicht installiert."</string>
+ <string name="activity_not_found" msgid="5591731020063337696">"Anwendung ist nicht installiert."</string>
<string name="configure_wallpaper" msgid="2820186271419674623">"Konfigurieren..."</string>
<string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
<string name="folders_tab_label" msgid="1145293785541489736">"Ordner"</string>
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startseite"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Entfernen"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Deinstallieren"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Update deinstallieren"</string>
<string name="menu_add" msgid="3065046628354640854">"Hinzufügen"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Apps verwalten"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 5e9b644..92d501e 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Αρχική σελίδα"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Κατάργηση"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Κατάργηση εγκατάστασης"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Κατάργηση εγκατάστασης ενημέρωσης"</string>
<string name="menu_add" msgid="3065046628354640854">"Προσθήκη"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Διαχείριση εφαρμογών"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 7334133..2a22436 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remove"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Uninstall"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Uninstall update"</string>
<string name="menu_add" msgid="3065046628354640854">"Add"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Manage apps"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index eadcbae..94c921c 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Página principal"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Quitar"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar la actualización"</string>
<string name="menu_add" msgid="3065046628354640854">"Agregar"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Administrar aplicaciones"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 90b4e1d..dfc22b5 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Inicio"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eliminar del escritorio"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar actualización"</string>
<string name="menu_add" msgid="3065046628354640854">"Añadir"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Administrar aplicaciones"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 0d53ea5..867b9b4 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"صفحه اصلی"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"حذف"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"حذف نصب"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"حذف نصب به روزرسانی"</string>
<string name="menu_add" msgid="3065046628354640854">"افزودن"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"مدیریت برنامه ها"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 7b02c8d..5174734 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Etusivu"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Poista"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Poista"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Poista päivitys"</string>
<string name="menu_add" msgid="3065046628354640854">"Lisää"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Hallinnoi sovelluksia"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 7ff39d7..687e0d9 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Page d\'accueil"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Supprimer"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Désinstaller"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Désinstaller la mise à jour"</string>
<string name="menu_add" msgid="3065046628354640854">"Ajouter"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gérer les applications"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index ea09db0..1016271 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Početna"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Ukloni"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Deinstaliraj"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Deinstalacija ažuriranja"</string>
<string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Upravljaj aplikacijama"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 77d9dda..3301158 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Főoldal"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eltávolítás"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Eltávolítás"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Eltávolítja a frissítést"</string>
<string name="menu_add" msgid="3065046628354640854">"Hozzáadás"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Alkalmazások kezelése"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index a7ed856..a2ddeee 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Rumah"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Hapus"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Copot pemasangan"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Copot pemasangan pemutakhiran"</string>
<string name="menu_add" msgid="3065046628354640854">"Tambahkan"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Mengelola aplikasi"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 003db6f..b25b808 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Rimuovi"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Disinstalla"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Disinstalla aggiornamento"</string>
<string name="menu_add" msgid="3065046628354640854">"Aggiungi"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gestisci applicazioni"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 75df245..563c674 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"דף הבית"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"הסר"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"הסר התקנה"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"הסר את התקנת העדכון"</string>
<string name="menu_add" msgid="3065046628354640854">"הוסף"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"נהל יישומים"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index ee6ab83..2ab244c 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"ホーム"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"削除"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"アンインストール"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"アップデートをアンインストール"</string>
<string name="menu_add" msgid="3065046628354640854">"追加"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"アプリの管理"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index f2b8b0c..db937e9 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"홈"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"삭제"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"제거"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"업데이트 제거"</string>
<string name="menu_add" msgid="3065046628354640854">"추가"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"애플리케이션 관리"</string>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 159cbb4..9cb549b 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -17,5 +17,7 @@
<resources>
<dimen name="workspace_cell_width">106dip</dimen>
<dimen name="workspace_cell_height">74dip</dimen>
+ <dimen name="folder_cell_width">100dip</dimen>
+ <dimen name="folder_cell_height">74dip</dimen>
<dimen name="button_bar_height">62dip</dimen>
</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index acf0e27..30858e2 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Pagrindinis"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Pašalinti"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Pašalinti"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Pašalinti naujinį"</string>
<string name="menu_add" msgid="3065046628354640854">"Pridėti"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Valdyti programas"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 9c1b389..9ca0aa1 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Sākums"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Noņemt"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Atinstalēt"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Atinstalēt atjauninājumu"</string>
<string name="menu_add" msgid="3065046628354640854">"Pievienot"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Lietotņu pārvaldība"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index ccdab7e..557dfff 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startsiden"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Fjern"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Avinstaller"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Avinstaller oppdateringen"</string>
<string name="menu_add" msgid="3065046628354640854">"Legg til"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Administrer programmer"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 3d7c7ac..f576ae5 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startpagina"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Verwijderen"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Verwijderen"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Update verwijderen"</string>
<string name="menu_add" msgid="3065046628354640854">"Toevoegen"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Apps beheren"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index f116165..e51a25e 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Ekran główny"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Usuń"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinstaluj"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinstaluj aktualizację"</string>
<string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Zarządzaj aplikacjami"</string>
diff --git a/res/values-port/dimens.xml b/res/values-port/dimens.xml
index 65a3fd3..ad5922d 100644
--- a/res/values-port/dimens.xml
+++ b/res/values-port/dimens.xml
@@ -17,4 +17,6 @@
<resources>
<dimen name="workspace_cell_width">80dip</dimen>
<dimen name="workspace_cell_height">100dip</dimen>
+ <dimen name="folder_cell_width">74dip</dimen>
+ <dimen name="folder_cell_height">86dip</dimen>
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index a3a5a8d..917119d 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Página inicial"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remover"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar atualização"</string>
<string name="menu_add" msgid="3065046628354640854">"Adicionar"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gerir aplicações"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 55deb94..309afe6 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Página inicial"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remover"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar atualização"</string>
<string name="menu_add" msgid="3065046628354640854">"Adicionar"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gerenciar aplicativos"</string>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
index 1b5729b..a8453ed 100644
--- a/res/values-rm/strings.xml
+++ b/res/values-rm/strings.xml
@@ -85,6 +85,16 @@
<skip />
<!-- no translation found for delete_zone_label_all_apps (6664588234817475108) -->
<skip />
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<!-- no translation found for delete_zone_label_all_apps_system_app (3683920959591819044) -->
<skip />
<string name="menu_add" msgid="3065046628354640854">"Agiuntar"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 3a72c51..f175b4d 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Domiciliu"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eliminaţi"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Dezinstalaţi"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Dezinstalaţi actualizarea"</string>
<string name="menu_add" msgid="3065046628354640854">"Adăugaţi"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gestionaţi aplicaţii"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 912c3f4..dd1f0af 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Главная"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Удалить"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Удалить"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Удалить обновление"</string>
<string name="menu_add" msgid="3065046628354640854">"Добавить"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Приложения"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 3cadf3b..ba54979 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Domovská stránka"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odstrániť"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinštalovať"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinštalovať aktualizáciu"</string>
<string name="menu_add" msgid="3065046628354640854">"Pridať"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Spravovať aplikácie"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index daf0899..ba98aeb 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Začetni zaslon"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odstrani"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odstrani"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odstrani posodobitev"</string>
<string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Upravljaj programe"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 1d92080..52cf464 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Почетна"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Уклони"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Деинсталирај"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Деинсталирај ажурирања"</string>
<string name="menu_add" msgid="3065046628354640854">"Додај"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Управљање апликацијама"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 8094f05..96ff34b 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startsida"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Ta bort"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Avinstallera"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Avinstallera uppdatering"</string>
<string name="menu_add" msgid="3065046628354640854">"Lägg till"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Hantera appar"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 26c33c9..875fa28 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"บ้าน"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"นำออก"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"ถอนการติดตั้ง"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"ถอนการติดตั้งการอัปเดต"</string>
<string name="menu_add" msgid="3065046628354640854">"เพิ่ม"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"จัดการแอปพลิเคชัน"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index f21dc3c..a1789cb 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Alisin"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"I-uninstall"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"I-uninstall ang update"</string>
<string name="menu_add" msgid="3065046628354640854">"Idagdag"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Pamahalaan ang apps"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index bf80bf5..9ae1c8e 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Ana Sayfa"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Kaldır"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Yüklemeyi Kaldır"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Güncelleme kaldırılsın mı?"</string>
<string name="menu_add" msgid="3065046628354640854">"Ekle"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Uyglm yönet"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 267ca88..daee514 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Головна"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Видалити"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Видалити"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Видалити оновлення"</string>
<string name="menu_add" msgid="3065046628354640854">"Додати"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Керув. прогр."</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index d3f549f..ca3e738 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Màn hình trang chủ"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Xóa"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Gỡ cài đặt"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Gỡ cài đặt cập nhật"</string>
<string name="menu_add" msgid="3065046628354640854">"Thêm"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Quản lý ứng dụng"</string>
diff --git a/res/values-xlarge-land/dimens.xml b/res/values-xlarge-land/dimens.xml
index b3d40d5..8d25555 100644
--- a/res/values-xlarge-land/dimens.xml
+++ b/res/values-xlarge-land/dimens.xml
@@ -27,6 +27,20 @@
<dimen name="customization_drawer_height">480dp</dimen>
<dimen name="customization_drawer_content_height">420dp</dimen>
- <dimen name="customization_drawer_content_min_width">952dp</dimen>
- <dimen name="customization_drawer_tab_widget_width">952dp</dimen>
+
+ <integer name="all_apps_view_cellCountX">7</integer>
+ <integer name="all_apps_view_cellCountY">5</integer>
+ <dimen name="all_apps_view_pageLayoutWidthGap">36dp</dimen>
+ <dimen name="all_apps_view_pageLayoutHeightGap">6dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingTop">20dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingBottom">14dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingLeft">40dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingRight">40dp</dimen>
+
+ <integer name="customization_drawer_contents_wallpaperCellSpanX">3</integer>
+ <integer name="customization_drawer_contents_wallpaperCellCountX">12</integer>
+ <integer name="customization_drawer_contents_widgetCellCountX">14</integer>
+ <integer name="customization_drawer_contents_cellCountX">8</integer>
+ <integer name="customization_drawer_contents_cellCountY">3</integer>
+ <dimen name="customization_drawer_contents_pageLayoutWidthGap">32dp</dimen>
</resources>
\ No newline at end of file
diff --git a/res/values-xlarge-port/dimens.xml b/res/values-xlarge-port/dimens.xml
index 8a4c78b..e696e34 100644
--- a/res/values-xlarge-port/dimens.xml
+++ b/res/values-xlarge-port/dimens.xml
@@ -27,6 +27,20 @@
<dimen name="customization_drawer_height">800dp</dimen>
<dimen name="customization_drawer_content_height">420dp</dimen>
- <dimen name="customization_drawer_content_min_width">640dp</dimen>
- <dimen name="customization_drawer_tab_widget_width">700dp</dimen>
+
+ <integer name="all_apps_view_cellCountX">5</integer>
+ <integer name="all_apps_view_cellCountY">7</integer>
+ <dimen name="all_apps_view_pageLayoutWidthGap">36dp</dimen>
+ <dimen name="all_apps_view_pageLayoutHeightGap">36dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingTop">25dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingBottom">10dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingLeft">20dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingRight">20dp</dimen>
+
+ <integer name="customization_drawer_contents_wallpaperCellSpanX">3</integer>
+ <integer name="customization_drawer_contents_wallpaperCellCountX">9</integer>
+ <integer name="customization_drawer_contents_widgetCellCountX">9</integer>
+ <integer name="customization_drawer_contents_cellCountX">5</integer>
+ <integer name="customization_drawer_contents_cellCountY">3</integer>
+ <dimen name="customization_drawer_contents_pageLayoutWidthGap">36dp</dimen>
</resources>
\ No newline at end of file
diff --git a/res/values-xlarge/config.xml b/res/values-xlarge/config.xml
index 56c7bc6..b9880e3 100644
--- a/res/values-xlarge/config.xml
+++ b/res/values-xlarge/config.xml
@@ -53,11 +53,6 @@
Should be an even number, for pixel alignment. -->
<integer name="config_dragViewExtraPixels">0</integer>
- <!-- When dragging items on the workspace, the number of pixels by which the position of
- the drag view should be offset from the position of the original view. -->
- <integer name="config_dragViewOffsetX">0</integer>
- <integer name="config_dragViewOffsetY">-12</integer>
-
<!-- When items are dropped on the mini screens in customize mode, we have a bounce animation
of the bright green hover outline, and then fade out the outline at the end. These are
the values used in that animation -->
diff --git a/res/values-xlarge/dimens.xml b/res/values-xlarge/dimens.xml
index 421c9e3..fffa0f2 100644
--- a/res/values-xlarge/dimens.xml
+++ b/res/values-xlarge/dimens.xml
@@ -28,6 +28,9 @@
<!-- Size of icons in workspace -->
<dimen name="app_icon_size">72dp</dimen>
+ <!-- Size of content of icons in workspace, as specified by the android icon guidelines -->
+ <dimen name="app_icon_content_size">60dp</dimen>
+
<!-- extra horizontal spacing between mini screen thumbnails ie. in all
apps and in customization mode -->
<dimen name="smallScreenExtraSpacing">0dip</dimen>
@@ -59,4 +62,9 @@
<!-- How much the content view of an alert dialog should be inset (currently used
for the WallpaperChooser in XLarge mode) -->
<dimen name="alert_dialog_content_inset">0dp</dimen>
+
+ <!-- When dragging items on the workspace, the number of dps by which the position of
+ the drag view should be offset from the position of the original view. -->
+ <dimen name="dragViewOffsetX">0dp</dimen>
+ <dimen name="dragViewOffsetY">-12dp</dimen>
</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index a3dc212..98b991f 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"主屏幕"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"删除"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"卸载"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"卸载更新"</string>
<string name="menu_add" msgid="3065046628354640854">"添加"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"管理应用程序"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 2274274..d9f61fb 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -67,6 +67,16 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"主螢幕"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"移除"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"解除安裝"</string>
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"解除安裝更新"</string>
<string name="menu_add" msgid="3065046628354640854">"新增"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"管理應用程式"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 2be5999..4f44253 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -104,6 +104,7 @@
<attr name="pageLayoutPaddingBottom" format="dimension" />
<attr name="pageLayoutPaddingLeft" format="dimension" />
<attr name="pageLayoutPaddingRight" format="dimension" />
+ <attr name="pageLayoutMaxHeight" format="dimension" />
<!-- The space between adjacent pages of the PagedView. -->
<attr name="pageSpacing" format="dimension" />
</declare-styleable>
diff --git a/res/values/config.xml b/res/values/config.xml
index c56a8ce..ec01fa8 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -12,12 +12,6 @@
Should be an even number, for pixel alignment. -->
<integer name="config_dragViewExtraPixels">40</integer>
- <!-- When dragging items on the workspace, the number of pixels by which the position of
- the drag view should be offset from the position of the original view.
- Setting to 1/2 of config_dragViewExtraPixels keeps it centered on its old position. -->
- <integer name="config_dragViewOffsetX">20</integer>
- <integer name="config_dragViewOffsetY">20</integer>
-
<!-- The duration (in ms) of the fade animation on the object outlines, used when
we are dragging objects around on the home screen. -->
<integer name="config_dragOutlineFadeTime">900</integer>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d6cd3ee..e346c6a 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -44,4 +44,9 @@
<!-- the area at the edge of the screen that makes the workspace go left
or right while you're dragging. -->
<dimen name="scroll_zone">20dp</dimen>
+
+ <!-- When dragging items on the workspace, the number of dps by which the position of
+ the drag view should be offset from the position of the original view. -->
+ <dimen name="dragViewOffsetX">0dp</dimen>
+ <dimen name="dragViewOffsetY">-8dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index eedbd6a..9ad3e24 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -151,6 +151,17 @@
device. [CHAR_LIMIT=30]-->
<string name="delete_zone_label_all_apps">Uninstall</string>
+ <!-- Accessibility: Search button -->
+ <string name="accessibility_search_button">Search</string>
+ <!-- Accessibility: Voice Search button -->
+ <string name="accessibility_voice_search_button">Voice Search</string>
+ <!-- Accessibility: AllApps button -->
+ <string name="accessibility_all_apps_button">Applications</string>
+ <!-- Accessibility: Customize button -->
+ <string name="accessibility_customize_button">Customize</string>
+ <!-- Accessibility: Delete button -->
+ <string name="accessibility_delete_button">Remove</string>
+
<!-- Label for trash icon in All Apps, when an updated system app is selected. The update will
be uninstalled. [CHAR_LIMIT=30] -->
<string name="delete_zone_label_all_apps_system_app">Uninstall update</string>
diff --git a/src/com/android/launcher2/AccessibleTabView.java b/src/com/android/launcher2/AccessibleTabView.java
new file mode 100644
index 0000000..a419911
--- /dev/null
+++ b/src/com/android/launcher2/AccessibleTabView.java
@@ -0,0 +1,48 @@
+/*
+ * 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.launcher2;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.widget.TextView;
+
+public class AccessibleTabView extends TextView {
+ public AccessibleTabView(Context context) {
+ super(context);
+ }
+
+ public AccessibleTabView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AccessibleTabView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return FocusHelper.handleTabKeyEvent(this, keyCode, event)
+ || super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return FocusHelper.handleTabKeyEvent(this, keyCode, event)
+ || super.onKeyUp(keyCode, event);
+ }
+}
diff --git a/src/com/android/launcher2/AllApps2D.java b/src/com/android/launcher2/AllApps2D.java
index 1cbb999..854c1ee 100644
--- a/src/com/android/launcher2/AllApps2D.java
+++ b/src/com/android/launcher2/AllApps2D.java
@@ -143,7 +143,7 @@
homeButton.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
}
});
}
@@ -167,7 +167,7 @@
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
break;
default:
return false;
@@ -190,7 +190,7 @@
app = new ApplicationInfo(app);
mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
return true;
}
@@ -341,6 +341,10 @@
public void surrender() {
}
+
+ public void reset() {
+ // Do nothing
+ }
}
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index 29f49af..a8aea18 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -350,7 +350,7 @@
if (mArrowNavigation) {
if (mLastSelection == SELECTION_HOME) {
reallyPlaySoundEffect(SoundEffectConstants.CLICK);
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
} else {
int whichApp = sRollo.mScript.get_gSelectedIconIndex();
if (whichApp >= 0) {
@@ -637,7 +637,7 @@
if ((isPortrait && y > mTouchYBorders[mTouchYBorders.length-1]) ||
(!isPortrait && x > mTouchXBorders[mTouchXBorders.length-1])) {
reallyPlaySoundEffect(SoundEffectConstants.CLICK);
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
}
sRollo.setHomeSelected(SELECTED_NONE);
}
@@ -691,10 +691,12 @@
int screenX = mMotionDownRawX - (bmp.getWidth() / 2);
int screenY = mMotionDownRawY - bmp.getHeight();
+ mLauncher.lockScreenOrientation();
+ mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, bmp);
mDragController.startDrag(
bmp, screenX, screenY, this, app, DragController.DRAG_ACTION_COPY);
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
}
return true;
}
@@ -747,6 +749,8 @@
@Override
public void onDropCompleted(View target, Object dragInfo, boolean success) {
+ mLauncher.getWorkspace().onDragStopped(success);
+ mLauncher.unlockScreenOrientation();
}
/**
@@ -1466,4 +1470,8 @@
sRS.contextDump();
}
}
+
+ public void reset() {
+ // Do nothing
+ }
}
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index b9b38c3..3d3c1ff 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -24,6 +24,7 @@
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -65,6 +66,8 @@
private final LayoutInflater mInflater;
private boolean mAllowHardwareLayerCreation;
+ private int mPageContentWidth;
+ private boolean mHasMadeSuccessfulDrop;
public AllAppsPagedView(Context context) {
this(context, null);
@@ -88,6 +91,11 @@
Resources r = context.getResources();
setDragSlopeThreshold(
r.getInteger(R.integer.config_allAppsDrawerDragSlopeThreshold) / 100.0f);
+
+ // Create a dummy page and set it up to find out the content width (used by our parent)
+ PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
+ setupPage(layout);
+ mPageContentWidth = layout.getContentWidth();
}
@Override
@@ -132,6 +140,10 @@
}
}
+ void resetSuccessfulDropFlag() {
+ mHasMadeSuccessfulDrop = false;
+ }
+
@Override
public void zoom(float zoom, boolean animate) {
mZoom = zoom;
@@ -279,6 +291,16 @@
c.translate((v.getWidth() - icon.getIntrinsicWidth()) / 2, v.getPaddingTop());
icon.draw(c);
+ Rect dragRect = null;
+ if (v instanceof TextView) {
+ int iconSize = getResources().getDimensionPixelSize(R.dimen.app_icon_size);
+ int top = v.getPaddingTop();
+ int left = (b.getWidth() - iconSize) / 2;
+ int right = left + iconSize;
+ int bottom = top + iconSize;
+ dragRect = new Rect(left, top, right, bottom);
+ }
+
// We toggle the checked state _after_ we create the view for the drag in case toggling the
// checked state changes the view's look
if (v instanceof Checkable) {
@@ -298,7 +320,7 @@
// Start the drag
mLauncher.lockScreenOrientation();
mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
- mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, null);
+ mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, dragRect);
b.recycle();
return true;
}
@@ -316,6 +338,16 @@
tearDownDragMode();
mLauncher.getWorkspace().onDragStopped(success);
mLauncher.unlockScreenOrientation();
+
+ if (!success && !mHasMadeSuccessfulDrop) {
+ mLauncher.getWorkspace().shrink(Workspace.ShrinkState.BOTTOM_HIDDEN);
+ } else {
+ mHasMadeSuccessfulDrop |= success;
+ }
+ }
+
+ int getPageContentWidth() {
+ return mPageContentWidth;
}
@Override
@@ -440,6 +472,18 @@
// do nothing?
}
+ public void reset() {
+ setCurrentPage(0);
+ invalidatePageData();
+ }
+
+ private void setupPage(PagedViewCellLayout layout) {
+ layout.setCellCount(mCellCountX, mCellCountY);
+ layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop, mPageLayoutPaddingRight,
+ mPageLayoutPaddingBottom);
+ layout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
+ }
+
@Override
public void syncPages() {
// ensure that we have the right number of pages (min of 1, since we have placeholders)
@@ -449,7 +493,6 @@
// remove any extra pages after the "last" page
int extraPageDiff = curNumPages - numPages;
for (int i = 0; i < extraPageDiff; ++i) {
- PagedViewCellLayout page = (PagedViewCellLayout) getChildAt(numPages);
removeViewAt(numPages);
}
// add any necessary pages
@@ -458,10 +501,7 @@
if (mAllowHardwareLayerCreation) {
layout.allowHardwareLayerCreation();
}
- layout.setCellCount(mCellCountX, mCellCountY);
- layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
- mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
- layout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
+ setupPage(layout);
addView(layout);
}
diff --git a/src/com/android/launcher2/AllAppsTabbed.java b/src/com/android/launcher2/AllAppsTabbed.java
index 0dd56ac..2deec8e 100644
--- a/src/com/android/launcher2/AllAppsTabbed.java
+++ b/src/com/android/launcher2/AllAppsTabbed.java
@@ -33,10 +33,9 @@
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;
-import android.widget.TabHost.OnTabChangeListener;
-import android.widget.TabHost.TabContentFactory;
import java.util.ArrayList;
+import java.util.Random;
/**
* Implements a tabbed version of AllApps2D.
@@ -82,6 +81,8 @@
}
};
+ // Create the tabs and wire them up properly
+ AllAppsTabKeyEventListener keyListener = new AllAppsTabKeyEventListener();
TextView tabView;
TabWidget tabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
@@ -92,6 +93,12 @@
tabView.setText(mContext.getString(R.string.all_apps_tab_downloaded));
addTab(newTabSpec(TAG_DOWNLOADED).setIndicator(tabView).setContent(contentFactory));
+ // Setup the key listener to jump between the last tab view and the market icon
+ View lastTab = tabWidget.getChildTabViewAt(tabWidget.getTabCount() - 1);
+ lastTab.setOnKeyListener(keyListener);
+ View shopButton = findViewById(R.id.market_button);
+ shopButton.setOnKeyListener(keyListener);
+
setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String tabId) {
// animate the changing of the tab content by fading pages in and out
@@ -119,6 +126,17 @@
}
});
+ // Set the width of the tab bar properly
+ int pageWidth = mAllApps.getPageContentWidth();
+ View allAppsTabBar = (View) findViewById(R.id.all_apps_tab_bar);
+ if (allAppsTabBar == null) throw new Resources.NotFoundException();
+ int tabWidgetPadding = 0;
+ final int childCount = tabWidget.getChildCount();
+ if (childCount > 0) {
+ tabWidgetPadding += tabWidget.getChildAt(0).getPaddingLeft() * 2;
+ }
+ allAppsTabBar.getLayoutParams().width = pageWidth + tabWidgetPadding;
+
// It needs to be INVISIBLE so that it will be measured in the layout.
// Otherwise the animations is messed up when we show it for the first time.
setVisibility(INVISIBLE);
@@ -239,6 +257,10 @@
mAllApps.surrender();
}
+ public void reset() {
+ mAllApps.reset();
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getY() > mAllApps.getBottom()) {
@@ -246,4 +268,12 @@
}
return true;
}
+
+ @Override
+ public int getDescendantFocusability() {
+ if (getVisibility() != View.VISIBLE) {
+ return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+ }
+ return super.getDescendantFocusability();
+ }
}
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index 007ecf8..3a74c71 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -41,6 +41,9 @@
public void updateApps(ArrayList<ApplicationInfo> list);
+ // Resets the AllApps page to the front
+ public void reset();
+
public void dumpState();
public void surrender();
diff --git a/src/com/android/launcher2/AppWidgetResizeFrame.java b/src/com/android/launcher2/AppWidgetResizeFrame.java
index 2b2662f..d975ed9 100644
--- a/src/com/android/launcher2/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher2/AppWidgetResizeFrame.java
@@ -18,6 +18,8 @@
private ItemInfo mItemInfo;
private LauncherAppWidgetHostView mWidgetView;
private CellLayout mCellLayout;
+ private DragLayer mDragLayer;
+ private Workspace mWorkspace;
private ImageView mLeftHandle;
private ImageView mRightHandle;
private ImageView mTopHandle;
@@ -57,7 +59,7 @@
public static final int BOTTOM = 3;
public AppWidgetResizeFrame(Context context, ItemInfo itemInfo,
- LauncherAppWidgetHostView widgetView, CellLayout cellLayout) {
+ LauncherAppWidgetHostView widgetView, CellLayout cellLayout, DragLayer dragLayer) {
super(context);
mContext = context;
@@ -65,6 +67,8 @@
mCellLayout = cellLayout;
mWidgetView = widgetView;
mResizeMode = widgetView.getAppWidgetInfo().resizeMode;
+ mDragLayer = dragLayer;
+ mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
int[] result = mCellLayout.rectToCell(info.minWidth, info.minHeight, null);
@@ -150,7 +154,7 @@
mDeltaX = Math.max(-mBaselineX, deltaX);
mDeltaX = Math.min(mBaselineWidth - 2 * mTouchTargetWidth, mDeltaX);
} else if (mRightBorderActive) {
- mDeltaX = Math.min(mCellLayout.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
+ mDeltaX = Math.min(mDragLayer.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
mDeltaX = Math.max(-mBaselineWidth + 2 * mTouchTargetWidth, mDeltaX);
}
@@ -158,7 +162,7 @@
mDeltaY = Math.max(-mBaselineY, deltaY);
mDeltaY = Math.min(mBaselineHeight - 2 * mTouchTargetWidth, mDeltaY);
} else if (mBottomBorderActive) {
- mDeltaY = Math.min(mCellLayout.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
+ mDeltaY = Math.min(mDragLayer.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
mDeltaY = Math.max(-mBaselineHeight + 2 * mTouchTargetWidth, mDeltaY);
}
}
@@ -168,7 +172,8 @@
*/
public void visualizeResizeForDelta(int deltaX, int deltaY) {
updateDeltas(deltaX, deltaY);
- CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+ DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+
if (mLeftBorderActive) {
lp.x = mBaselineX + mDeltaX;
lp.width = mBaselineWidth - mDeltaX;
@@ -261,6 +266,7 @@
// Update the cells occupied by this widget
mCellLayout.markCellsAsOccupiedForView(mWidgetView);
+ mWidgetView.requestLayout();
}
/**
@@ -284,20 +290,22 @@
}
public void snapToWidget(boolean animate) {
- final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+ final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+ int xOffset = mCellLayout.getLeft() - mWorkspace.getScrollX();
+ int yOffset = mCellLayout.getTop() - mWorkspace.getScrollY();
int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding;
int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding;
- int newX = mWidgetView.getLeft() - mBackgroundPadding;
- int newY = mWidgetView.getTop() - mBackgroundPadding;
+ int newX = mWidgetView.getLeft() - mBackgroundPadding + xOffset;
+ int newY = mWidgetView.getTop() - mBackgroundPadding + yOffset;
// We need to make sure the frame stays within the bounds of the CellLayout
if (newY < 0) {
newHeight -= -newY;
newY = 0;
}
- if (newY + newHeight > mCellLayout.getHeight()) {
- newHeight -= newY + newHeight - mCellLayout.getHeight();
+ if (newY + newHeight > mDragLayer.getHeight()) {
+ newHeight -= newY + newHeight - mDragLayer.getHeight();
}
if (!animate) {
diff --git a/src/com/android/launcher2/BubbleTextView.java b/src/com/android/launcher2/BubbleTextView.java
index 1464854..703b3a8 100644
--- a/src/com/android/launcher2/BubbleTextView.java
+++ b/src/com/android/launcher2/BubbleTextView.java
@@ -29,6 +29,7 @@
import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
@@ -87,8 +88,6 @@
private void init() {
mBackground = getBackground();
- setFocusable(true);
- setBackgroundDrawable(null);
final Resources res = getContext().getResources();
int bubbleColor = res.getColor(R.color.bubble_dark_background);
@@ -330,4 +329,16 @@
}
return true;
}
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return FocusHelper.handleBubbleTextViewKeyEvent(this, keyCode, event)
+ || super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return FocusHelper.handleBubbleTextViewKeyEvent(this, keyCode, event)
+ || super.onKeyUp(keyCode, event);
+ }
}
diff --git a/src/com/android/launcher2/CachedTextView.java b/src/com/android/launcher2/CachedTextView.java
index 403d856..d0f6dd8 100644
--- a/src/com/android/launcher2/CachedTextView.java
+++ b/src/com/android/launcher2/CachedTextView.java
@@ -18,10 +18,11 @@
import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
-import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.util.AttributeSet;
import android.widget.TextView;
@@ -163,6 +164,16 @@
if (mPrevAlpha != alpha) {
mPrevAlpha = alpha;
mCachePaint.setAlpha(alpha);
+
+ // We manually update the drawables alpha since the default TextView implementation may
+ // not do this if there is a background set (which we may due to the focus bg)
+ final Drawable[] dr = getCompoundDrawables();
+ for (int i = 0; i < dr.length; ++i) {
+ if (dr[i] != null) {
+ dr[i].mutate().setAlpha(alpha);
+ }
+ }
+
super.onSetAlpha(alpha);
}
return true;
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 1111c53..636b041 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -95,7 +95,7 @@
private float mGlowBackgroundScale;
private float mGlowBackgroundAlpha;
- private boolean mAcceptsDrops = false;
+ private boolean mAcceptsDrops = true;
// If we're actively dragging something over this screen, mIsDragOverlapping is true
private boolean mIsDragOverlapping = false;
private boolean mIsDragOccuring = false;
@@ -736,6 +736,22 @@
result[1] = vStartPadding + cellY * (mCellHeight + mHeightGap);
}
+ /**
+ * Given a cell coordinate, return the point that represents the upper left corner of that cell
+ *
+ * @param cellX X coordinate of the cell
+ * @param cellY Y coordinate of the cell
+ *
+ * @param result Array of 2 ints to hold the x and y coordinate of the point
+ */
+ void cellToCenterPoint(int cellX, int cellY, int[] result) {
+ final int hStartPadding = getLeftPadding();
+ final int vStartPadding = getTopPadding();
+
+ result[0] = hStartPadding + cellX * (mCellWidth + mWidthGap) + mCellWidth / 2;
+ result[1] = vStartPadding + cellY * (mCellHeight + mHeightGap) + mCellHeight / 2;
+ }
+
int getCellWidth() {
return mCellWidth;
}
@@ -956,13 +972,15 @@
int top = topLeft[1];
if (v != null) {
- if (v.getParent() instanceof CellLayout) {
- LayoutParams lp = (LayoutParams) v.getLayoutParams();
- left += lp.leftMargin;
- top += lp.topMargin;
- }
+ // When drawing the drag outline, it did not account for margin offsets
+ // added by the view's parent.
+ MarginLayoutParams lp = (MarginLayoutParams) v.getLayoutParams();
+ left += lp.leftMargin;
+ top += lp.topMargin;
- // Offsets due to the size difference between the View and the dragOutline
+ // Offsets due to the size difference between the View and the dragOutline.
+ // There is a size difference to account for the outer blur, which may lie
+ // outside the bounds of the view.
left += (v.getWidth() - dragOutline.getWidth()) / 2;
top += (v.getHeight() - dragOutline.getHeight()) / 2;
}
@@ -1008,16 +1026,23 @@
* @param pixelY The Y location at which you want to search for a vacant area.
* @param spanX Horizontal span of the object.
* @param spanY Vertical span of the object.
- * @param ignoreView Considers space occupied by this view as unoccupied
- * @param result Previously returned value to possibly recycle.
+ * @param ignoreOccupied If true, the result can be an occupied cell
+ * @param result Array in which to place the result, or null (in which case a new array will
+ * be allocated)
* @return The X, Y cell of a vacant area that can contain this object,
* nearest the requested location.
*/
- int[] findNearestVacantArea(
- int pixelX, int pixelY, int spanX, int spanY, View ignoreView, int[] result) {
+ int[] findNearestArea(int pixelX, int pixelY, int spanX, int spanY, View ignoreView,
+ boolean ignoreOccupied, int[] result) {
// mark space take by ignoreView as available (method checks if ignoreView is null)
markCellsAsUnoccupiedForView(ignoreView);
+ // For items with a spanX / spanY > 1, the passed in point (pixelX, pixelY) corresponds
+ // to the center of the item, but we are searching based on the top-left cell, so
+ // we translate the point over to correspond to the top-left.
+ pixelX -= (mCellWidth + mWidthGap) * (spanX - 1) / 2f;
+ pixelY -= (mCellHeight + mHeightGap) * (spanY - 1) / 2f;
+
// Keep track of best-scoring drop area
final int[] bestXY = result != null ? result : new int[2];
double bestDistance = Double.MAX_VALUE;
@@ -1029,18 +1054,20 @@
for (int y = 0; y < countY - (spanY - 1); y++) {
inner:
for (int x = 0; x < countX - (spanX - 1); x++) {
- for (int i = 0; i < spanX; i++) {
- for (int j = 0; j < spanY; j++) {
- if (occupied[x + i][y + j]) {
- // small optimization: we can skip to after the column we just found
- // an occupied cell
- x += i;
- continue inner;
+ if (ignoreOccupied) {
+ for (int i = 0; i < spanX; i++) {
+ for (int j = 0; j < spanY; j++) {
+ if (occupied[x + i][y + j]) {
+ // small optimization: we can skip to after the column we
+ // just found an occupied cell
+ x += i;
+ continue inner;
+ }
}
}
}
final int[] cellXY = mTmpCellXY;
- cellToPoint(x, y, cellXY);
+ cellToCenterPoint(x, y, cellXY);
double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2)
+ Math.pow(cellXY[1] - pixelY, 2));
@@ -1062,6 +1089,42 @@
}
}
+ /**
+ * Find a vacant area that will fit the given bounds nearest the requested
+ * cell location. Uses Euclidean distance to score multiple vacant areas.
+ *
+ * @param pixelX The X location at which you want to search for a vacant area.
+ * @param pixelY The Y location at which you want to search for a vacant area.
+ * @param spanX Horizontal span of the object.
+ * @param spanY Vertical span of the object.
+ * @param ignoreView Considers space occupied by this view as unoccupied
+ * @param result Previously returned value to possibly recycle.
+ * @return The X, Y cell of a vacant area that can contain this object,
+ * nearest the requested location.
+ */
+ int[] findNearestVacantArea(
+ int pixelX, int pixelY, int spanX, int spanY, View ignoreView, int[] result) {
+ return findNearestArea(pixelX, pixelY, spanX, spanY, ignoreView, true, result);
+ }
+
+ /**
+ * Find a starting cell position that will fit the given bounds nearest the requested
+ * cell location. Uses Euclidean distance to score multiple vacant areas.
+ *
+ * @param pixelX The X location at which you want to search for a vacant area.
+ * @param pixelY The Y location at which you want to search for a vacant area.
+ * @param spanX Horizontal span of the object.
+ * @param spanY Vertical span of the object.
+ * @param ignoreView Considers space occupied by this view as unoccupied
+ * @param result Previously returned value to possibly recycle.
+ * @return The X, Y cell of a vacant area that can contain this object,
+ * nearest the requested location.
+ */
+ int[] findNearestArea(
+ int pixelX, int pixelY, int spanX, int spanY, int[] result) {
+ return findNearestArea(pixelX, pixelY, spanX, spanY, null, false, result);
+ }
+
boolean existsEmptyCell() {
return findCellForSpan(null, 1, 1);
}
@@ -1457,6 +1520,14 @@
}
}
+ public boolean isOccupied(int x, int y) {
+ if (x < mCountX && y < mCountY) {
+ return mOccupied[x][y];
+ } else {
+ throw new RuntimeException("Position exceeds the bound of this CellLayout");
+ }
+ }
+
@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new CellLayout.LayoutParams(getContext(), attrs);
@@ -1587,38 +1658,6 @@
}
}
- public void setWidth(int width) {
- this.width = width;
- }
-
- public int getWidth() {
- return width;
- }
-
- public void setHeight(int height) {
- this.height = height;
- }
-
- public int getHeight() {
- return height;
- }
-
- public void setX(int x) {
- this.x = x;
- }
-
- public int getX() {
- return x;
- }
-
- public void setY(int y) {
- this.y = y;
- }
-
- public int getY() {
- return y;
- }
-
public String toString() {
return "(" + this.cellX + ", " + this.cellY + ")";
}
@@ -1630,7 +1669,7 @@
// 2. When long clicking on an empty cell in a CellLayout, we save information about the
// cellX and cellY coordinates and which page was clicked. We then set this as a tag on
// the CellLayout that was long clicked
- static final class CellInfo implements ContextMenu.ContextMenuInfo {
+ static final class CellInfo {
View cell;
int cellX = -1;
int cellY = -1;
diff --git a/src/com/android/launcher2/CellLayoutChildren.java b/src/com/android/launcher2/CellLayoutChildren.java
index 04996f3..e4e6fb1 100644
--- a/src/com/android/launcher2/CellLayoutChildren.java
+++ b/src/com/android/launcher2/CellLayoutChildren.java
@@ -43,12 +43,6 @@
private int mWidthGap;
private int mHeightGap;
- // Variables relating to resizing widgets
- private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
- new ArrayList<AppWidgetResizeFrame>();
- private AppWidgetResizeFrame mCurrentResizeFrame;
- private int mXDown, mYDown;
-
public CellLayoutChildren(Context context) {
super(context);
mWallpaperManager = WallpaperManager.getInstance(context);
@@ -81,27 +75,31 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int cellWidth = mCellWidth;
- final int cellHeight = mCellHeight;
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
- CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
-
- lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap,
- mLeftPadding, mTopPadding);
-
- int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
- int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
- MeasureSpec.EXACTLY);
-
- child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+ measureChild(child);
}
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(widthSpecSize, heightSpecSize);
}
+ public void measureChild(View child) {
+ final int cellWidth = mCellWidth;
+ final int cellHeight = mCellHeight;
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
+
+ lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap,
+ mLeftPadding, mTopPadding);
+
+ int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
+ int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
+ MeasureSpec.EXACTLY);
+
+ child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+ }
+
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
@@ -176,95 +174,4 @@
protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
super.setChildrenDrawnWithCacheEnabled(enabled);
}
-
- public void clearAllResizeFrames() {
- for (AppWidgetResizeFrame frame: mResizeFrames) {
- removeView(frame);
- }
- mResizeFrames.clear();
- }
-
- public boolean hasResizeFrames() {
- return mResizeFrames.size() > 0;
- }
-
- public boolean isWidgetBeingResized() {
- return mCurrentResizeFrame != null;
- }
-
- private boolean handleTouchDown(MotionEvent ev) {
- Rect hitRect = new Rect();
-
- int x = (int) ev.getX();
- int y = (int) ev.getY();
-
- for (AppWidgetResizeFrame child: mResizeFrames) {
- child.getHitRect(hitRect);
- if (hitRect.contains(x, y)) {
- if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
- mCurrentResizeFrame = child;
- mXDown = x;
- mYDown = y;
- requestDisallowInterceptTouchEvent(true);
- return true;
- }
- }
- }
- return false;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (handleTouchDown(ev)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean handled = false;
- int action = ev.getAction();
-
- int x = (int) ev.getX();
- int y = (int) ev.getY();
-
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (handleTouchDown(ev)) {
- return true;
- }
- }
- }
-
- if (mCurrentResizeFrame != null) {
- handled = true;
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
- break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- mCurrentResizeFrame.commitResizeForDelta(x - mXDown, y - mYDown);
- mCurrentResizeFrame = null;
- }
- }
- return handled;
- }
-
- public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
- CellLayout cellLayout) {
- AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
- itemInfo, widget, cellLayout);
-
- CellLayout.LayoutParams lp = new CellLayout.LayoutParams(-1, -1, -1, -1);
- lp.isLockedToGrid = false;
-
- addView(resizeFrame, lp);
- mResizeFrames.add(resizeFrame);
-
- resizeFrame.snapToWidget(false);
- }
}
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 5c61b0b..ca60361 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -140,6 +140,8 @@
private int[] mDragViewOrigin = new int[2];
+ private int mPageContentWidth;
+
public CustomizePagedView(Context context) {
this(context, null, 0);
}
@@ -170,7 +172,12 @@
final Resources r = context.getResources();
setDragSlopeThreshold(
r.getInteger(R.integer.config_customizationDrawerDragSlopeThreshold) / 100.0f);
- mMinPageWidth = r.getDimensionPixelSize(R.dimen.customization_drawer_content_min_width);
+
+ // Create a dummy page and set it up to find out the content width (used by our parent)
+ PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
+ setupPage(layout);
+ mPageContentWidth = layout.getContentWidth();
+ mMinPageWidth = layout.getWidthBeforeFirstLayout();
setVisibility(View.GONE);
setSoundEffectsEnabled(false);
@@ -481,8 +488,6 @@
@Override
public void onClick(final View v) {
- // Return early if this is not initiated from a touch
- if (!v.isInTouchMode()) return;
// Return early if we are still animating the pages
if (mNextPage != INVALID_PAGE) return;
@@ -1128,8 +1133,10 @@
}
// Set a min page width for PagedView layout if we have more than a single page
- if (enforceMinimumPagedWidths) {
- setMinimumWidthOverride((childCount > 1) ? mMinPageWidth : 0);
+ if (enforceMinimumPagedWidths && childCount > 1) {
+ setMinimumWidthOverride(mMinPageWidth);
+ } else {
+ resetMinimumWidthOverride();
}
// Bound the current page index
@@ -1161,6 +1168,10 @@
}
}
+ int getPageContentWidth() {
+ return mPageContentWidth;
+ }
+
@Override
protected int getAssociatedLowerPageBound(int page) {
return 0;
diff --git a/src/com/android/launcher2/CustomizeTrayTabHost.java b/src/com/android/launcher2/CustomizeTrayTabHost.java
index 76cfc84..5c683c4 100644
--- a/src/com/android/launcher2/CustomizeTrayTabHost.java
+++ b/src/com/android/launcher2/CustomizeTrayTabHost.java
@@ -16,20 +16,116 @@
package com.android.launcher2;
-import android.animation.Animator;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.TabHost;
+import java.util.Random;
-public class CustomizeTrayTabHost extends TabHost implements LauncherTransitionable {
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+import android.widget.TextView;
+
+import com.android.launcher.R;
+import com.android.launcher2.CustomizePagedView.CustomizationType;
+
+public class CustomizeTrayTabHost extends TabHost implements LauncherTransitionable {
+ // tags for the customization tabs
+ private static final String WIDGETS_TAG = "widgets";
+ private static final String APPLICATIONS_TAG = "applications";
+ private static final String SHORTCUTS_TAG = "shortcuts";
+ private static final String WALLPAPERS_TAG = "wallpapers";
+
private boolean mFirstLayout = true;
- public CustomizeTrayTabHost(Context context) {
- super(context);
- }
+ private final LayoutInflater mInflater;
+ private Context mContext;
public CustomizeTrayTabHost(Context context, AttributeSet attrs) {
super(context, attrs);
+ mContext = context;
+ mInflater = LayoutInflater.from(context);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ setup();
+
+ final CustomizePagedView customizePagedView =
+ (CustomizePagedView) findViewById(R.id.customization_drawer_tab_contents);
+
+ // Configure tabs
+ TabContentFactory contentFactory = new TabContentFactory() {
+ public View createTabContent(String tag) {
+ return customizePagedView;
+ }
+ };
+
+ TextView tabView;
+ TabWidget tabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
+
+ tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+ tabView.setText(mContext.getString(R.string.widgets_tab_label));
+ addTab(newTabSpec(WIDGETS_TAG)
+ .setIndicator(tabView).setContent(contentFactory));
+ tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+ tabView.setText(mContext.getString(R.string.applications_tab_label));
+ addTab(newTabSpec(APPLICATIONS_TAG)
+ .setIndicator(tabView).setContent(contentFactory));
+ tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+ tabView.setText(mContext.getString(R.string.wallpapers_tab_label));
+ addTab(newTabSpec(WALLPAPERS_TAG)
+ .setIndicator(tabView).setContent(contentFactory));
+ tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+ tabView.setText(mContext.getString(R.string.shortcuts_tab_label));
+ addTab(newTabSpec(SHORTCUTS_TAG)
+ .setIndicator(tabView).setContent(contentFactory));
+
+ setOnTabChangedListener(new OnTabChangeListener() {
+ public void onTabChanged(String tabId) {
+ final CustomizePagedView.CustomizationType newType =
+ getCustomizeFilterForTabTag(tabId);
+ if (newType != customizePagedView.getCustomizationFilter()) {
+ // animate the changing of the tab content by fading pages in and out
+ final Resources res = getResources();
+ final int duration = res.getInteger(R.integer.config_tabTransitionTime);
+ final float alpha = customizePagedView.getAlpha();
+ ValueAnimator alphaAnim = ObjectAnimator.ofFloat(customizePagedView,
+ "alpha", alpha, 0.0f);
+ alphaAnim.setDuration(duration);
+ alphaAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ customizePagedView.setCustomizationFilter(newType);
+
+ final float alpha = customizePagedView.getAlpha();
+ ValueAnimator alphaAnim = ObjectAnimator.ofFloat(
+ customizePagedView, "alpha", alpha, 1.0f);
+ alphaAnim.setDuration(duration);
+ alphaAnim.start();
+ }
+ });
+ alphaAnim.start();
+ }
+ }
+ });
+
+ // Set the width of the tab bar properly
+ int pageWidth = customizePagedView.getPageContentWidth();
+ TabWidget customizeTabBar = (TabWidget) findViewById(com.android.internal.R.id.tabs);
+ if (customizeTabBar == null) throw new Resources.NotFoundException();
+ int tabWidgetPadding = 0;
+ final int childCount = tabWidget.getChildCount();
+ if (childCount > 0) {
+ tabWidgetPadding += tabWidget.getChildAt(0).getPaddingLeft() * 2;
+ }
+ customizeTabBar.getLayoutParams().width = pageWidth + tabWidgetPadding;
}
@Override
@@ -57,4 +153,25 @@
mFirstLayout = false;
super.onLayout(changed, l, t, r, b);
}
+
+ @Override
+ public int getDescendantFocusability() {
+ if (getVisibility() != View.VISIBLE) {
+ return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+ }
+ return super.getDescendantFocusability();
+ }
+
+ CustomizationType getCustomizeFilterForTabTag(String tag) {
+ if (tag.equals(WIDGETS_TAG)) {
+ return CustomizationType.WidgetCustomization;
+ } else if (tag.equals(APPLICATIONS_TAG)) {
+ return CustomizationType.ApplicationCustomization;
+ } else if (tag.equals(WALLPAPERS_TAG)) {
+ return CustomizePagedView.CustomizationType.WallpaperCustomization;
+ } else if (tag.equals(SHORTCUTS_TAG)) {
+ return CustomizePagedView.CustomizationType.ShortcutCustomization;
+ }
+ return CustomizationType.WidgetCustomization;
+ }
}
diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java
index 98d2b83..6d3bed5 100644
--- a/src/com/android/launcher2/DeleteZone.java
+++ b/src/com/android/launcher2/DeleteZone.java
@@ -16,8 +16,10 @@
package com.android.launcher2;
-import com.android.launcher.R;
-
+import android.animation.AnimatorSet;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -29,11 +31,10 @@
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.view.animation.AnimationSet;
import android.view.animation.TranslateAnimation;
+import com.android.launcher.R;
+
public class DeleteZone extends IconDropTarget {
private static final int ORIENTATION_HORIZONTAL = 1;
private static final int TRANSITION_DURATION = 250;
@@ -42,10 +43,8 @@
private static final int XLARGE_ANIMATION_DURATION = 200;
private static final int LEFT_DRAWABLE = 0;
- private AnimationSet mInAnimation;
- private AnimationSet mOutAnimation;
- private Animation mHandleInAnimation;
- private Animation mHandleOutAnimation;
+ private AnimatorSet mInAnimation;
+ private AnimatorSet mOutAnimation;
private int mOrientation;
private DragController mDragController;
@@ -181,10 +180,10 @@
mTransition.resetTransition();
createAnimations();
- startAnimation(mInAnimation);
+ mInAnimation.start();
if (mOverlappingViews != null) {
for (View view : mOverlappingViews) {
- view.startAnimation(mHandleOutAnimation);
+ createOutAlphaAnim(view).start();
}
}
setVisibility(VISIBLE);
@@ -196,68 +195,72 @@
mActive = false;
mDragController.setDeleteRegion(null);
- if (mOutAnimation != null) startAnimation(mOutAnimation);
- if (mHandleInAnimation != null && mOverlappingViews != null) {
+ mOutAnimation.start();
+ if (mOverlappingViews != null) {
for (View view : mOverlappingViews) {
- view.startAnimation(mHandleInAnimation);
+ createInAlphaAnim(view).start();
}
}
- setVisibility(GONE);
}
}
+ private Animator createAlphaAnim(View v, float start, float end) {
+ Animator anim = ObjectAnimator.ofFloat(v, "alpha", start, end);
+ anim.setDuration(getAnimationDuration());
+ return anim;
+ }
+ private Animator createInAlphaAnim(View v) {
+ return createAlphaAnim(v, 0f, 1f);
+ }
+ private Animator createOutAlphaAnim(View v) {
+ return createAlphaAnim(v, 1f, 0f);
+ }
+
private void createAnimations() {
int duration = getAnimationDuration();
- if (mHandleInAnimation == null) {
- mHandleInAnimation = new AlphaAnimation(0.0f, 1.0f);
- mHandleInAnimation.setDuration(duration);
- }
+ Animator inAlphaAnim = createInAlphaAnim(this);
if (mInAnimation == null) {
- mInAnimation = new FastAnimationSet();
+ mInAnimation = new AnimatorSet();
+ mInAnimation.setInterpolator(new AccelerateInterpolator());
+ mInAnimation.setDuration(duration);
if (!LauncherApplication.isScreenXLarge()) {
- final AnimationSet animationSet = mInAnimation;
- animationSet.setInterpolator(new AccelerateInterpolator());
- animationSet.addAnimation(new AlphaAnimation(0.0f, 1.0f));
+ Animator translateAnim;
if (mOrientation == ORIENTATION_HORIZONTAL) {
- animationSet.addAnimation(new TranslateAnimation(Animation.ABSOLUTE, 0.0f,
- Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f,
- Animation.RELATIVE_TO_SELF, 0.0f));
+ translateAnim = ObjectAnimator.ofFloat(this, "translationY",
+ getMeasuredWidth(), 0f);
} else {
- animationSet.addAnimation(new TranslateAnimation(Animation.RELATIVE_TO_SELF,
- 1.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.ABSOLUTE, 0.0f,
- Animation.ABSOLUTE, 0.0f));
+ translateAnim = ObjectAnimator.ofFloat(this, "translationX",
+ getMeasuredHeight(), 0f);
}
- animationSet.setDuration(duration);
+ mInAnimation.playTogether(translateAnim, inAlphaAnim);
} else {
- mInAnimation.addAnimation(mHandleInAnimation);
+ mInAnimation.play(inAlphaAnim);
}
}
- if (mHandleOutAnimation == null) {
- mHandleOutAnimation = new AlphaAnimation(1.0f, 0.0f);
- mHandleOutAnimation.setFillAfter(true);
- mHandleOutAnimation.setDuration(duration);
- }
-
+ Animator outAlphaAnim = createOutAlphaAnim(this);
if (mOutAnimation == null) {
- mOutAnimation = new FastAnimationSet();
+ mOutAnimation = new AnimatorSet();
+ mOutAnimation.setInterpolator(new AccelerateInterpolator());
+ mOutAnimation.setDuration(duration);
if (!LauncherApplication.isScreenXLarge()) {
- final AnimationSet animationSet = mOutAnimation;
- animationSet.setInterpolator(new AccelerateInterpolator());
- animationSet.addAnimation(new AlphaAnimation(1.0f, 0.0f));
+ Animator translateAnim;
if (mOrientation == ORIENTATION_HORIZONTAL) {
- animationSet.addAnimation(new FastTranslateAnimation(Animation.ABSOLUTE, 0.0f,
- Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
- Animation.RELATIVE_TO_SELF, 1.0f));
+ translateAnim = ObjectAnimator.ofFloat(this, "translationY", 0f,
+ getMeasuredWidth());
} else {
- animationSet.addAnimation(new FastTranslateAnimation(Animation.RELATIVE_TO_SELF,
- 0.0f, Animation.RELATIVE_TO_SELF, 1.0f, Animation.ABSOLUTE, 0.0f,
- Animation.ABSOLUTE, 0.0f));
+ translateAnim = ObjectAnimator.ofFloat(this, "translationX", 0f,
+ getMeasuredHeight());
}
- animationSet.setDuration(duration);
+ mOutAnimation.playTogether(translateAnim, outAlphaAnim);
} else {
- mOutAnimation.addAnimation(mHandleOutAnimation);
+ mOutAnimation.addListener(new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animation) {
+ setVisibility(GONE);
+ }
+ });
+ mOutAnimation.play(outAlphaAnim);
}
}
}
@@ -275,38 +278,4 @@
return LauncherApplication.isScreenXLarge() ?
XLARGE_ANIMATION_DURATION : ANIMATION_DURATION;
}
-
- private static class FastTranslateAnimation extends TranslateAnimation {
- public FastTranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
- int fromYType, float fromYValue, int toYType, float toYValue) {
- super(fromXType, fromXValue, toXType, toXValue,
- fromYType, fromYValue, toYType, toYValue);
- }
-
- @Override
- public boolean willChangeTransformationMatrix() {
- return true;
- }
-
- @Override
- public boolean willChangeBounds() {
- return false;
- }
- }
-
- private static class FastAnimationSet extends AnimationSet {
- FastAnimationSet() {
- super(false);
- }
-
- @Override
- public boolean willChangeTransformationMatrix() {
- return true;
- }
-
- @Override
- public boolean willChangeBounds() {
- return false;
- }
- }
}
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index cb4509b..5ca1e1c 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -73,10 +73,10 @@
private boolean mDragging;
/** X coordinate of the down event. */
- private float mMotionDownX;
+ private int mMotionDownX;
/** Y coordinate of the down event. */
- private float mMotionDownY;
+ private int mMotionDownY;
/** Info about the screen for clamping. */
private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
@@ -85,10 +85,10 @@
private View mOriginator;
/** X offset from the upper-left corner of the cell to where we touched. */
- private float mTouchOffsetX;
+ private int mTouchOffsetX;
/** Y offset from the upper-left corner of the cell to where we touched. */
- private float mTouchOffsetY;
+ private int mTouchOffsetY;
/** the area at the edge of the screen that makes the workspace go left
* or right while you're dragging.
@@ -289,13 +289,14 @@
listener.onDragStart(source, dragInfo, dragAction);
}
- int registrationX = ((int)mMotionDownX) - screenX;
- int registrationY = ((int)mMotionDownY) - screenY;
+ final int registrationX = ((int)mMotionDownX) - screenX;
+ final int registrationY = ((int)mMotionDownY) - screenY;
final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
- mTouchOffsetX = mMotionDownX - screenX - dragRegionLeft;
- mTouchOffsetY = mMotionDownY - screenY - dragRegionTop;
+
+ mTouchOffsetX = mMotionDownX - (screenX + dragRegionLeft);
+ mTouchOffsetY = mMotionDownY - (screenY + dragRegionTop);
mDragging = true;
mDragSource = source;
@@ -314,8 +315,7 @@
});
if (dragRegion != null) {
- dragView.setDragRegion(dragRegionLeft, dragRegion.top,
- dragRegion.right - dragRegionLeft, dragRegion.bottom - dragRegionTop);
+ dragView.setDragRegion(new Rect(dragRegion));
}
dragView.show(mWindowToken, (int)mMotionDownX, (int)mMotionDownY);
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index eb53945..c2b710e 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -16,10 +16,11 @@
package com.android.launcher2;
-import com.android.launcher.R;
+import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -27,6 +28,8 @@
import android.widget.FrameLayout;
import android.widget.ImageView;
+import com.android.launcher.R;
+
/**
* A ViewGroup that coordinates dragging across its descendants
*/
@@ -34,6 +37,12 @@
private DragController mDragController;
private int[] mTmpXY = new int[2];
+ // Variables relating to resizing widgets
+ private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
+ new ArrayList<AppWidgetResizeFrame>();
+ private AppWidgetResizeFrame mCurrentResizeFrame;
+ private int mXDown, mYDown;
+
/**
* Used to create a new DragLayer from XML.
*
@@ -56,31 +65,66 @@
return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
}
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- // If the current CellLayoutChildren has a resize frame, we need to detect if any touch
- // event has occurred which doesn't result in resizing a widget. In this case, we
- // dismiss any visible resize frames.
- final Workspace w = (Workspace) findViewById(R.id.workspace);
- if (w != null) {
- final CellLayout currentPage = (CellLayout) w.getChildAt(w.getCurrentPage());
- final CellLayoutChildren childrenLayout = currentPage.getChildrenLayout();
+ private boolean handleTouchDown(MotionEvent ev) {
+ Rect hitRect = new Rect();
+ int x = (int) ev.getX();
+ int y = (int) ev.getY();
- if (childrenLayout.hasResizeFrames() && !childrenLayout.isWidgetBeingResized()) {
- post(new Runnable() {
- public void run() {
- if (!childrenLayout.isWidgetBeingResized()) {
- childrenLayout.clearAllResizeFrames();
- }
- }
- });
+ for (AppWidgetResizeFrame child: mResizeFrames) {
+ child.getHitRect(hitRect);
+ if (hitRect.contains(x, y)) {
+ if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
+ mCurrentResizeFrame = child;
+ mXDown = x;
+ mYDown = y;
+ requestDisallowInterceptTouchEvent(true);
+ return true;
+ }
}
}
+ return false;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ if (handleTouchDown(ev)) {
+ return true;
+ }
+ }
+ clearAllResizeFrames();
return mDragController.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
+ boolean handled = false;
+ int action = ev.getAction();
+
+ int x = (int) ev.getX();
+ int y = (int) ev.getY();
+
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ if (handleTouchDown(ev)) {
+ return true;
+ }
+ }
+ }
+
+ if (mCurrentResizeFrame != null) {
+ handled = true;
+ switch (action) {
+ case MotionEvent.ACTION_MOVE:
+ mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ mCurrentResizeFrame.commitResizeForDelta(x - mXDown, y - mYDown);
+ mCurrentResizeFrame = null;
+ }
+ }
+ if (handled) return true;
return mDragController.onTouchEvent(ev);
}
@@ -103,4 +147,94 @@
v.getLocationOnScreen(mTmpXY);
return createDragView(mDragController.getViewBitmap(v), mTmpXY[0], mTmpXY[1]);
}
+
+ public static class LayoutParams extends FrameLayout.LayoutParams {
+ public int x, y;
+ public boolean customPosition = false;
+
+ /**
+ * {@inheritDoc}
+ */
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public void setY(int y) {
+ this.y = y;
+ }
+
+ public int getY() {
+ return y;
+ }
+ }
+
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ View child = getChildAt(i);
+ final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
+ if (flp instanceof LayoutParams) {
+ final LayoutParams lp = (LayoutParams) flp;
+ if (lp.customPosition) {
+ child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
+ }
+ }
+ }
+ }
+
+ public void clearAllResizeFrames() {
+ if (mResizeFrames.size() > 0) {
+ for (AppWidgetResizeFrame frame: mResizeFrames) {
+ removeView(frame);
+ }
+ mResizeFrames.clear();
+ }
+ }
+
+ public boolean hasResizeFrames() {
+ return mResizeFrames.size() > 0;
+ }
+
+ public boolean isWidgetBeingResized() {
+ return mCurrentResizeFrame != null;
+ }
+
+ public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
+ CellLayout cellLayout) {
+ AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
+ itemInfo, widget, cellLayout, this);
+
+ LayoutParams lp = new LayoutParams(-1, -1);
+ lp.customPosition = true;
+
+ addView(resizeFrame, lp);
+ mResizeFrames.add(resizeFrame);
+
+ resizeFrame.snapToWidget(false);
+ }
}
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index 45620b9..b02e22b 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -26,6 +26,7 @@
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.os.IBinder;
import android.view.Gravity;
import android.view.View;
@@ -42,10 +43,7 @@
private int mRegistrationX;
private int mRegistrationY;
- private int mDragRegionLeft = 0;
- private int mDragRegionTop = 0;
- private int mDragRegionWidth;
- private int mDragRegionHeight;
+ private Rect mDragRegion = null;
ValueAnimator mAnim;
private float mOffsetX = 0.0f;
@@ -87,8 +85,8 @@
scale.setScale(scaleFactor, scaleFactor);
}
- final int offsetX = res.getInteger(R.integer.config_dragViewOffsetX);
- final int offsetY = res.getInteger(R.integer.config_dragViewOffsetY);
+ final int offsetX = res.getDimensionPixelSize(R.dimen.dragViewOffsetX);
+ final int offsetY = res.getDimensionPixelSize(R.dimen.dragViewOffsetY);
// Animate the view into the correct position
mAnim = ValueAnimator.ofFloat(0.0f, 1.0f);
@@ -117,7 +115,7 @@
});
mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true);
- setDragRegion(0, 0, width, height);
+ setDragRegion(new Rect(0, 0, width, height));
// The point in our scaled bitmap that the touch events are located
mRegistrationX = registrationX;
@@ -132,31 +130,32 @@
return mOffsetY;
}
- public void setDragRegion(int left, int top, int width, int height) {
- mDragRegionLeft = left;
- mDragRegionTop = top;
- mDragRegionWidth = width;
- mDragRegionHeight = height;
- }
-
public void setOnDrawRunnable(Runnable r) {
mOnDrawRunnable = r;
}
public int getDragRegionLeft() {
- return mDragRegionLeft;
+ return mDragRegion.left;
}
public int getDragRegionTop() {
- return mDragRegionTop;
+ return mDragRegion.top;
}
public int getDragRegionWidth() {
- return mDragRegionWidth;
+ return mDragRegion.width();
}
public int getDragRegionHeight() {
- return mDragRegionHeight;
+ return mDragRegion.height();
+ }
+
+ public void setDragRegion(Rect r) {
+ mDragRegion = r;
+ }
+
+ public Rect getDragRegion() {
+ return mDragRegion;
}
@Override
diff --git a/src/com/android/launcher2/FocusHelper.java b/src/com/android/launcher2/FocusHelper.java
new file mode 100644
index 0000000..c9bd58c
--- /dev/null
+++ b/src/com/android/launcher2/FocusHelper.java
@@ -0,0 +1,772 @@
+/*
+ * 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.launcher2;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+
+import com.android.launcher.R;
+
+/**
+ * A keyboard listener we set on all the button bar buttons.
+ */
+class ButtonBarKeyEventListener implements View.OnKeyListener {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ return FocusHelper.handleButtonBarButtonKeyEvent(v, keyCode, event);
+ }
+}
+
+/**
+ * A keyboard listener we set on the last tab button in AllApps to jump to then
+ * market icon and vice versa.
+ */
+class AllAppsTabKeyEventListener implements View.OnKeyListener {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ return FocusHelper.handleAllAppsTabKeyEvent(v, keyCode, event);
+ }
+}
+
+public class FocusHelper {
+ /**
+ * Private helper to get the parent TabHost in the view hiearchy.
+ */
+ private static TabHost findTabHostParent(View v) {
+ ViewParent p = v.getParent();
+ while (p != null && !(p instanceof TabHost)) {
+ p = p.getParent();
+ }
+ return (TabHost) p;
+ }
+
+ /**
+ * Handles key events in a AllApps tab between the last tab view and the shop button.
+ */
+ static boolean handleAllAppsTabKeyEvent(View v, int keyCode, KeyEvent e) {
+ final TabHost tabHost = findTabHostParent(v);
+ final ViewGroup contents = (ViewGroup)
+ tabHost.findViewById(com.android.internal.R.id.tabcontent);
+ final View shop = tabHost.findViewById(R.id.market_button);
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the shop button if we aren't on it
+ if (v != shop) {
+ shop.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the content view (down is handled by the tab key handler otherwise)
+ if (v == shop) {
+ contents.requestFocus();
+ wasHandled = true;
+ }
+ }
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Private helper to determine whether a view is visible.
+ */
+ private static boolean isVisible(View v) {
+ return v.getVisibility() == View.VISIBLE;
+ }
+
+ /**
+ * Handles key events in a PageViewExtendedLayout containing PagedViewWidgets.
+ */
+ static boolean handlePagedViewWidgetKeyEvent(PagedViewWidget w, int keyCode, KeyEvent e) {
+ if (!LauncherApplication.isScreenXLarge()) return false;
+
+ final PagedViewExtendedLayout parent = (PagedViewExtendedLayout) w.getParent();
+ final ViewGroup container = (ViewGroup) parent.getParent();
+ final TabHost tabHost = findTabHostParent(container);
+ final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs);
+ final int widgetIndex = parent.indexOfChild(w);
+ final int widgetCount = parent.getChildCount();
+ final int pageIndex = container.indexOfChild(parent);
+ final int pageCount = container.getChildCount();
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ PagedViewExtendedLayout newParent = null;
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+ // Select the previous widget or the last widget on the previous page
+ if (widgetIndex > 0) {
+ parent.getChildAt(widgetIndex - 1).requestFocus();
+ } else {
+ if (pageIndex > 0) {
+ newParent = (PagedViewExtendedLayout)
+ container.getChildAt(pageIndex - 1);
+ newParent.getChildAt(newParent.getChildCount() - 1).requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next widget or the first widget on the next page
+ if (widgetIndex < (widgetCount - 1)) {
+ parent.getChildAt(widgetIndex + 1).requestFocus();
+ } else {
+ if (pageIndex < (pageCount - 1)) {
+ newParent = (PagedViewExtendedLayout)
+ container.getChildAt(pageIndex + 1);
+ newParent.getChildAt(0).requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (handleKeyEvent) {
+ // Select widgets tab on the tab bar
+ tabs.requestFocus();
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // TODO: Should focus the global search bar
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ if (handleKeyEvent) {
+ // Simulate a click on the widget
+ View.OnClickListener clickListener = (View.OnClickListener) container;
+ clickListener.onClick(w);
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_PAGE_UP:
+ if (handleKeyEvent) {
+ // Select the first item on the previous page, or the first item on this page
+ // if there is no previous page
+ if (pageIndex > 0) {
+ newParent = (PagedViewExtendedLayout) container.getChildAt(pageIndex - 1);
+ newParent.getChildAt(0).requestFocus();
+ } else {
+ parent.getChildAt(0).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_PAGE_DOWN:
+ if (handleKeyEvent) {
+ // Select the first item on the next page, or the last item on this page
+ // if there is no next page
+ if (pageIndex < (pageCount - 1)) {
+ newParent = (PagedViewExtendedLayout) container.getChildAt(pageIndex + 1);
+ newParent.getChildAt(0).requestFocus();
+ } else {
+ parent.getChildAt(widgetCount - 1).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_HOME:
+ if (handleKeyEvent) {
+ // Select the first item on this page
+ parent.getChildAt(0).requestFocus();
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_END:
+ if (handleKeyEvent) {
+ // Select the last item on this page
+ parent.getChildAt(widgetCount - 1).requestFocus();
+ }
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Private helper method to get the PagedViewCellLayoutChildren given a PagedViewCellLayout
+ * index.
+ */
+ private static PagedViewCellLayoutChildren getPagedViewCellLayoutChildrenForIndex(
+ ViewGroup container, int i) {
+ ViewGroup parent = (ViewGroup) container.getChildAt(i);
+ return (PagedViewCellLayoutChildren) parent.getChildAt(0);
+ }
+
+ /**
+ * Handles key events in a PageViewCellLayout containing PagedViewIcons.
+ */
+ static boolean handlePagedViewIconKeyEvent(PagedViewIcon v, int keyCode, KeyEvent e) {
+ if (!LauncherApplication.isScreenXLarge()) return false;
+
+ final PagedViewCellLayoutChildren parent = (PagedViewCellLayoutChildren) v.getParent();
+ final PagedViewCellLayout parentLayout = (PagedViewCellLayout) parent.getParent();
+ // Note we have an extra parent because of the
+ // PagedViewCellLayout/PagedViewCellLayoutChildren relationship
+ final ViewGroup container = (ViewGroup) parentLayout.getParent();
+ final TabHost tabHost = findTabHostParent(container);
+ final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs);
+ final int widgetIndex = parent.indexOfChild(v);
+ final int widgetCount = parent.getChildCount();
+ final int pageIndex = container.indexOfChild(parentLayout);
+ final int pageCount = container.getChildCount();
+ final int cellCountX = parentLayout.getCellCountX();
+ final int cellCountY = parentLayout.getCellCountY();
+ final int x = widgetIndex % cellCountX;
+ final int y = widgetIndex / cellCountX;
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ PagedViewCellLayoutChildren newParent = null;
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+ // Select the previous icon or the last icon on the previous page
+ if (widgetIndex > 0) {
+ parent.getChildAt(widgetIndex - 1).requestFocus();
+ } else {
+ if (pageIndex > 0) {
+ newParent = getPagedViewCellLayoutChildrenForIndex(container,
+ pageIndex - 1);
+ newParent.getChildAt(newParent.getChildCount() - 1).requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next icon or the first icon on the next page
+ if (widgetIndex < (widgetCount - 1)) {
+ parent.getChildAt(widgetIndex + 1).requestFocus();
+ } else {
+ if (pageIndex < (pageCount - 1)) {
+ newParent = getPagedViewCellLayoutChildrenForIndex(container,
+ pageIndex + 1);
+ newParent.getChildAt(0).requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (handleKeyEvent) {
+ // Select the closest icon in the previous row, otherwise select the tab bar
+ if (y > 0) {
+ int newWidgetIndex = ((y - 1) * cellCountX) + x;
+ parent.getChildAt(newWidgetIndex).requestFocus();
+ } else {
+ tabs.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the closest icon in the previous row, otherwise do nothing
+ if (y < (cellCountY - 1)) {
+ int newWidgetIndex = Math.min(widgetCount - 1, ((y + 1) * cellCountX) + x);
+ parent.getChildAt(newWidgetIndex).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ if (handleKeyEvent) {
+ // Simulate a click on the icon
+ View.OnClickListener clickListener = (View.OnClickListener) container;
+ clickListener.onClick(v);
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_PAGE_UP:
+ if (handleKeyEvent) {
+ // Select the first icon on the previous page, or the first icon on this page
+ // if there is no previous page
+ if (pageIndex > 0) {
+ newParent = getPagedViewCellLayoutChildrenForIndex(container,
+ pageIndex - 1);
+ newParent.getChildAt(0).requestFocus();
+ } else {
+ parent.getChildAt(0).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_PAGE_DOWN:
+ if (handleKeyEvent) {
+ // Select the first icon on the next page, or the last icon on this page
+ // if there is no next page
+ if (pageIndex < (pageCount - 1)) {
+ newParent = getPagedViewCellLayoutChildrenForIndex(container,
+ pageIndex + 1);
+ newParent.getChildAt(0).requestFocus();
+ } else {
+ parent.getChildAt(widgetCount - 1).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_HOME:
+ if (handleKeyEvent) {
+ // Select the first icon on this page
+ parent.getChildAt(0).requestFocus();
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_END:
+ if (handleKeyEvent) {
+ // Select the last icon on this page
+ parent.getChildAt(widgetCount - 1).requestFocus();
+ }
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Handles key events in the tab widget.
+ */
+ static boolean handleTabKeyEvent(AccessibleTabView v, int keyCode, KeyEvent e) {
+ if (!LauncherApplication.isScreenXLarge()) return false;
+
+ final FocusOnlyTabWidget parent = (FocusOnlyTabWidget) v.getParent();
+ final TabHost tabHost = findTabHostParent(parent);
+ final ViewGroup contents = (ViewGroup)
+ tabHost.findViewById(com.android.internal.R.id.tabcontent);
+ final int tabCount = parent.getTabCount();
+ final int tabIndex = parent.getChildTabIndex(v);
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+ // Select the previous tab
+ if (tabIndex > 0) {
+ parent.getChildTabViewAt(tabIndex - 1).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next tab, or if the last tab has a focus right id, select that
+ if (tabIndex < (tabCount - 1)) {
+ parent.getChildTabViewAt(tabIndex + 1).requestFocus();
+ } else {
+ if (v.getNextFocusRightId() != View.NO_ID) {
+ tabHost.findViewById(v.getNextFocusRightId()).requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ // Do nothing
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the content view
+ contents.requestFocus();
+ }
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Handles key events in a the workspace button bar.
+ */
+ static boolean handleButtonBarButtonKeyEvent(View v, int keyCode, KeyEvent e) {
+ if (!LauncherApplication.isScreenXLarge()) return false;
+
+ final ViewGroup parent = (ViewGroup) v.getParent();
+ final ViewGroup launcher = (ViewGroup) parent.getParent();
+ final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
+ final int buttonIndex = parent.indexOfChild(v);
+ final int buttonCount = parent.getChildCount();
+ final int pageIndex = workspace.getCurrentPage();
+ final int pageCount = workspace.getChildCount();
+ final int firstButtonIndex = parent.indexOfChild(parent.findViewById(R.id.search_button));
+ final int lastButtonIndex = parent.indexOfChild(parent.findViewById(R.id.configure_button));
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+ // Select the previous button, otherwise do nothing (since the button bar is
+ // static)
+ if (buttonIndex > firstButtonIndex) {
+ int newButtonIndex = buttonIndex - 1;
+ while (newButtonIndex >= firstButtonIndex) {
+ View prev = parent.getChildAt(newButtonIndex);
+ if (isVisible(prev) && prev.isFocusable()) {
+ prev.requestFocus();
+ break;
+ }
+ --newButtonIndex;
+ }
+ } else {
+ if (pageIndex > 0) {
+ // Snap to previous page and clear focus
+ workspace.snapToPage(pageIndex - 1);
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next button, otherwise do nothing (since the button bar is
+ // static)
+ if (buttonIndex < lastButtonIndex) {
+ int newButtonIndex = buttonIndex + 1;
+ while (newButtonIndex <= lastButtonIndex) {
+ View next = parent.getChildAt(newButtonIndex);
+ if (isVisible(next) && next.isFocusable()) {
+ next.requestFocus();
+ break;
+ }
+ ++newButtonIndex;
+ }
+ } else {
+ if (pageIndex < (pageCount - 1)) {
+ // Snap to next page and clear focus
+ workspace.snapToPage(pageIndex + 1);
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ // Do nothing
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the first bubble text view in the current page of the workspace
+ final CellLayout layout = (CellLayout) workspace.getChildAt(pageIndex);
+ final CellLayoutChildren children = layout.getChildrenLayout();
+ final View newIcon = getBubbleTextViewInDirection(layout, children, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ workspace.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Private helper method to get the CellLayoutChildren given a CellLayout index.
+ */
+ private static CellLayoutChildren getCellLayoutChildrenForIndex(ViewGroup container, int i) {
+ ViewGroup parent = (ViewGroup) container.getChildAt(i);
+ return (CellLayoutChildren) parent.getChildAt(0);
+ }
+
+ /**
+ * Private helper method to sort all the CellLayout children in order of their (x,y) spatially
+ * from top left to bottom right.
+ */
+ private static ArrayList<View> getCellLayoutChildrenSortedSpatially(CellLayout layout,
+ ViewGroup parent) {
+ // First we order each the CellLayout children by their x,y coordinates
+ final int cellCountX = layout.getCountX();
+ final int count = parent.getChildCount();
+ ArrayList<View> views = new ArrayList<View>();
+ for (int j = 0; j < count; ++j) {
+ views.add(parent.getChildAt(j));
+ }
+ Collections.sort(views, new Comparator<View>() {
+ @Override
+ public int compare(View lhs, View rhs) {
+ CellLayout.LayoutParams llp = (CellLayout.LayoutParams) lhs.getLayoutParams();
+ CellLayout.LayoutParams rlp = (CellLayout.LayoutParams) rhs.getLayoutParams();
+ int lvIndex = (llp.cellY * cellCountX) + llp.cellX;
+ int rvIndex = (rlp.cellY * cellCountX) + rlp.cellX;
+ return lvIndex - rvIndex;
+ }
+ });
+ return views;
+ }
+ /**
+ * Private helper method to find the index of the next BubbleTextView in the delta direction.
+ * @param delta either -1 or 1 depending on the direction we want to search
+ */
+ private static View findIndexOfBubbleTextView(ArrayList<View> views, int i, int delta) {
+ // Then we find the next BubbleTextView offset by delta from i
+ final int count = views.size();
+ int newI = i + delta;
+ while (0 <= newI && newI < count) {
+ View newV = views.get(newI);
+ if (newV instanceof BubbleTextView) {
+ return newV;
+ }
+ newI += delta;
+ }
+ return null;
+ }
+ private static View getBubbleTextViewInDirection(CellLayout layout, ViewGroup parent, int i,
+ int delta) {
+ final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+ return findIndexOfBubbleTextView(views, i, delta);
+ }
+ private static View getBubbleTextViewInDirection(CellLayout layout, ViewGroup parent, View v,
+ int delta) {
+ final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+ return findIndexOfBubbleTextView(views, views.indexOf(v), delta);
+ }
+ /**
+ * Private helper method to find the next closest BubbleTextView in the delta direction on the
+ * next line.
+ * @param delta either -1 or 1 depending on the line and direction we want to search
+ */
+ private static View getClosestBubbleTextViewOnLine(CellLayout layout, ViewGroup parent, View v,
+ int lineDelta) {
+ final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+ final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
+ final int cellCountX = layout.getCountX();
+ final int cellCountY = layout.getCountY();
+ final int row = lp.cellY;
+ final int newRow = row + lineDelta;
+ if (0 <= newRow && newRow < cellCountY) {
+ float closestDistance = Float.MAX_VALUE;
+ int closestIndex = -1;
+ int index = views.indexOf(v);
+ int endIndex = (lineDelta < 0) ? -1 : views.size();
+ while (index != endIndex) {
+ View newV = views.get(index);
+ CellLayout.LayoutParams tmpLp = (CellLayout.LayoutParams) newV.getLayoutParams();
+ boolean satisfiesRow = (lineDelta < 0) ? (tmpLp.cellY < row) : (tmpLp.cellY > row);
+ if (satisfiesRow && newV instanceof BubbleTextView) {
+ float tmpDistance = (float) Math.sqrt(Math.pow(tmpLp.cellX - lp.cellX, 2) +
+ Math.pow(tmpLp.cellY - lp.cellY, 2));
+ if (tmpDistance < closestDistance) {
+ closestIndex = index;
+ closestDistance = tmpDistance;
+ }
+ }
+ if (index <= endIndex) {
+ ++index;
+ } else {
+ --index;
+ }
+ }
+ if (closestIndex > -1) {
+ return views.get(closestIndex);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Handles key events in a Workspace containing BubbleTextView.
+ */
+ static boolean handleBubbleTextViewKeyEvent(BubbleTextView v, int keyCode, KeyEvent e) {
+ if (!LauncherApplication.isScreenXLarge()) return false;
+
+ CellLayoutChildren parent = (CellLayoutChildren) v.getParent();
+ final CellLayout layout = (CellLayout) parent.getParent();
+ final Workspace workspace = (Workspace) layout.getParent();
+ final ViewGroup launcher = (ViewGroup) workspace.getParent();
+ final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.all_apps_button_cluster);
+ int iconIndex = parent.indexOfChild(v);
+ int iconCount = parent.getChildCount();
+ int pageIndex = workspace.indexOfChild(layout);
+ int pageCount = workspace.getChildCount();
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+ // Select the previous icon or the last icon on the previous page if possible
+ View newIcon = getBubbleTextViewInDirection(layout, parent, v, -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ if (pageIndex > 0) {
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+ newIcon = getBubbleTextViewInDirection(layout, parent,
+ parent.getChildCount(), -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ // Snap to the previous page
+ workspace.snapToPage(pageIndex - 1);
+ }
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next icon or the first icon on the next page if possible
+ View newIcon = getBubbleTextViewInDirection(layout, parent, v, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ if (pageIndex < (pageCount - 1)) {
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
+ newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ // Snap to the next page
+ workspace.snapToPage(pageIndex + 1);
+ }
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (handleKeyEvent) {
+ // Select the closest icon in the previous line, otherwise select the tab bar
+ View newIcon = getClosestBubbleTextViewOnLine(layout, parent, v, -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ wasHandled = true;
+ } else {
+ tabs.requestFocus();
+ }
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the closest icon in the next line, otherwise select the tab bar
+ View newIcon = getClosestBubbleTextViewOnLine(layout, parent, v, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ wasHandled = true;
+ }
+ }
+ break;
+ case KeyEvent.KEYCODE_PAGE_UP:
+ if (handleKeyEvent) {
+ // Select the first icon on the previous page or the first icon on this page
+ // if there is no previous page
+ if (pageIndex > 0) {
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+ View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ // Snap to the previous page
+ workspace.snapToPage(pageIndex - 1);
+ }
+ } else {
+ View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_PAGE_DOWN:
+ if (handleKeyEvent) {
+ // Select the first icon on the next page or the last icon on this page
+ // if there is no previous page
+ if (pageIndex < (pageCount - 1)) {
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
+ View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ // Snap to the next page
+ workspace.snapToPage(pageIndex + 1);
+ }
+ } else {
+ View newIcon = getBubbleTextViewInDirection(layout, parent,
+ parent.getChildCount(), -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_HOME:
+ if (handleKeyEvent) {
+ // Select the first icon on this page
+ View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_END:
+ if (handleKeyEvent) {
+ // Select the last icon on this page
+ View newIcon = getBubbleTextViewInDirection(layout, parent,
+ parent.getChildCount(), -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+}
diff --git a/src/com/android/launcher2/FocusOnlyTabWidget.java b/src/com/android/launcher2/FocusOnlyTabWidget.java
new file mode 100644
index 0000000..8e9f58c
--- /dev/null
+++ b/src/com/android/launcher2/FocusOnlyTabWidget.java
@@ -0,0 +1,86 @@
+/*
+ * 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.launcher2;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TabWidget;
+
+public class FocusOnlyTabWidget extends TabWidget {
+ public FocusOnlyTabWidget(Context context) {
+ super(context);
+ }
+
+ public FocusOnlyTabWidget(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public FocusOnlyTabWidget(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public View getSelectedTab() {
+ final int count = getTabCount();
+ for (int i = 0; i < count; ++i) {
+ View v = getChildTabViewAt(i);
+ if (v.isSelected()) {
+ return v;
+ }
+ }
+ return null;
+ }
+
+ public int getChildTabIndex(View v) {
+ final int tabCount = getTabCount();
+ for (int i = 0; i < tabCount; ++i) {
+ if (getChildTabViewAt(i) == v) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void setCurrentTabToFocusedTab() {
+ View tab = null;
+ int index = -1;
+ final int count = getTabCount();
+ for (int i = 0; i < count; ++i) {
+ View v = getChildTabViewAt(i);
+ if (v.hasFocus()) {
+ tab = v;
+ index = i;
+ break;
+ }
+ }
+ if (index > -1) {
+ super.setCurrentTab(index);
+ super.onFocusChange(tab, true);
+ }
+ }
+ public void superOnFocusChange(View v, boolean hasFocus) {
+ super.onFocusChange(v, hasFocus);
+ }
+
+ @Override
+ public void onFocusChange(android.view.View v, boolean hasFocus) {
+ if (v == this && hasFocus && getTabCount() > 0) {
+ getSelectedTab().requestFocus();
+ return;
+ }
+ }
+}
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 059e73d..33a1cd3 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -37,7 +37,6 @@
public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener,
OnItemClickListener, OnClickListener, View.OnLongClickListener {
- protected AbsListView mContent;
protected DragController mDragController;
protected Launcher mLauncher;
@@ -66,10 +65,6 @@
protected void onFinishInflate() {
super.onFinishInflate();
- mContent = (AbsListView) findViewById(R.id.folder_content);
- mContent.setOnItemClickListener(this);
- mContent.setOnItemLongClickListener(this);
-
mCloseButton = (Button) findViewById(R.id.folder_close);
mCloseButton.setOnClickListener(this);
mCloseButton.setOnLongClickListener(this);
@@ -121,18 +116,7 @@
public void onDragViewVisible() {
}
- /**
- * Sets the adapter used to populate the content area. The adapter must only
- * contains ShortcutInfo items.
- *
- * @param adapter The list of applications to display in the folder.
- */
- void setContentAdapter(BaseAdapter adapter) {
- mContent.setAdapter(adapter);
- }
-
void notifyDataSetChanged() {
- ((BaseAdapter) mContent.getAdapter()).notifyDataSetChanged();
}
void setLauncher(Launcher launcher) {
@@ -146,10 +130,7 @@
return mInfo;
}
- // When the folder opens, we need to refresh the GridView's selection by
- // forcing a layout
void onOpen() {
- mContent.requestLayout();
}
void onClose() {
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index dd83c78..1122d77 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -43,7 +43,10 @@
}
public boolean isDropEnabled() {
- return !((Workspace)getParent().getParent()).isSmall();
+ final ViewGroup cellLayoutChildren = (ViewGroup) getParent();
+ final ViewGroup cellLayout = (ViewGroup) cellLayoutChildren.getParent();
+ final Workspace workspace = (Workspace) cellLayout.getParent();
+ return !workspace.isSmall();
}
static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
@@ -74,6 +77,11 @@
&& item.container != mInfo.id;
}
+ public void addItem(ShortcutInfo item) {
+ mInfo.add(item);
+ LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
+ }
+
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
ShortcutInfo item;
@@ -83,8 +91,9 @@
} else {
item = (ShortcutInfo)dragInfo;
}
- mInfo.add(item);
- LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
+ item.cellX = -1;
+ item.cellY = -1;
+ addItem(item);
}
public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index d7a360d..60cab8e 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -19,13 +19,11 @@
import com.android.common.Search;
import com.android.launcher.R;
-import com.android.launcher2.CustomizePagedView.CustomizationType;
import com.android.launcher2.Workspace.ShrinkState;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
@@ -98,11 +96,8 @@
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TabHost;
-import android.widget.TabWidget;
import android.widget.TextView;
import android.widget.Toast;
-import android.widget.TabHost.OnTabChangeListener;
-import android.widget.TabHost.TabContentFactory;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -112,7 +107,6 @@
import java.util.HashMap;
import java.util.List;
-
/**
* Default launcher application.
*/
@@ -172,12 +166,6 @@
// Type: long
private static final String RUNTIME_STATE_PENDING_FOLDER_RENAME_ID = "launcher.rename_folder_id";
- // tags for the customization tabs
- private static final String WIDGETS_TAG = "widgets";
- private static final String APPLICATIONS_TAG = "applications";
- private static final String SHORTCUTS_TAG = "shortcuts";
- private static final String WALLPAPERS_TAG = "wallpapers";
-
private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon";
/** The different states that Launcher can be in. */
@@ -214,10 +202,10 @@
private DeleteZone mDeleteZone;
private HandleView mHandleView;
private AllAppsView mAllAppsGrid;
- private TabHost mHomeCustomizationDrawer;
+ private CustomizeTrayTabHost mHomeCustomizationDrawer;
private boolean mAutoAdvanceRunning = false;
- private View mButtonCluster;
+ private ViewGroup mButtonCluster;
private View mAllAppsButton;
private View mDivider;
private View mConfigureButton;
@@ -293,19 +281,6 @@
int cellY;
}
- private CustomizationType getCustomizeFilterForTabTag(String tag) {
- if (tag.equals(WIDGETS_TAG)) {
- return CustomizationType.WidgetCustomization;
- } else if (tag.equals(APPLICATIONS_TAG)) {
- return CustomizationType.ApplicationCustomization;
- } else if (tag.equals(WALLPAPERS_TAG)) {
- return CustomizePagedView.CustomizationType.WallpaperCustomization;
- } else if (tag.equals(SHORTCUTS_TAG)) {
- return CustomizePagedView.CustomizationType.ShortcutCustomization;
- }
- return CustomizationType.WidgetCustomization;
- }
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -334,68 +309,11 @@
loadHotseats();
checkForLocaleChange();
setContentView(R.layout.launcher);
- mHomeCustomizationDrawer = (TabHost) findViewById(R.id.customization_drawer);
+ mHomeCustomizationDrawer = (CustomizeTrayTabHost) findViewById(R.id.customization_drawer);
if (mHomeCustomizationDrawer != null) {
- mHomeCustomizationDrawer.setup();
-
// share the same customization workspace across all the tabs
- mCustomizePagedView = (CustomizePagedView) mInflater.inflate(
- R.layout.customization_drawer_tab_contents, mHomeCustomizationDrawer, false);
- TabContentFactory contentFactory = new TabContentFactory() {
- public View createTabContent(String tag) {
- return mCustomizePagedView;
- }
- };
-
-
- TextView tabView;
- TabWidget tabWidget = (TabWidget)
- mHomeCustomizationDrawer.findViewById(com.android.internal.R.id.tabs);
-
- tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
- tabView.setText(getString(R.string.widgets_tab_label));
- mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(WIDGETS_TAG)
- .setIndicator(tabView).setContent(contentFactory));
- tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
- tabView.setText(getString(R.string.applications_tab_label));
- mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(APPLICATIONS_TAG)
- .setIndicator(tabView).setContent(contentFactory));
- tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
- tabView.setText(getString(R.string.wallpapers_tab_label));
- mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(WALLPAPERS_TAG)
- .setIndicator(tabView).setContent(contentFactory));
- tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
- tabView.setText(getString(R.string.shortcuts_tab_label));
- mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(SHORTCUTS_TAG)
- .setIndicator(tabView).setContent(contentFactory));
- mHomeCustomizationDrawer.setOnTabChangedListener(new OnTabChangeListener() {
- public void onTabChanged(String tabId) {
- final CustomizePagedView.CustomizationType newType =
- getCustomizeFilterForTabTag(tabId);
- if (newType != mCustomizePagedView.getCustomizationFilter()) {
- // animate the changing of the tab content by fading pages in and out
- final Resources res = getResources();
- final int duration = res.getInteger(R.integer.config_tabTransitionTime);
- final float alpha = mCustomizePagedView.getAlpha();
- ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mCustomizePagedView,
- "alpha", alpha, 0.0f);
- alphaAnim.setDuration(duration);
- alphaAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mCustomizePagedView.setCustomizationFilter(newType);
-
- final float alpha = mCustomizePagedView.getAlpha();
- ValueAnimator alphaAnim = ObjectAnimator.ofFloat(
- mCustomizePagedView, "alpha", alpha, 1.0f);
- alphaAnim.setDuration(duration);
- alphaAnim.start();
- }
- });
- alphaAnim.start();
- }
- }
- });
+ mCustomizePagedView = (CustomizePagedView) findViewById(
+ R.id.customization_drawer_tab_contents);
}
setupViews();
@@ -851,8 +769,10 @@
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- boolean handled = super.onKeyDown(keyCode, event);
- if (!handled && acceptFilter() && keyCode != KeyEvent.KEYCODE_ENTER) {
+ final int uniChar = event.getUnicodeChar();
+ final boolean handled = super.onKeyDown(keyCode, event);
+ final boolean isKeyNotWhitespace = uniChar > 0 && !Character.isWhitespace(uniChar);
+ if (!handled && acceptFilter() && isKeyNotWhitespace) {
boolean gotKey = TextKeyListener.getInstance().onKeyDown(mWorkspace, mDefaultKeySsb,
keyCode, event);
if (gotKey && mDefaultKeySsb != null && mDefaultKeySsb.length() > 0) {
@@ -957,7 +877,8 @@
String curTab = savedState.getString("customize_currentTab");
if (curTab != null) {
// We set this directly so that there is no delay before the tab is set
- mCustomizePagedView.setCustomizationFilter(getCustomizeFilterForTabTag(curTab));
+ mCustomizePagedView.setCustomizationFilter(
+ mHomeCustomizationDrawer.getCustomizeFilterForTabTag(curTab));
mHomeCustomizationDrawer.setCurrentTabByTag(curTab);
}
@@ -1039,7 +960,7 @@
deleteZone.setDragController(dragController);
final View allAppsButton = findViewById(R.id.all_apps_button);
- final View divider = findViewById(R.id.divider);
+ final View divider = findViewById(R.id.all_apps_divider);
final View configureButton = findViewById(R.id.configure_button);
if (LauncherApplication.isScreenXLarge()) {
@@ -1088,10 +1009,15 @@
if (allAppsDeleteZone != null) {
dragController.addDropTarget(allAppsDeleteZone);
}
- mButtonCluster = findViewById(R.id.all_apps_button_cluster);
+ mButtonCluster = (ViewGroup) findViewById(R.id.all_apps_button_cluster);
+ View.OnKeyListener listener = new ButtonBarKeyEventListener();
+ int buttonCount = mButtonCluster.getChildCount();
+ for (int i = 0; i < buttonCount; ++i) {
+ mButtonCluster.getChildAt(i).setOnKeyListener(listener);
+ }
mAllAppsButton = findViewById(R.id.all_apps_button);
- mDivider = findViewById(R.id.divider);
+ mDivider = findViewById(R.id.all_apps_divider);
mConfigureButton = findViewById(R.id.configure_button);
// We had previously set these click handlers in XML, but the first time we launched
@@ -1332,6 +1258,11 @@
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
mUserPresent = false;
updateRunning();
+
+ // Reset AllApps to it's initial state
+ if (mAllAppsGrid != null) {
+ mAllAppsGrid.reset();
+ }
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
mUserPresent = true;
updateRunning();
@@ -1503,6 +1434,11 @@
INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
+
+ // Reset AllApps to it's initial state
+ if (mAllAppsGrid != null) {
+ mAllAppsGrid.reset();
+ }
}
}
@@ -1872,7 +1808,7 @@
}
}
- void addFolder(int screen, int intersectCellX, int intersectCellY) {
+ FolderIcon addFolder(int screen, int intersectCellX, int intersectCellY) {
UserFolderInfo folderInfo = new UserFolderInfo();
folderInfo.title = getText(R.string.folder_name);
@@ -1880,7 +1816,7 @@
final int[] cellXY = mTmpAddItemCellCoordinates;
if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
showOutOfSpaceMessage();
- return;
+ return null;
}
// Update the model
@@ -1894,6 +1830,7 @@
(ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()),
folderInfo, mIconCache);
mWorkspace.addInScreen(newFolder, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
+ return newFolder;
}
void removeFolder(FolderInfo folder) {
@@ -2645,7 +2582,6 @@
private void showAndEnableToolbarButton(View button) {
button.setVisibility(View.VISIBLE);
- button.setFocusable(true);
button.setClickable(true);
}
@@ -2656,7 +2592,6 @@
}
private void disableToolbarButton(View button) {
- button.setFocusable(false);
button.setClickable(false);
}
@@ -2764,7 +2699,7 @@
* of the screen.
* @param toState The state to zoom out to. Must be ALL_APPS or CUSTOMIZE.
*/
- private void cameraZoomOut(State toState, boolean animated) {
+ private void cameraZoomOut(State toState, boolean animated, boolean springLoaded) {
final Resources res = getResources();
final boolean toAllApps = (toState == State.ALL_APPS);
@@ -2784,7 +2719,15 @@
setPivotsForZoom(toView, toState, scale);
if (toAllApps) {
- mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
+ if (!springLoaded) {
+ mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
+
+ // Everytime we launch into AllApps, we reset the successful drop flag which
+ // controls when it should hide/show the mini workspaces
+ mAllAppsPagedView.resetSuccessfulDropFlag();
+ } else {
+ mWorkspace.shrink(ShrinkState.BOTTOM_VISIBLE, animated);
+ }
} else {
mWorkspace.shrink(ShrinkState.TOP, animated);
}
@@ -2792,10 +2735,8 @@
if (animated) {
final ValueAnimator scaleAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
scaleAnim.setInterpolator(new Workspace.ZoomOutInterpolator());
- scaleAnim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
+ scaleAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
((View) toView.getParent()).fastInvalidate();
toView.setFastScaleX(a * scale + b * 1f);
toView.setFastScaleY(a * scale + b * 1f);
@@ -2806,10 +2747,8 @@
toView.setFastAlpha(0f);
ValueAnimator alphaAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(fadeDuration);
alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
- alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
+ alphaAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
// don't need to invalidate because we do so above
toView.setFastAlpha(a * 0f + b * 1f);
}
@@ -2880,10 +2819,6 @@
* @param fromState The current state (must be ALL_APPS or CUSTOMIZE).
* @param animated If true, the transition will be animated.
*/
- private void cameraZoomIn(State fromState, boolean animated) {
- cameraZoomIn(fromState, animated, false);
- }
-
private void cameraZoomIn(State fromState, boolean animated, boolean springLoaded) {
Resources res = getResources();
final boolean fromAllApps = (fromState == State.ALL_APPS);
@@ -2906,7 +2841,6 @@
if (!springLoaded) {
mWorkspace.unshrink(animated);
}
-
if (animated) {
if (mStateAnimation != null) mStateAnimation.cancel();
mStateAnimation = new AnimatorSet();
@@ -2916,10 +2850,8 @@
ValueAnimator scaleAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
scaleAnim.setInterpolator(new Workspace.ZoomInInterpolator());
- scaleAnim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
+ scaleAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
((View)fromView.getParent()).fastInvalidate();
fromView.setFastScaleX(a * oldScaleX + b * scaleFactor);
fromView.setFastScaleY(a * oldScaleY + b * scaleFactor);
@@ -2928,10 +2860,8 @@
final ValueAnimator alphaAnim = ValueAnimator.ofFloat(0f, 1f);
alphaAnim.setDuration(res.getInteger(R.integer.config_allAppsFadeOutTime));
alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
- alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
+ alphaAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
// don't need to invalidate because we do so above
fromView.setFastAlpha(a * 1f + b * 0f);
}
@@ -2980,7 +2910,7 @@
}
if (LauncherApplication.isScreenXLarge()) {
- cameraZoomOut(State.ALL_APPS, animated);
+ cameraZoomOut(State.ALL_APPS, animated, false);
} else {
mAllAppsGrid.zoom(1.0f, animated);
}
@@ -3034,11 +2964,11 @@
void enterSpringLoadedDragMode(CellLayout layout) {
mWorkspace.enterSpringLoadedDragMode(layout);
if (mState == State.ALL_APPS) {
- cameraZoomIn(State.ALL_APPS, true, true);
mState = State.ALL_APPS_SPRING_LOADED;
+ cameraZoomIn(State.ALL_APPS, true, true);
} else if (mState == State.CUSTOMIZE) {
- cameraZoomIn(State.CUSTOMIZE, true, true);
mState = State.CUSTOMIZE_SPRING_LOADED;
+ cameraZoomIn(State.CUSTOMIZE, true, true);
}/* else {
// we're already in spring loaded mode; don't do anything
}*/
@@ -3047,11 +2977,11 @@
void exitSpringLoadedDragMode() {
if (mState == State.ALL_APPS_SPRING_LOADED) {
mWorkspace.exitSpringLoadedDragMode(Workspace.ShrinkState.BOTTOM_VISIBLE);
- cameraZoomOut(State.ALL_APPS, true);
+ cameraZoomOut(State.ALL_APPS, true, true);
mState = State.ALL_APPS;
} else if (mState == State.CUSTOMIZE_SPRING_LOADED) {
mWorkspace.exitSpringLoadedDragMode(Workspace.ShrinkState.TOP);
- cameraZoomOut(State.CUSTOMIZE, true);
+ cameraZoomOut(State.CUSTOMIZE, true, true);
mState = State.CUSTOMIZE;
}/* else {
// we're not in spring loaded mode; don't do anything
@@ -3101,12 +3031,12 @@
if (mState == State.ALL_APPS || mState == State.ALL_APPS_SPRING_LOADED) {
mWorkspace.setVisibility(View.VISIBLE);
if (LauncherApplication.isScreenXLarge()) {
- cameraZoomIn(State.ALL_APPS, animated);
+ cameraZoomIn(State.ALL_APPS, animated, false);
} else {
mAllAppsGrid.zoom(0.0f, animated);
}
((View)mAllAppsGrid).setFocusable(false);
- mWorkspace.getChildAt(mWorkspace.getCurrentPage()).requestFocus();
+ ((CellLayout) mWorkspace.getChildAt(mWorkspace.getCurrentPage())).getChildrenLayout().requestFocus();
}
}
@@ -3124,7 +3054,7 @@
return;
}
- cameraZoomOut(State.CUSTOMIZE, animated);
+ cameraZoomOut(State.CUSTOMIZE, animated, false);
// Change the state *after* we've called all the transition code
mState = State.CUSTOMIZE;
@@ -3137,7 +3067,7 @@
// Hide the customization drawer (only exists in x-large configuration)
void hideCustomizationDrawer(boolean animated) {
if (mState == State.CUSTOMIZE || mState == State.CUSTOMIZE_SPRING_LOADED) {
- cameraZoomIn(State.CUSTOMIZE, animated);
+ cameraZoomIn(State.CUSTOMIZE, animated, false);
}
}
@@ -3220,14 +3150,20 @@
private void updateGlobalSearchIcon() {
if (LauncherApplication.isScreenXLarge()) {
+ final View searchButton = findViewById(R.id.search_button);
+ final View searchDivider = findViewById(R.id.search_divider);
+
final SearchManager searchManager =
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
ComponentName activityName = searchManager.getGlobalSearchActivity();
if (activityName != null) {
sGlobalSearchIcon = updateButtonWithIconFromExternalActivity(
R.id.search_button, activityName, R.drawable.ic_generic_search);
+ searchButton.setVisibility(View.VISIBLE);
+ searchDivider.setVisibility(View.VISIBLE);
} else {
- findViewById(R.id.search_button).setVisibility(View.GONE);
+ searchButton.setVisibility(View.GONE);
+ searchDivider.setVisibility(View.GONE);
}
}
}
@@ -3238,13 +3174,19 @@
private void updateVoiceSearchIcon() {
if (LauncherApplication.isScreenXLarge()) {
+ final View searchDivider = findViewById(R.id.search_divider);
+ final View voiceButton = findViewById(R.id.voice_button);
+
Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
ComponentName activityName = intent.resolveActivity(getPackageManager());
if (activityName != null) {
sVoiceSearchIcon = updateButtonWithIconFromExternalActivity(
R.id.voice_button, activityName, R.drawable.ic_voice_search);
+ searchDivider.setVisibility(View.VISIBLE);
+ voiceButton.setVisibility(View.VISIBLE);
} else {
- findViewById(R.id.voice_button).setVisibility(View.GONE);
+ searchDivider.setVisibility(View.GONE);
+ voiceButton.setVisibility(View.GONE);
}
}
}
@@ -3455,6 +3397,8 @@
*/
public void startBinding() {
final Workspace workspace = mWorkspace;
+
+ mWorkspace.clearDropTargets();
int count = workspace.getChildCount();
for (int i = 0; i < count; i++) {
// Use removeAllViewsInLayout() to avoid an extra requestLayout() and invalidate().
diff --git a/src/com/android/launcher2/LauncherAnimatorUpdateListener.java b/src/com/android/launcher2/LauncherAnimatorUpdateListener.java
new file mode 100644
index 0000000..dd82113
--- /dev/null
+++ b/src/com/android/launcher2/LauncherAnimatorUpdateListener.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.launcher2;
+
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+
+abstract class LauncherAnimatorUpdateListener implements AnimatorUpdateListener {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float b = (Float) animation.getAnimatedValue();
+ final float a = 1f - b;
+ onAnimationUpdate(a, b);
+ }
+
+ abstract void onAnimationUpdate(float a, float b);
+}
\ No newline at end of file
diff --git a/src/com/android/launcher2/LauncherAppWidgetHostView.java b/src/com/android/launcher2/LauncherAppWidgetHostView.java
index 7f60cac..0dd1d83 100644
--- a/src/com/android/launcher2/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher2/LauncherAppWidgetHostView.java
@@ -22,6 +22,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.ViewGroup;
import com.android.launcher.R;
@@ -122,4 +123,9 @@
}
super.onVisibilityChanged(changedView, visibility);
}
+
+ @Override
+ public int getDescendantFocusability() {
+ return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+ }
}
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index c098749..e432733 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -91,9 +91,6 @@
private AllAppsList mAllAppsList; // only access in worker thread
private IconCache mIconCache;
- final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
- final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
- final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
private Bitmap mDefaultIcon;
@@ -522,9 +519,6 @@
mLoaderTask.stopLocked();
}
}
- mItems.clear();
- mAppWidgets.clear();
- mFolders.clear();
}
/**
@@ -540,6 +534,10 @@
private boolean mStopped;
private boolean mLoadAndBindStepFinished;
+ final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
+ final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
+ final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
+
LoaderTask(Context context, boolean isLaunching) {
mContext = context;
mIsLaunching = isLaunching;
@@ -1294,6 +1292,7 @@
Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);
Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);
Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
+ Log.d(TAG, "mItems size=" + mItems.size());
}
}
@@ -1797,7 +1796,6 @@
ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.added", mAllAppsList.added);
ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.removed", mAllAppsList.removed);
ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.modified", mAllAppsList.modified);
- Log.d(TAG, "mItems size=" + mItems.size());
if (mLoaderTask != null) {
mLoaderTask.dumpState();
} else {
diff --git a/src/com/android/launcher2/LiveFolder.java b/src/com/android/launcher2/LiveFolder.java
index 07a295f..b692953 100644
--- a/src/com/android/launcher2/LiveFolder.java
+++ b/src/com/android/launcher2/LiveFolder.java
@@ -22,10 +22,12 @@
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
+import android.widget.BaseAdapter;
import android.net.Uri;
import android.provider.LiveFolders;
import android.os.AsyncTask;
import android.database.Cursor;
+import android.widget.GridView;
import java.lang.ref.WeakReference;
@@ -33,6 +35,7 @@
public class LiveFolder extends Folder {
private AsyncTask<LiveFolderInfo,Void,Cursor> mLoadingTask;
+ protected GridView mContent;
public LiveFolder(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -44,6 +47,15 @@
return (LiveFolder) LayoutInflater.from(context).inflate(layout, null);
}
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mContent = (GridView) findViewById(R.id.folder_content);
+ mContent.setOnItemClickListener(this);
+ mContent.setOnItemLongClickListener(this);
+ }
+
private static boolean isDisplayModeList(FolderInfo folderInfo) {
return ((LiveFolderInfo) folderInfo).displayMode ==
LiveFolders.DISPLAY_MODE_LIST;
@@ -68,6 +80,21 @@
}
}
+ /**
+ * Sets the adapter used to populate the content area. The adapter must only
+ * contains ShortcutInfo items.
+ *
+ * @param adapter The list of applications to display in the folder.
+ */
+ void setContentAdapter(BaseAdapter adapter) {
+ mContent.setAdapter(adapter);
+ }
+
+ @Override
+ void notifyDataSetChanged() {
+ ((BaseAdapter) mContent.getAdapter()).notifyDataSetChanged();
+ }
+
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
return false;
@@ -84,6 +111,9 @@
@Override
void onOpen() {
super.onOpen();
+ // When the folder opens, we need to refresh the GridView's selection by
+ // forcing a layout
+ mContent.requestLayout();
requestFocus();
}
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index e7ecb99..9eae647 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -110,6 +110,7 @@
protected int mPageLayoutPaddingRight;
protected int mPageLayoutWidthGap;
protected int mPageLayoutHeightGap;
+ protected int mPageLayoutMaxHeight;
protected int mCellCountX;
protected int mCellCountY;
protected boolean mCenterPagesVertically;
@@ -189,6 +190,8 @@
R.styleable.PagedView_pageLayoutWidthGap, -1);
mPageLayoutHeightGap = a.getDimensionPixelSize(
R.styleable.PagedView_pageLayoutHeightGap, -1);
+ mPageLayoutMaxHeight = a.getDimensionPixelSize(
+ R.styleable.PagedView_pageLayoutMaxHeight, -1);
a.recycle();
setHapticFeedbackEnabled(false);
@@ -289,6 +292,10 @@
mIsPageMoving = false;
}
+ protected boolean isPageMoving() {
+ return mIsPageMoving;
+ }
+
// a method that subclasses can override to add behavior
protected void onPageBeginMoving() {
}
@@ -384,6 +391,10 @@
final int verticalPadding = mPaddingTop + mPaddingBottom;
+ if (mPageLayoutMaxHeight != -1) {
+ heightSize = Math.min(mPageLayoutMaxHeight, heightSize);
+ }
+
// The children are given the same width and height as the workspace
// unless they were set to WRAP_CONTENT
final int childCount = getChildCount();
@@ -1155,7 +1166,7 @@
public void requestChildFocus(View child, View focused) {
super.requestChildFocus(child, focused);
int page = indexOfChild(child);
- if (page >= 0 && !isInTouchMode()) {
+ if (page >= 0 && page != getCurrentPage() && !isInTouchMode()) {
snapToPage(page);
}
}
@@ -1177,6 +1188,9 @@
protected void setMinimumWidthOverride(int minimumWidth) {
mMinimumWidth = minimumWidth;
}
+ protected void resetMinimumWidthOverride() {
+ mMinimumWidth = 0;
+ }
protected int getChildWidth(int index) {
return Math.max(mMinimumWidth, getChildAt(index).getMeasuredWidth());
diff --git a/src/com/android/launcher2/PagedViewCellLayout.java b/src/com/android/launcher2/PagedViewCellLayout.java
index 28bb78b..28e092e 100644
--- a/src/com/android/launcher2/PagedViewCellLayout.java
+++ b/src/com/android/launcher2/PagedViewCellLayout.java
@@ -180,6 +180,14 @@
return mChildren.indexOfChild(v);
}
+ public int getCellCountX() {
+ return mCellCountX;
+ }
+
+ public int getCellCountY() {
+ return mCellCountY;
+ }
+
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO: currently ignoring padding
@@ -243,6 +251,18 @@
setMeasuredDimension(newWidth, newHeight);
}
+ int getContentWidth() {
+ // Return the distance from the left edge of the content of the leftmost icon to
+ // the right edge of the content of the rightmost icon
+
+ // icons are centered within cells, find out how much padding that accounts for
+ return getWidthBeforeFirstLayout() - (mCellWidth - Utilities.getIconContentSize());
+ }
+
+ int getWidthBeforeFirstLayout() {
+ return mCellCountX * mCellWidth + (mCellCountX - 1) * mWidthGap;
+ }
+
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
@@ -281,17 +301,6 @@
mHolographicChildren.setGap(widthGap, heightGap);
}
- public void setCellDimensions(int width, int height) {
- mCellWidth = width;
- mCellHeight = height;
- mChildren.setCellDimensions(width, height);
- mHolographicChildren.setCellDimensions(width, height);
- }
-
- public int getDefaultCellDimensions() {
- return sDefaultCellDimensions;
- }
-
public int[] getCellCountForDimensions(int width, int height) {
// Always assume we're working with the smallest span to make sure we
// reserve enough space in both orientations
diff --git a/src/com/android/launcher2/PagedViewExtendedLayout.java b/src/com/android/launcher2/PagedViewExtendedLayout.java
index e54d261..81f1498 100644
--- a/src/com/android/launcher2/PagedViewExtendedLayout.java
+++ b/src/com/android/launcher2/PagedViewExtendedLayout.java
@@ -26,7 +26,7 @@
* The linear layout used strictly for the widget/wallpaper tab of the customization tray
*/
public class PagedViewExtendedLayout extends LinearLayout implements Page {
- static final String TAG = "PagedViewWidgetLayout";
+ static final String TAG = "PagedViewExtendedLayout";
public PagedViewExtendedLayout(Context context) {
this(context, null);
diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java
index bde6559..f46b63c 100644
--- a/src/com/android/launcher2/PagedViewIcon.java
+++ b/src/com/android/launcher2/PagedViewIcon.java
@@ -31,6 +31,7 @@
import android.os.HandlerThread;
import android.os.Message;
import android.util.AttributeSet;
+import android.view.KeyEvent;
import android.widget.Checkable;
import android.widget.TextView;
@@ -128,8 +129,6 @@
mCheckedFadeOutDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeOutTime);
}
- setFocusable(true);
- setBackgroundDrawable(null);
mHolographicOutlineView = new HolographicPagedViewIcon(context, this);
}
@@ -245,6 +244,18 @@
}
@Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
+ || super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
+ || super.onKeyUp(keyCode, event);
+ }
+
+ @Override
public boolean isChecked() {
return mIsChecked;
}
diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java
index 72f928b..c2d609e 100644
--- a/src/com/android/launcher2/PagedViewWidget.java
+++ b/src/com/android/launcher2/PagedViewWidget.java
@@ -36,6 +36,7 @@
import android.os.HandlerThread;
import android.os.Message;
import android.util.AttributeSet;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Checkable;
@@ -228,6 +229,18 @@
}
@Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return FocusHelper.handlePagedViewWidgetKeyEvent(this, keyCode, event)
+ || super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return FocusHelper.handlePagedViewWidgetKeyEvent(this, keyCode, event)
+ || super.onKeyUp(keyCode, event);
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
if (mAlpha > 0) {
super.onDraw(canvas);
diff --git a/src/com/android/launcher2/ShortcutsAdapter.java b/src/com/android/launcher2/ShortcutsAdapter.java
index 93c500a..de73c3e 100644
--- a/src/com/android/launcher2/ShortcutsAdapter.java
+++ b/src/com/android/launcher2/ShortcutsAdapter.java
@@ -30,7 +30,7 @@
/**
* GridView adapter to show the list of applications and shortcuts
*/
-public class ShortcutsAdapter extends ArrayAdapter<ShortcutInfo> {
+public class ShortcutsAdapter extends ArrayAdapter<ShortcutInfo> {
private final LayoutInflater mInflater;
private final IconCache mIconCache;
diff --git a/src/com/android/launcher2/UserFolder.java b/src/com/android/launcher2/UserFolder.java
index 251b3f9..b800b07 100644
--- a/src/com/android/launcher2/UserFolder.java
+++ b/src/com/android/launcher2/UserFolder.java
@@ -1,11 +1,18 @@
package com.android.launcher2;
import android.content.Context;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.GridView;
+import android.widget.TextView;
import com.android.launcher.R;
+import java.util.ArrayList;
/**
* Folder which contains applications or shortcuts chosen by the user.
@@ -14,8 +21,21 @@
public class UserFolder extends Folder implements DropTarget {
private static final String TAG = "Launcher.UserFolder";
+ protected CellLayout mContent;
+ private final LayoutInflater mInflater;
+ private final IconCache mIconCache;
+
public UserFolder(Context context, AttributeSet attrs) {
super(context, attrs);
+ mInflater = LayoutInflater.from(context);
+ mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mContent = (CellLayout) findViewById(R.id.folder_content);
}
/**
@@ -29,6 +49,48 @@
return (UserFolder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
}
+ @Override
+ void notifyDataSetChanged() {
+ // recreate all the children if the data set changes under us. We may want to do this more
+ // intelligently (ie just removing the views that should no longer exist)
+ mContent.removeAllViewsInLayout();
+ bind(mInfo);
+ }
+
+ public void onClick(View v) {
+ Object tag = v.getTag();
+ if (tag instanceof ShortcutInfo) {
+ // refactor this code from Folder
+ ShortcutInfo item = (ShortcutInfo) tag;
+ int[] pos = new int[2];
+ v.getLocationOnScreen(pos);
+ item.intent.setSourceBounds(new Rect(pos[0], pos[1],
+ pos[0] + v.getWidth(), pos[1] + v.getHeight()));
+ mLauncher.startActivitySafely(item.intent, item);
+ } else {
+ super.onClick(v);
+ }
+ }
+
+ public boolean onLongClick(View v) {
+ Object tag = v.getTag();
+ if (tag instanceof ShortcutInfo) {
+ // refactor this code from Folder
+ ShortcutInfo item = (ShortcutInfo) tag;
+ if (!v.isInTouchMode()) {
+ return false;
+ }
+
+ mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
+ mLauncher.closeFolder(this);
+ mDragItem = item;
+
+ return true;
+ } else {
+ return super.onLongClick(v);
+ }
+ }
+
public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
final ItemInfo item = (ItemInfo) dragInfo;
@@ -44,11 +106,45 @@
if (dragInfo instanceof ApplicationInfo) {
// Came from all apps -- make a copy
item = ((ApplicationInfo)dragInfo).makeShortcut();
+ item.spanX = 1;
+ item.spanY = 1;
} else {
item = (ShortcutInfo)dragInfo;
}
- ((ShortcutsAdapter)mContent.getAdapter()).add(item);
- LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
+ findAndSetEmptyCells(item);
+ ((UserFolderInfo)mInfo).add(item);
+ createAndAddShortcut(item);
+ LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
+ }
+
+ protected boolean findAndSetEmptyCells(ShortcutInfo item) {
+ int[] emptyCell = new int[2];
+ if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
+ item.cellX = emptyCell[0];
+ item.cellY = emptyCell[1];
+ LauncherModel.addOrMoveItemInDatabase(
+ mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected void createAndAddShortcut(ShortcutInfo item) {
+ final TextView textView =
+ (TextView) mInflater.inflate(R.layout.application_boxed, this, false);
+ textView.setCompoundDrawablesWithIntrinsicBounds(null,
+ new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
+ textView.setText(item.title);
+ textView.setTag(item);
+
+ textView.setOnClickListener(this);
+ textView.setOnLongClickListener(this);
+
+ CellLayout.LayoutParams lp =
+ new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
+ boolean insert = false;
+ mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
}
public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
@@ -66,8 +162,7 @@
@Override
public void onDropCompleted(View target, Object dragInfo, boolean success) {
if (success) {
- ShortcutsAdapter adapter = (ShortcutsAdapter)mContent.getAdapter();
- adapter.remove(mDragItem);
+ ((UserFolderInfo)mInfo).remove(mDragItem);
}
}
@@ -77,14 +172,24 @@
void bind(FolderInfo info) {
super.bind(info);
- setContentAdapter(new ShortcutsAdapter(mContext, ((UserFolderInfo) info).contents));
+ ArrayList<ShortcutInfo> children = ((UserFolderInfo)info).contents;
+ for (int i = 0; i < children.size(); i++) {
+ ShortcutInfo child = (ShortcutInfo) children.get(i);
+ if ((child.cellX == -1 && child.cellY == -1) ||
+ mContent.isOccupied(child.cellX, child.cellY)) {
+ findAndSetEmptyCells(child);
+ }
+ createAndAddShortcut((ShortcutInfo) children.get(i));
+ }
}
- // When the folder opens, we need to refresh the GridView's selection by
- // forcing a layout
@Override
void onOpen() {
super.onOpen();
+ // When the folder opens, we need to refresh the GridView's selection by
+ // forcing a layout
+ // TODO: find out if this is still necessary
+ mContent.requestLayout();
requestFocus();
}
diff --git a/src/com/android/launcher2/Utilities.java b/src/com/android/launcher2/Utilities.java
index 60f71f5..cd98cab 100644
--- a/src/com/android/launcher2/Utilities.java
+++ b/src/com/android/launcher2/Utilities.java
@@ -16,6 +16,8 @@
package com.android.launcher2;
+import java.util.Random;
+
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -51,6 +53,7 @@
private static int sIconWidth = -1;
private static int sIconHeight = -1;
+ private static int sIconContentSize = -1;
private static int sIconTextureWidth = -1;
private static int sIconTextureHeight = -1;
@@ -90,6 +93,10 @@
static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
static int sColorIndex = 0;
+ static int getIconContentSize() {
+ return sIconContentSize;
+ }
+
/**
* Returns a bitmap suitable for the all apps view. The bitmap will be a power
* of two sized ARGB_8888 bitmap that can be used as a gl texture.
@@ -236,6 +243,9 @@
final float density = metrics.density;
sIconWidth = sIconHeight = (int) resources.getDimension(R.dimen.app_icon_size);
+ if (LauncherApplication.isScreenXLarge()) {
+ sIconContentSize = (int) resources.getDimension(R.dimen.app_icon_content_size);
+ }
sIconTextureWidth = sIconTextureHeight = sIconWidth + 2;
sBlurPaint.setMaskFilter(new BlurMaskFilter(5 * density, BlurMaskFilter.Blur.NORMAL));
@@ -381,4 +391,8 @@
}
return n;
}
+
+ static int generateRandomId() {
+ return new Random(System.currentTimeMillis()).nextInt(1 << 24);
+ }
}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index e7865d2..98cf62b 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -155,6 +155,7 @@
// return an (x, y) value from helper functions. Do NOT use them to maintain other state.
private int[] mTempCell = new int[2];
private int[] mTempEstimate = new int[2];
+ private float[] mDragViewVisualCenter = new float[2];
private float[] mTempOriginXY = new float[2];
private float[] mTempDragCoordinates = new float[2];
private float[] mTempTouchCoordinates = new float[2];
@@ -213,6 +214,7 @@
WallpaperOffsetInterpolator mWallpaperOffset;
boolean mUpdateWallpaperOffsetImmediately = false;
boolean mSyncWallpaperOffsetWithScroll = true;
+ private Runnable mDelayedResizeRunnable;
// info about the last drag
private DragView mLastDragView;
@@ -340,58 +342,41 @@
}
}
- @Override
- public void addView(View child, int index, LayoutParams params) {
+ private void onAddView(View child) {
if (!(child instanceof CellLayout)) {
throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
}
((CellLayout) child).setOnInterceptTouchListener(this);
child.setOnClickListener(this);
child.setClickable(true);
+ }
+ @Override
+ public void addView(View child, int index, LayoutParams params) {
+ onAddView(child);
super.addView(child, index, params);
}
@Override
public void addView(View child) {
- if (!(child instanceof CellLayout)) {
- throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
- }
- ((CellLayout) child).setOnInterceptTouchListener(this);
- child.setOnClickListener(this);
- child.setClickable(true);
+ onAddView(child);
super.addView(child);
}
@Override
public void addView(View child, int index) {
- if (!(child instanceof CellLayout)) {
- throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
- }
- ((CellLayout) child).setOnInterceptTouchListener(this);
- child.setOnClickListener(this);
- child.setClickable(true);
+ onAddView(child);
super.addView(child, index);
}
@Override
public void addView(View child, int width, int height) {
- if (!(child instanceof CellLayout)) {
- throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
- }
- ((CellLayout) child).setOnInterceptTouchListener(this);
- child.setOnClickListener(this);
- child.setClickable(true);
+ onAddView(child);
super.addView(child, width, height);
}
@Override
public void addView(View child, LayoutParams params) {
- if (!(child instanceof CellLayout)) {
- throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
- }
- ((CellLayout) child).setOnInterceptTouchListener(this);
- child.setOnClickListener(this);
- child.setClickable(true);
+ onAddView(child);
super.addView(child, params);
}
@@ -645,6 +630,11 @@
}
mOverScrollMaxBackgroundAlpha = 0.0f;
mOverScrollPageIndex = -1;
+
+ if (mDelayedResizeRunnable != null) {
+ mDelayedResizeRunnable.run();
+ mDelayedResizeRunnable = null;
+ }
}
@Override
@@ -1067,6 +1057,9 @@
@Override
protected void screenScrolled(int screenCenter) {
+ // If the screen is not xlarge, then don't rotate the CellLayouts
+ if (!LauncherApplication.isScreenXLarge()) return;
+
final int halfScreenSize = getMeasuredWidth() / 2;
for (int i = 0; i < getChildCount(); i++) {
@@ -1244,6 +1237,14 @@
}
@Override
+ public int getDescendantFocusability() {
+ if (mIsSmall) {
+ return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+ }
+ return super.getDescendantFocusability();
+ }
+
+ @Override
public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
if (!mLauncher.isAllAppsVisible()) {
final Folder openFolder = getOpenFolder();
@@ -1392,14 +1393,6 @@
// we use this to shrink the workspace for the all apps view and the customize view
public void shrink(ShrinkState shrinkState, boolean animated) {
- // In the launcher interaction model, we're never in the state where we're shrunken and
- // visible in the bottom of the screen, and then want to fade to being invisible.
- // After spring loaded mode ends, this method was getting called twice, the first time
- // with BOTTOM_VISIBLE (what we want) and a second time with BOTTOM_INVISIBLE (not
- // what we want). As a temporary solution, we just change the second call to BOTTOM_VISIBLE
- if (mIsSmall && mShrinkState == ShrinkState.BOTTOM_VISIBLE) {
- shrinkState = ShrinkState.BOTTOM_VISIBLE;
- }
if (mFirstLayout) {
// (mFirstLayout == "first layout has not happened yet")
// if we get a call to shrink() as part of our initialization (for example, if
@@ -1591,10 +1584,8 @@
final float oldVerticalWallpaperOffset = getVerticalWallpaperOffset();
final float newHorizontalWallpaperOffset = 0.5f;
final float newVerticalWallpaperOffset = wallpaperOffset;
- animWithInterpolator.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
+ animWithInterpolator.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
if (b == 0f) {
// an optimization, and required for correct behavior.
return;
@@ -1708,26 +1699,32 @@
for (int i = 0; i < screenCount; i++) {
CellLayout cl = (CellLayout) getChildAt(i);
cl.setIsDragOccuring(isDragHappening);
- switch (state) {
- case TOP:
- cl.setIsDefaultDropTarget(i == mCurrentPage);
- case BOTTOM_HIDDEN:
- case BOTTOM_VISIBLE:
- case SPRING_LOADED:
- if (state != ShrinkState.TOP) {
- cl.setIsDefaultDropTarget(false);
- }
- if (!isDragHappening) {
- // even if a drag isn't happening, we don't want to show a screen as
- // accepting drops if it doesn't have at least one free cell
- spanX = 1;
- spanY = 1;
- }
- // the page accepts drops if we can find at least one empty spot
- cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
- break;
- default:
- throw new RuntimeException("Unhandled ShrinkState " + state);
+ if (state == null) {
+ // If we are not in a shrunken state, mark all cell layouts as droppable (if they
+ // have the space)
+ cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
+ } else {
+ switch (state) {
+ case TOP:
+ cl.setIsDefaultDropTarget(i == mCurrentPage);
+ case BOTTOM_HIDDEN:
+ case BOTTOM_VISIBLE:
+ case SPRING_LOADED:
+ if (state != ShrinkState.TOP) {
+ cl.setIsDefaultDropTarget(false);
+ }
+ if (!isDragHappening) {
+ // even if a drag isn't happening, we don't want to show a screen as
+ // accepting drops if it doesn't have at least one free cell
+ spanX = 1;
+ spanY = 1;
+ }
+ // the page accepts drops if we can find at least one empty spot
+ cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
+ break;
+ default:
+ throw new RuntimeException("Unhandled ShrinkState " + state);
+ }
}
}
}
@@ -1800,8 +1797,8 @@
}
public void exitWidgetResizeMode() {
- final CellLayout currentLayout = (CellLayout) getChildAt(getCurrentPage());
- currentLayout.getChildrenLayout().clearAllResizeFrames();
+ DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+ dragLayer.clearAllResizeFrames();
}
void unshrink(boolean animated) {
@@ -1930,10 +1927,8 @@
final float oldVerticalWallpaperOffset = getVerticalWallpaperOffset();
final float newHorizontalWallpaperOffset = wallpaperOffsetForCurrentScroll();
final float newVerticalWallpaperOffset = 0.5f;
- animWithInterpolator.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
+ animWithInterpolator.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
if (b == 0f) {
// an optimization, but not required
return;
@@ -1964,11 +1959,9 @@
ValueAnimator rotationAnim =
ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
rotationAnim.setInterpolator(new DecelerateInterpolator(2.0f));
- rotationAnim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
+ rotationAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
// don't invalidate workspace because we did it above
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
if (b == 0f) {
// an optimization, but not required
return;
@@ -2140,12 +2133,23 @@
final int bmpWidth = b.getWidth();
final int bmpHeight = b.getHeight();
+
child.getLocationOnScreen(mTempXY);
final int screenX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
final int screenY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
- mLauncher.lockScreenOrientation();
- mDragController.startDrag(
- b, screenX, screenY, this, child.getTag(), DragController.DRAG_ACTION_MOVE);
+
+ Rect dragRect = null;
+ if (child instanceof BubbleTextView) {
+ int iconSize = getResources().getDimensionPixelSize(R.dimen.app_icon_size);
+ int top = child.getPaddingTop();
+ int left = (bmpWidth - iconSize) / 2;
+ int right = left + iconSize;
+ int bottom = top + iconSize;
+ dragRect = new Rect(left, top, right, bottom);
+ }
+
+ mDragController.startDrag(b, screenX, screenY, this, child.getTag(),
+ DragController.DRAG_ACTION_MOVE, dragRect);
b.recycle();
}
@@ -2167,10 +2171,8 @@
final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
// Based on the position of the drag view, find the top left of the original view
- int viewX = dragViewX + (dragView.getWidth() - child.getWidth()) / 2;
- int viewY = dragViewY + (dragView.getHeight() - child.getHeight()) / 2;
- viewX += getResources().getInteger(R.integer.config_dragViewOffsetX);
- viewY += getResources().getInteger(R.integer.config_dragViewOffsetY);
+ int viewX = dragViewX + (dragView.getWidth() - child.getMeasuredWidth()) / 2;
+ int viewY = dragViewY + (dragView.getHeight() - child.getMeasuredHeight()) / 2;
// Set its old pos (in the new parent's coordinates); it will be animated
// in animateViewIntoPosition after the next layout pass
@@ -2271,24 +2273,56 @@
return true;
}
+ boolean createUserFolderIfNecessary(View newView, CellLayout target, int originX,
+ int originY, boolean external) {
+ int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
+ int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
+
+ // First we find the cell nearest to point at which the item is dropped, without
+ // any consideration to whether there is an item there.
+ mTargetCell = findNearestArea(originX, originY,
+ spanX, spanY, target,
+ mTargetCell);
+
+ View v = target.getChildAt(mTargetCell[0], mTargetCell[1]);
+ boolean hasntMoved = mDragInfo != null && (mDragInfo.cellX == mTargetCell[0] &&
+ mDragInfo.cellY == mTargetCell[1]);
+
+ if (v == null || hasntMoved) return false;
+
+ final int screen = (mTargetCell == null) ?
+ mDragInfo.screen : indexOfChild(target);
+
+ boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);
+ boolean willBecomeShortcut = (newView.getTag() instanceof ShortcutInfo);
+
+ if (aboveShortcut && willBecomeShortcut) {
+ ShortcutInfo sourceInfo = (ShortcutInfo) newView.getTag();
+ ShortcutInfo destInfo = (ShortcutInfo) v.getTag();
+ // if the drag started here, we need to remove it from the workspace
+ if (!external) {
+ int fromScreen = mDragInfo.screen;
+ CellLayout sourceLayout = (CellLayout) getChildAt(fromScreen);
+ sourceLayout.removeView(newView);
+ }
+
+ target.removeView(v);
+ FolderIcon fi = mLauncher.addFolder(screen, mTargetCell[0], mTargetCell[1]);
+ fi.addItem(destInfo);
+ fi.addItem(sourceInfo);
+ return true;
+ }
+ return false;
+ }
+
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
- boolean largeOrSpringLoaded = !mIsSmall || mWasSpringLoadedOnDragExit;
- int originX = largeOrSpringLoaded ? x - xOffset : x - xOffset + dragView.getWidth() / 2;
- int originY = largeOrSpringLoaded ? y - yOffset : y - yOffset + dragView.getHeight() / 2;
- if (mIsSmall || mIsInUnshrinkAnimation) {
- // get originX and originY in the local coordinate system of the screen
- mTempOriginXY[0] = originX;
- mTempOriginXY[1] = originY;
- mapPointFromSelfToChild(mDragTargetLayout, mTempOriginXY);
- originX = (int)mTempOriginXY[0];
- originY = (int)mTempOriginXY[1];
- if (!largeOrSpringLoaded) {
- originX -= mDragTargetLayout.getCellWidth() / 2;
- originY -= mDragTargetLayout.getCellHeight() / 2;
- }
- }
+ mDragViewVisualCenter = getDragViewVisualCenter(x, y, xOffset, yOffset, dragView,
+ mDragViewVisualCenter);
+
+ // We want the point to be mapped to the dragTarget.
+ mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
// When you are in customization mode and drag to a particular screen, make that the
// new current/default screen, so any subsequent taps add items to that screen
@@ -2300,14 +2334,15 @@
}
if (source != this) {
- final int[] touchXY = new int[] { originX, originY };
+ final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
+ (int) mDragViewVisualCenter[1] };
if ((mIsSmall || mIsInUnshrinkAnimation) && !mLauncher.isAllAppsVisible()) {
// When the workspace is shrunk and the drop comes from customize, don't actually
// add the item to the screen -- customize will do this itself
((ItemInfo) dragInfo).dropPos = touchXY;
return;
}
- onDropExternal(touchXY, dragInfo, mDragTargetLayout, false);
+ onDropExternal(touchXY, dragInfo, mDragTargetLayout, false, dragView);
} else if (mDragInfo != null) {
final View cell = mDragInfo.cell;
CellLayout dropTargetLayout = mDragTargetLayout;
@@ -2324,13 +2359,22 @@
if (dropTargetLayout != null) {
// Move internally
- mTargetCell = findNearestVacantArea(originX, originY,
- mDragInfo.spanX, mDragInfo.spanY, cell, dropTargetLayout,
- mTargetCell);
-
final int screen = (mTargetCell == null) ?
mDragInfo.screen : indexOfChild(dropTargetLayout);
+ // If the item being dropped is a shortcut and the nearest drop cell also contains
+ // a shortcut, then create a folder with the two shortcuts.
+ if (createUserFolderIfNecessary(cell, dropTargetLayout,
+ (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], false)) {
+ return;
+ }
+
+ // Aside from the special case where we're dropping a shortcut onto a shortcut,
+ // we need to find the nearest cell location that is vacant
+ mTargetCell = findNearestVacantArea((int) mDragViewVisualCenter[0],
+ (int) mDragViewVisualCenter[1], mDragInfo.spanX, mDragInfo.spanY, cell,
+ dropTargetLayout, mTargetCell);
+
if (screen != mCurrentPage) {
snapToPage(screen);
}
@@ -2353,7 +2397,6 @@
mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
if (cell instanceof LauncherAppWidgetHostView) {
- final CellLayoutChildren children = dropTargetLayout.getChildrenLayout();
final CellLayout cellLayout = dropTargetLayout;
// We post this call so that the widget has a chance to be placed
// in its final location
@@ -2361,10 +2404,21 @@
final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
AppWidgetProviderInfo pinfo = hostView.getAppWidgetInfo();
if (pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
+ final Runnable resizeRunnable = new Runnable() {
+ public void run() {
+ DragLayer dragLayer = (DragLayer)
+ mLauncher.findViewById(R.id.drag_layer);
+ dragLayer.addResizeFrame(info, hostView,
+ cellLayout);
+ }
+ };
post(new Runnable() {
public void run() {
- children.addResizeFrame(info, hostView,
- cellLayout);
+ if (!isPageMoving()) {
+ resizeRunnable.run();
+ } else {
+ mDelayedResizeRunnable = resizeRunnable;
+ }
}
});
}
@@ -2378,14 +2432,30 @@
final CellLayout parent = (CellLayout) cell.getParent().getParent();
+ int loc[] = new int[2];
+ getViewLocationRelativeToSelf(dragView, loc);
+
// Prepare it to be animated into its new position
// This must be called after the view has been re-parented
- setPositionForDropAnimation(dragView, originX, originY, parent, cell);
+ setPositionForDropAnimation(dragView, loc[0], loc[1], parent, cell);
boolean animateDrop = !mWasSpringLoadedOnDragExit;
parent.onDropChild(cell, animateDrop);
}
}
+ private void getViewLocationRelativeToSelf(View v, int[] location) {
+ getLocationOnScreen(location);
+ int x = location[0];
+ int y = location[1];
+
+ v.getLocationOnScreen(location);
+ int vX = location[0];
+ int vY = location[1];
+
+ location[0] = vX - x;
+ location[1] = vY - y;
+ }
+
public void onDragEnter(DragSource source, int x, int y, int xOffset,
int yOffset, DragView dragView, Object dragInfo) {
mDragTargetLayout = null; // Reset the drag state
@@ -2614,11 +2684,11 @@
xy[1] -= (mScrollY - v.getTop());
}
- static private float squaredDistance(float[] point1, float[] point2) {
+ static private float squaredDistance(float[] point1, float[] point2) {
float distanceX = point1[0] - point2[0];
float distanceY = point2[1] - point2[1];
return distanceX * distanceX + distanceY * distanceY;
- }
+ }
/*
*
@@ -2716,21 +2786,57 @@
return bestMatchingScreen;
}
+ // This is used to compute the visual center of the dragView. This point is then
+ // used to visualize drop locations and determine where to drop an item. The idea is that
+ // the visual center represents the user's interpretation of where the item is, and hence
+ // is the appropriate point to use when determining drop location.
+ private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset,
+ DragView dragView, float[] recycle) {
+ float res[];
+ if (recycle == null) {
+ res = new float[2];
+ } else {
+ res = recycle;
+ }
+
+ // First off, the drag view has been shifted in a way that is not represented in the
+ // x and y values or the x/yOffsets. Here we account for that shift.
+ x += getResources().getDimensionPixelSize(R.dimen.dragViewOffsetX);
+ y += getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
+
+ // These represent the visual top and left of drag view if a dragRect was provided.
+ // If a dragRect was not provided, then they correspond to the actual view left and
+ // top, as the dragRect is in that case taken to be the entire dragView.
+ // R.dimen.dragViewOffsetY.
+ int left = x - xOffset;
+ int top = y - yOffset;
+
+ // In order to find the visual center, we shift by half the dragRect
+ res[0] = left + dragView.getDragRegion().width() / 2;
+ res[1] = top + dragView.getDragRegion().height() / 2;
+
+ return res;
+ }
+
public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
// When touch is inside the scroll area, skip dragOver actions for the current screen
if (!mInScrollArea) {
CellLayout layout;
- int originX = x - xOffset;
- int originY = y - yOffset;
+ int left = x - xOffset;
+ int top = y - yOffset;
+
+ mDragViewVisualCenter = getDragViewVisualCenter(x, y, xOffset, yOffset, dragView,
+ mDragViewVisualCenter);
+
boolean shrunken = mIsSmall || mIsInUnshrinkAnimation;
if (shrunken) {
mLastDragView = dragView;
- mLastDragOriginX = originX;
- mLastDragOriginY = originY;
+ mLastDragOriginX = left;
+ mLastDragOriginY = top;
mLastDragXOffset = xOffset;
mLastDragYOffset = yOffset;
- layout = findMatchingPageForDragOver(dragView, originX, originY, xOffset, yOffset);
+ layout = findMatchingPageForDragOver(dragView, left, top, xOffset, yOffset);
if (layout != mDragTargetLayout) {
if (mDragTargetLayout != null) {
@@ -2776,35 +2882,14 @@
}
}
- if (source instanceof AllAppsPagedView) {
- // This is a hack to fix the point used to determine which cell an icon from
- // the all apps screen is over
- if (item != null && item.spanX == 1 && layout != null) {
- int dragRegionLeft = (dragView.getWidth() - layout.getCellWidth()) / 2;
-
- originX += dragRegionLeft - dragView.getDragRegionLeft();
- if (dragView.getDragRegionWidth() != layout.getCellWidth()) {
- dragView.setDragRegion(dragView.getDragRegionLeft(),
- dragView.getDragRegionTop(),
- layout.getCellWidth(),
- dragView.getDragRegionHeight());
- }
- }
- } else if (source == this) {
- // When dragging from the workspace, the drag view is slightly bigger than
- // the original view, and offset vertically. Adjust to account for this.
- final View origView = mDragInfo.cell;
- originX += (dragView.getMeasuredWidth() - origView.getWidth()) / 2;
- originY += (dragView.getMeasuredHeight() - origView.getHeight()) / 2
- + dragView.getOffsetY();
- }
-
if (mDragTargetLayout != null) {
final View child = (mDragInfo == null) ? null : mDragInfo.cell;
- float[] localOrigin = { originX, originY };
- mapPointFromSelfToChild(mDragTargetLayout, localOrigin, null);
+ // We want the point to be mapped to the dragTarget.
+ mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
- (int) localOrigin[0], (int) localOrigin[1], item.spanX, item.spanY);
+ (int) mDragViewVisualCenter[0],
+ (int) mDragViewVisualCenter[1],
+ item.spanX, item.spanY);
}
}
}
@@ -2850,6 +2935,11 @@
return false;
}
+ private void onDropExternal(int[] touchXY, Object dragInfo,
+ CellLayout cellLayout, boolean insertAtFirst) {
+ onDropExternal(touchXY, dragInfo, cellLayout, insertAtFirst, null);
+ }
+
/**
* Drop an item that didn't originate on one of the workspace screens.
* It may have come from Launcher (e.g. from all apps or customize), or it may have
@@ -2859,7 +2949,7 @@
* to add an item to one of the workspace screens.
*/
private void onDropExternal(int[] touchXY, Object dragInfo,
- CellLayout cellLayout, boolean insertAtFirst) {
+ CellLayout cellLayout, boolean insertAtFirst, DragView dragView) {
int screen = indexOfChild(cellLayout);
if (dragInfo instanceof PendingAddItemInfo) {
PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
@@ -2902,10 +2992,18 @@
throw new IllegalStateException("Unknown item type: " + info.itemType);
}
+ // If the item being dropped is a shortcut and the nearest drop cell also contains
+ // a shortcut, then create a folder with the two shortcuts.
+ if (touchXY != null && createUserFolderIfNecessary(view, cellLayout, touchXY[0],
+ touchXY[1], true)) {
+ return;
+ }
+
mTargetCell = new int[2];
if (touchXY != null) {
// when dragging and dropping, just find the closest free spot
- cellLayout.findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, mTargetCell);
+ mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, null, cellLayout,
+ mTargetCell);
} else {
cellLayout.findCellForSpan(mTargetCell, 1, 1);
}
@@ -2915,6 +3013,15 @@
cellLayout.onDropChild(view, animateDrop);
cellLayout.animateDrop();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
+ cellLayout.getChildrenLayout().measureChild(view);
+
+ if (dragView != null) {
+ // we have the visual center of the drag view, we need to find the actual
+ // left and top of the dragView.
+ int loc[] = new int[2];
+ getViewLocationRelativeToSelf(dragView, loc);
+ setPositionForDropAnimation(dragView, loc[0], loc[1], cellLayout, view);
+ }
LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
@@ -2942,16 +3049,24 @@
/**
* Calculate the nearest cell where the given object would be dropped.
+ *
+ * pixelX and pixelY should be in the coordinate system of layout
*/
private int[] findNearestVacantArea(int pixelX, int pixelY,
int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
-
- int localPixelX = pixelX - (layout.getLeft() - mScrollX);
- int localPixelY = pixelY - (layout.getTop() - mScrollY);
-
- // Find the best target drop location
return layout.findNearestVacantArea(
- localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
+ pixelX, pixelY, spanX, spanY, ignoreView, recycle);
+ }
+
+ /**
+ * Calculate the nearest cell where the given object would be dropped.
+ *
+ * pixelX and pixelY should be in the coordinate system of layout
+ */
+ private int[] findNearestArea(int pixelX, int pixelY,
+ int spanX, int spanY, CellLayout layout, int[] recycle) {
+ return layout.findNearestArea(
+ pixelX, pixelY, spanX, spanY, recycle);
}
void setLauncher(Launcher launcher) {
@@ -3104,6 +3219,21 @@
return null;
}
+ void clearDropTargets() {
+ final int screenCount = getChildCount();
+
+ for (int i = 0; i < screenCount; i++) {
+ final CellLayout layoutParent = (CellLayout) getChildAt(i);
+ final ViewGroup layout = layoutParent.getChildrenLayout();
+ int childCount = layout.getChildCount();
+ for (int j = 0; j < childCount; j++) {
+ View v = layout.getChildAt(j);
+ if (v instanceof DropTarget) {
+ mDragController.removeDropTarget((DropTarget) v);
+ }
+ }
+ }
+ }
void removeItems(final ArrayList<ApplicationInfo> apps) {
final int screenCount = getChildCount();