Merge "Allowing the first screen to expand to the screen edge" into ub-launcher3-calgary
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 3a361e2..1147326 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -51,12 +51,8 @@
android:layout_gravity="right" />
<include
- android:id="@+id/app_info_drop_target_bar"
- layout="@layout/drop_target_bar_vert_info" />
-
- <include
- android:id="@+id/search_drop_target_bar"
- layout="@layout/drop_target_bar_vert_search" />
+ android:id="@+id/drop_target_bar"
+ layout="@layout/drop_target_bar_vert" />
<include layout="@layout/overview_panel"
android:id="@+id/overview_panel"
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 4576e4d..fed99f3 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -60,15 +60,11 @@
<com.android.launcher3.pageindicators.PageIndicatorLine
android:id="@+id/page_indicator"
android:layout_width="match_parent"
- android:layout_height="1dp" />
+ android:layout_height="@dimen/dynamic_grid_page_indicator_height" />
<include
- android:id="@+id/app_info_drop_target_bar"
- layout="@layout/drop_target_bar_horz_info" />
-
- <include
- android:id="@+id/search_drop_target_bar"
- layout="@layout/drop_target_bar_horz_search" />
+ android:id="@+id/drop_target_bar"
+ layout="@layout/drop_target_bar_horz" />
<include layout="@layout/widgets_view"
android:id="@+id/widgets_view"
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 0f755d8..23e673c 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -51,12 +51,8 @@
android:layout_height="match_parent" />
<include
- android:id="@+id/app_info_drop_target_bar"
- layout="@layout/drop_target_bar_horz_info" />
-
- <include
- android:id="@+id/search_drop_target_bar"
- layout="@layout/drop_target_bar_horz_search" />
+ android:id="@+id/drop_target_bar"
+ layout="@layout/drop_target_bar_horz" />
<include layout="@layout/overview_panel"
android:id="@+id/overview_panel"
@@ -67,7 +63,7 @@
<com.android.launcher3.pageindicators.PageIndicatorLine
android:id="@+id/page_indicator"
android:layout_width="match_parent"
- android:layout_height="1dp" />
+ android:layout_height="@dimen/dynamic_grid_page_indicator_height" />
<include layout="@layout/widgets_view"
android:id="@+id/widgets_view"
diff --git a/res/layout/drop_target_bar_horz.xml b/res/layout/drop_target_bar_horz.xml
new file mode 100644
index 0000000..ee22d1e
--- /dev/null
+++ b/res/layout/drop_target_bar_horz.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.launcher3.DropTargetBar
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/dynamic_grid_drop_target_size"
+ android:layout_gravity="center_horizontal|top"
+ android:focusable="false">
+
+ <FrameLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" >
+
+ <!-- Delete target -->
+
+ <com.android.launcher3.DeleteDropTarget
+ launcher:hideParentOnDisable="true"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:id="@+id/delete_target_text"
+ style="@style/DropTargetButton"
+ android:text="@string/remove_drop_target_label" />
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" >
+
+ <!-- App Info -->
+
+ <com.android.launcher3.InfoDropTarget
+ launcher:hideParentOnDisable="true"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:id="@+id/info_target_text"
+ style="@style/DropTargetButton"
+ android:text="@string/app_info_drop_target_label" />
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" >
+
+ <!-- Uninstall target -->
+
+ <com.android.launcher3.UninstallDropTarget
+ launcher:hideParentOnDisable="true"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:id="@+id/uninstall_target_text"
+ style="@style/DropTargetButton"
+ android:text="@string/uninstall_drop_target_label" />
+ </FrameLayout>
+
+</com.android.launcher3.DropTargetBar>
\ No newline at end of file
diff --git a/res/layout/drop_target_bar_horz_info.xml b/res/layout/drop_target_bar_horz_info.xml
deleted file mode 100644
index 92a9b22..0000000
--- a/res/layout/drop_target_bar_horz_info.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 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.launcher3.AppInfoDropTargetBar xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="48dp"
- android:layout_gravity="center_horizontal|bottom"
- android:focusable="false" >
-
- <FrameLayout
- android:id="@+id/drag_target_bar"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <!-- Info target -->
-
- <com.android.launcher3.InfoDropTarget
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="center"
- android:gravity="center"
- android:id="@+id/info_target_text"
- style="@style/DropTargetButton"
- android:text="@string/app_info_drop_target_label" />
- </FrameLayout>
-</com.android.launcher3.AppInfoDropTargetBar>
\ No newline at end of file
diff --git a/res/layout/drop_target_bar_horz_search.xml b/res/layout/drop_target_bar_horz_search.xml
deleted file mode 100644
index 7997801..0000000
--- a/res/layout/drop_target_bar_horz_search.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.launcher3.SearchDropTargetBar xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center_horizontal|top"
- android:focusable="false">
-
- <!-- Drag specific targets container -->
-
- <LinearLayout
- android:id="@+id/drag_target_bar"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center" >
-
- <FrameLayout
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1" >
-
- <!-- Delete target -->
-
- <com.android.launcher3.DeleteDropTarget
- launcher:hideParentOnDisable="true"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="center"
- android:gravity="center"
- android:id="@+id/delete_target_text"
- style="@style/DropTargetButton"
- android:text="@string/remove_drop_target_label" />
- </FrameLayout>
-
- <FrameLayout
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1" >
-
- <!-- Uninstall target -->
-
- <com.android.launcher3.UninstallDropTarget
- launcher:hideParentOnDisable="true"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="center"
- android:gravity="center"
- android:id="@+id/uninstall_target_text"
- style="@style/DropTargetButton"
- android:text="@string/uninstall_drop_target_label" />
- </FrameLayout>
- </LinearLayout>
-
-</com.android.launcher3.SearchDropTargetBar>
\ No newline at end of file
diff --git a/res/layout/drop_target_bar_vert.xml b/res/layout/drop_target_bar_vert.xml
new file mode 100644
index 0000000..10b1d7c
--- /dev/null
+++ b/res/layout/drop_target_bar_vert.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 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.launcher3.DropTargetBar
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/dynamic_grid_drop_target_size"
+ android:orientation="vertical"
+ android:layout_height="match_parent"
+ android:layout_gravity="left"
+ android:focusable="false"
+ android:paddingTop="@dimen/vert_drop_target_vertical_gap" >
+
+ <!-- Delete target -->
+ <com.android.launcher3.DeleteDropTarget
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/dynamic_grid_drop_target_size"
+ android:gravity="center"
+ android:paddingLeft="@dimen/vert_drop_target_horizontal_gap"
+ android:paddingRight="@dimen/vert_drop_target_horizontal_gap"
+ android:id="@+id/delete_target_text"
+ android:textColor="@android:color/white" />
+
+ <!-- Uninstall target -->
+ <com.android.launcher3.UninstallDropTarget
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/dynamic_grid_drop_target_size"
+ android:gravity="center"
+ android:paddingLeft="@dimen/vert_drop_target_horizontal_gap"
+ android:paddingRight="@dimen/vert_drop_target_horizontal_gap"
+ android:id="@+id/uninstall_target_text"
+ android:textColor="@android:color/white"
+ android:layout_marginTop="@dimen/vert_drop_target_vertical_gap"/>
+
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <!-- App Info -->
+ <com.android.launcher3.InfoDropTarget
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/dynamic_grid_drop_target_size"
+ android:gravity="center"
+ android:paddingLeft="@dimen/vert_drop_target_horizontal_gap"
+ android:paddingRight="@dimen/vert_drop_target_horizontal_gap"
+ android:id="@+id/info_target_text"
+ android:textColor="@android:color/white"
+ android:layout_marginBottom="64dp"/>
+
+</com.android.launcher3.DropTargetBar>
\ No newline at end of file
diff --git a/res/layout/drop_target_bar_vert_info.xml b/res/layout/drop_target_bar_vert_info.xml
deleted file mode 100644
index da33d1a..0000000
--- a/res/layout/drop_target_bar_vert_info.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 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.launcher3.AppInfoDropTargetBar xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="48dp"
- android:layout_height="match_parent"
- android:focusable="false" >
-
- <FrameLayout
- android:id="@+id/drag_target_bar"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <!-- Info target -->
- <com.android.launcher3.InfoDropTarget
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_gravity="center_horizontal|bottom"
- android:gravity="center"
- android:paddingLeft="14dp"
- android:paddingRight="14dp"
- android:textColor="@android:color/white"
- android:id="@+id/info_target_text" />
- </FrameLayout>
-
-</com.android.launcher3.AppInfoDropTargetBar>
\ No newline at end of file
diff --git a/res/layout/drop_target_bar_vert_search.xml b/res/layout/drop_target_bar_vert_search.xml
deleted file mode 100644
index d5e41df..0000000
--- a/res/layout/drop_target_bar_vert_search.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.launcher3.SearchDropTargetBar xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="48dp"
- android:layout_height="match_parent"
- android:focusable="false">
-
- <!-- Drag specific targets container -->
-
- <LinearLayout
- android:id="@+id/drag_target_bar"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:layout_gravity="center"
- android:paddingTop="20dp">
-
- <!-- Delete target -->
- <com.android.launcher3.DeleteDropTarget
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:gravity="center"
- android:paddingLeft="14dp"
- android:paddingRight="14dp"
- android:id="@+id/delete_target_text"
- android:textColor="@android:color/white"
- android:layout_marginBottom="10dp" />
-
- <!-- Uninstall target -->
- <com.android.launcher3.UninstallDropTarget
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_gravity="center"
- android:gravity="center"
- android:paddingLeft="14dp"
- android:paddingRight="14dp"
- android:id="@+id/uninstall_target_text"
- android:textColor="@android:color/white"
- android:layout_marginTop="10dp"/>
- </LinearLayout>
-
-</com.android.launcher3.SearchDropTargetBar>
\ No newline at end of file
diff --git a/res/layout/qsb_container.xml b/res/layout/qsb_container.xml
index 3de2876..55c7390 100644
--- a/res/layout/qsb_container.xml
+++ b/res/layout/qsb_container.xml
@@ -20,4 +20,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/qsb_container"
- android:padding="0dp" />
\ No newline at end of file
+ android:padding="0dp" >
+
+ <fragment
+ android:name="com.android.launcher3.QsbContainerView$QsbFragment"
+ android:layout_width="match_parent"
+ android:tag="qsb_view"
+ android:layout_height="match_parent"/>
+</com.android.launcher3.QsbContainerView>
\ No newline at end of file
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 1169f44..8fa7586 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -76,10 +76,10 @@
<string name="allow_rotation_desc" msgid="7635719920854330492">"Al girar el dispositivo"</string>
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"La configuración de pantalla actual no permite girar la pantalla"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
+ <string name="abandoned_clean_this" msgid="7610119707847920412">"Quitar"</string>
<string name="abandoned_search" msgid="891119232568284442">"Buscar"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Esta aplicación no está instalada"</string>
- <string name="abandoned_promise_explanation" msgid="3990027586878167529">"La aplicación de este icono no está instalada. Puedes eliminar el icono o buscar la aplicación e instalarla manualmente."</string>
+ <string name="abandoned_promise_explanation" msgid="3990027586878167529">"La aplicación de este icono no está instalada. Puedes quitar el icono o buscar la aplicación e instalarla manualmente."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Descargando <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="PROGRESS">%2$s</xliff:g> completado)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Esperando para instalar <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Añadir a la pantalla de inicio"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 682cc12..3cc1885 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -59,7 +59,7 @@
<string name="migration_cling_description" msgid="2752413805582227644">"გსურთ, ძველი მთავარი ეკრანიდან ხატულების და საქაღ. იმპორტი?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ხატულების კოპირება"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"სტანდარტული განლაგება"</string>
- <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"ფონები, ვიჯეტები, & პარამეტრები"</string>
+ <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"ფონები, ვიჯეტები & პარამეტრები"</string>
<string name="workspace_cling_longpress_description" msgid="6569028007301925917">"მოსარგებად, ხანგრძლივად შეეხეთ ფონს."</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"გასაგებია"</string>
<string name="folder_opened" msgid="94695026776264709">"საქაღალდე გახსნილია, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index 9081e84..a1acc03 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -35,7 +35,7 @@
<string name="all_apps_search_market_message" msgid="5470761048755751471">"<xliff:g id="QUERY">%1$s</xliff:g>ကို သွားပါ"</string>
<string name="out_of_space" msgid="4691004494942118364">"ဤပင်မမျက်နှာစာတွင် နေရာလွတ် မကျန်တော့ပါ"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"အနှစ်သက်ဆုံးများ ထားရာတွင် နေရာလွတ် မကျန်တော့ပါ"</string>
- <string name="all_apps_button_label" msgid="9110807029020582876">"အပ်ပလီကေးရှင်းများ"</string>
+ <string name="all_apps_button_label" msgid="9110807029020582876">"အက်ပ်များ"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"ပင်မစာမျက်နှာ"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"ဖယ်ရှားမည်"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ဖယ်ထုတ်မည်"</string>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index 169f3de..acebc33 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -59,7 +59,7 @@
<string name="migration_cling_description" msgid="2752413805582227644">"आफ्नो पुरानो गृह स्क्रीनबाट अाईकन र फोल्डरहरू आयात गर्नुहोस्?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ICONS प्रतिलिप गर्नुहोस्"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"START FRESH"</string>
- <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"वालपेपरहरू, विजेट; सेटिङहरू"</string>
+ <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"वालपेपर, विजेट तथा सेटिङहरू"</string>
<string name="workspace_cling_longpress_description" msgid="6569028007301925917">"अनुकूलन गर्नका लागि पृष्ठभूमिलाई ट्याप गरी थिचिरहनुहोस्"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"बुँझें"</string>
<string name="folder_opened" msgid="94695026776264709">"फोल्डर खुल्यो <xliff:g id="WIDTH">%1$d</xliff:g> बाट <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml
index 47bb556..8e8e6ea 100644
--- a/res/values-pa-rIN/strings.xml
+++ b/res/values-pa-rIN/strings.xml
@@ -30,7 +30,7 @@
<string name="long_accessible_way_to_add" msgid="4289502106628154155">"ਡਬਲ-ਟੈਪ & ਇੱਕ ਵਿਜੇਟ ਚੁਣਨ ਲਈ ਹੋਲਡ ਕਰੋ ਅਤੇ ਕਸਟਮ ਕਿਰਿਆਵਾਂ ਵਰਤੋ।"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="6705987535534678581">"ਐਪਾਂ ਖੋਜੋ…"</string>
- <string name="all_apps_loading_message" msgid="7557140873644765180">"ਐਪਸ ਲੋਡ ਕਰ ਰਿਹਾ ਹੈ..."</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"ਐਪਾਂ ਨੂੰ ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..."</string>
<string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ਨਾਲ ਮਿਲਦੀਆਂ ਕੋਈ ਵੀ ਐਪਾਂ ਨਹੀਂ ਮਿਲੀਆਂ"</string>
<string name="all_apps_search_market_message" msgid="5470761048755751471">"<xliff:g id="QUERY">%1$s</xliff:g> ਤੇ ਜਾਓ"</string>
<string name="out_of_space" msgid="4691004494942118364">"ਇਸ ਹੋਮ ਸਕ੍ਰੀਨ ਲਈ ਹੋਰ ਖਾਲੀ ਸਥਾਨ ਨਹੀਂ ਹੈ।"</string>
@@ -40,12 +40,12 @@
<string name="remove_drop_target_label" msgid="7812859488053230776">"ਹਟਾਓ"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ਸਥਾਪਨਾ ਰੱਦ ਕਰੋ"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ਐਪ ਜਾਣਕਾਰੀ"</string>
- <string name="permlab_install_shortcut" msgid="5632423390354674437">"ਸ਼ੌਰਟਕਟ ਇੰਸਟੌਲ ਕਰੋ"</string>
- <string name="permdesc_install_shortcut" msgid="923466509822011139">"ਇੱਕ ਐਪ ਨੂੰ ਉਪਭੋਗਤਾ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਸ਼ੌਰਟਕਟ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ੌਰਟਕਟ ਪੜ੍ਹੋ"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ੌਰਟਕਟ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ੌਰਟਕਟ ਲਿਖੋ"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ੌਰਟਕਟ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+ <string name="permlab_install_shortcut" msgid="5632423390354674437">"ਸ਼ਾਰਟਕੱਟ ਇੰਸਟੌਲ ਕਰੋ"</string>
+ <string name="permdesc_install_shortcut" msgid="923466509822011139">"ਇੱਕ ਐਪ ਨੂੰ ਉਪਭੋਗਤਾ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਸ਼ਾਰਟਕੱਟ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+ <string name="permlab_read_settings" msgid="1941457408239617576">"ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਪੜ੍ਹੋ"</string>
+ <string name="permdesc_read_settings" msgid="5833423719057558387">"ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+ <string name="permlab_write_settings" msgid="3574213698004620587">"ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਲਿਖੋ"</string>
+ <string name="permdesc_write_settings" msgid="5440712911516509985">"ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਫੋਨ ਕਾਲਾਂ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ"</string>
<string name="gadget_error_text" msgid="6081085226050792095">"ਵਿਜੇਟ ਲੋਡ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"ਸਥਾਪਤ ਕਰੋ"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 5b2eb27..19f7a77 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -62,7 +62,7 @@
<string name="migration_cling_copy_apps" msgid="946331230090919440">"NAKILI IKONI"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ANZA UPYA"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Mandhari, wijeti na mipangilio"</string>
- <string name="workspace_cling_longpress_description" msgid="6569028007301925917">"Gusa na ushikilie mandhari ili uweke mapendeleo"</string>
+ <string name="workspace_cling_longpress_description" msgid="6569028007301925917">"Gusa na ushikilie mandhari ili ubadilishe upendavyo"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"NIMEELEWA"</string>
<string name="folder_opened" msgid="94695026776264709">"Folda imefunguliwa, <xliff:g id="WIDTH">%1$d</xliff:g> kwa <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="4625795376335528256">"Gonga ili ufunge folda"</string>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 7510fafd..35ee58e 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -17,19 +17,7 @@
<resources>
<!-- Dynamic Grid -->
<dimen name="dynamic_grid_edge_margin">6dp</dimen>
- <dimen name="dynamic_grid_search_bar_height">48dp</dimen>
- <!-- We want 46dp extra for the tall search bar. -->
- <dimen name="dynamic_grid_search_bar_height_tall">94dp</dimen>
- <dimen name="qsb_internal_padding_top">8dp</dimen>
- <dimen name="qsb_internal_padding_bottom">8dp</dimen>
- <dimen name="dynamic_grid_search_bar_extra_top_padding">0dp</dimen>
- <!-- Reduce the space between the status bar and the search bar when the search bar is tall -->
- <dimen name="dynamic_grid_search_bar_negative_top_padding_short">-4dp</dimen>
- <dimen name="dynamic_grid_search_bar_bottom_padding">4dp</dimen>
- <!-- Reduce the padding between the search bar and workspace when the search bar is tall -->
- <dimen name="dynamic_grid_search_bar_bottom_negative_padding_short">-6dp</dimen>
- <dimen name="dynamic_grid_search_bar_bottom_padding_tablet">16dp</dimen>
- <dimen name="dynamic_grid_page_indicator_height">20dp</dimen>
+ <dimen name="dynamic_grid_page_indicator_height">1dp</dimen>
<dimen name="dynamic_grid_icon_drawable_padding">4dp</dimen>
<dimen name="dynamic_grid_workspace_page_spacing">8dp</dimen>
<dimen name="dynamic_grid_overview_min_icon_zone_height">80dp</dimen>
@@ -37,6 +25,15 @@
<dimen name="dynamic_grid_overview_bar_item_width">80dp</dimen>
<dimen name="dynamic_grid_overview_bar_spacer_width">20dp</dimen>
+ <dimen name="dynamic_grid_workspace_top_padding">12dp</dimen>
+ <!-- Minimum space between workspace and hotseat in spring loaded mode -->
+ <dimen name="dynamic_grid_min_spring_loaded_space">8dp</dimen>
+
+<!-- Drop target bar -->
+ <dimen name="dynamic_grid_drop_target_size">48dp</dimen>
+ <dimen name="vert_drop_target_vertical_gap">20dp</dimen>
+ <dimen name="vert_drop_target_horizontal_gap">14dp</dimen>
+
<!-- App Widget resize frame -->
<dimen name="default_widget_padding">8dp</dimen>
<dimen name="widget_handle_margin">13dp</dimen>
diff --git a/src/com/android/launcher3/AppInfoDropTargetBar.java b/src/com/android/launcher3/AppInfoDropTargetBar.java
deleted file mode 100644
index e06f941..0000000
--- a/src/com/android/launcher3/AppInfoDropTargetBar.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.launcher3.dragndrop.DragController;
-
-public class AppInfoDropTargetBar extends BaseDropTargetBar {
- private ButtonDropTarget mAppInfoDropTarget;
-
- public AppInfoDropTargetBar(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public AppInfoDropTargetBar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- // Get the individual components
- mAppInfoDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.info_target_text);
-
- mAppInfoDropTarget.setDropTargetBar(this);
- }
-
- @Override
- public void setup(Launcher launcher, DragController dragController) {
- dragController.addDragListener(this);
-
- dragController.addDragListener(mAppInfoDropTarget);
- dragController.addDropTarget(mAppInfoDropTarget);
-
- mAppInfoDropTarget.setLauncher(launcher);
- }
-
- @Override
- public void showDropTargets() {
- animateDropTargetBarToAlpha(1f, DEFAULT_DRAG_FADE_DURATION);
- }
-
- @Override
- public void hideDropTargets() {
- animateDropTargetBarToAlpha(0f, DEFAULT_DRAG_FADE_DURATION);
- }
-
- private void animateDropTargetBarToAlpha(float alpha, int duration) {
- resetAnimation(duration);
- if (duration > 0) {
- animateAlpha(mDropTargetBar, alpha, DEFAULT_INTERPOLATOR);
- mCurrentAnimation.start();
- } else {
- mDropTargetBar.setAlpha(alpha);
- AlphaUpdateListener.updateVisibility(mDropTargetBar, mAccessibilityEnabled);
- }
- }
-
- @Override
- public void enableAccessibleDrag(boolean enable) {
- mAppInfoDropTarget.enableAccessibleDrag(enable);
- }
-}
diff --git a/src/com/android/launcher3/BaseContainerView.java b/src/com/android/launcher3/BaseContainerView.java
index d0cacd3..a9ef43d 100644
--- a/src/com/android/launcher3/BaseContainerView.java
+++ b/src/com/android/launcher3/BaseContainerView.java
@@ -24,6 +24,9 @@
import android.view.View;
import android.widget.FrameLayout;
+import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.config.FeatureFlags;
+
/**
* A base container view, which supports resizing.
*/
@@ -48,7 +51,11 @@
super(context, attrs, defStyleAttr);
int width = ((Launcher) context).getDeviceProfile().availableWidthPx;
- mHorizontalPadding = DeviceProfile.getContainerPadding(context, width);
+ if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && (this instanceof AllAppsContainerView)) {
+ mHorizontalPadding = 0;
+ } else {
+ mHorizontalPadding = DeviceProfile.getContainerPadding(context, width);
+ }
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.BaseContainerView, defStyleAttr, 0);
diff --git a/src/com/android/launcher3/BaseDropTargetBar.java b/src/com/android/launcher3/BaseDropTargetBar.java
deleted file mode 100644
index 9b38623..0000000
--- a/src/com/android/launcher3/BaseDropTargetBar.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.TimeInterpolator;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.accessibility.AccessibilityManager;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.FrameLayout;
-
-import com.android.launcher3.dragndrop.DragController;
-
-/**
- * Base class for drop target bars (where you can drop apps to do actions such as uninstall).
- */
-public abstract class BaseDropTargetBar extends FrameLayout implements DragController.DragListener {
- protected static final int DEFAULT_DRAG_FADE_DURATION = 175;
- protected static final TimeInterpolator DEFAULT_INTERPOLATOR = new AccelerateInterpolator();
-
- protected View mDropTargetBar;
- protected boolean mAccessibilityEnabled = false;
-
- protected AnimatorSet mCurrentAnimation;
- protected boolean mDeferOnDragEnd;
-
- public BaseDropTargetBar(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public BaseDropTargetBar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- mDropTargetBar = findViewById(R.id.drag_target_bar);
-
- // Create the various fade animations
- mDropTargetBar.setAlpha(0f);
- }
-
- /**
- * Convenience method to animate the alpha of a view.
- */
- protected void animateAlpha(View v, float alpha, TimeInterpolator interpolator) {
- if (Float.compare(v.getAlpha(), alpha) != 0) {
- ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.ALPHA, alpha);
- anim.setInterpolator(interpolator);
- anim.addListener(new ViewVisiblilyUpdateHandler(v));
- mCurrentAnimation.play(anim);
- }
- }
-
- protected void resetAnimation(int newAnimationDuration) {
- // Update the accessibility state
- AccessibilityManager am = (AccessibilityManager)
- getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
- mAccessibilityEnabled = am.isEnabled();
-
- // Cancel any existing animation
- if (mCurrentAnimation != null) {
- mCurrentAnimation.cancel();
- mCurrentAnimation = null;
- }
-
- if (newAnimationDuration > 0) {
- mCurrentAnimation = new AnimatorSet();
- mCurrentAnimation.setDuration(newAnimationDuration);
- }
- }
-
- /*
- * DragController.DragListener implementation
- */
- @Override
- public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
- showDropTargets();
- }
-
- /**
- * This is called to defer hiding the delete drop target until the drop animation has completed,
- * instead of hiding immediately when the drag has ended.
- */
- protected void deferOnDragEnd() {
- mDeferOnDragEnd = true;
- }
-
- @Override
- public void onDragEnd() {
- if (!mDeferOnDragEnd) {
- hideDropTargets();
- } else {
- mDeferOnDragEnd = false;
- }
- }
-
- public abstract void showDropTargets();
-
- public abstract void hideDropTargets();
-
- public abstract void enableAccessibleDrag(boolean enable);
-
- public abstract void setup(Launcher launcher, DragController dragController);
-
- private class ViewVisiblilyUpdateHandler extends AnimatorListenerAdapter {
- private final View mView;
-
- ViewVisiblilyUpdateHandler(View v) {
- mView = v;
- }
-
- @Override
- public void onAnimationStart(Animator animation) {
- // Ensure that the view is visible for the animation
- mView.setVisibility(View.VISIBLE);
- }
-
- @Override
- public void onAnimationEnd(Animator animation){
- AlphaUpdateListener.updateVisibility(mView, mAccessibilityEnabled);
- }
-
- }
-}
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 43afbe5..61ac713 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -55,10 +55,10 @@
private static final int DRAG_VIEW_DROP_DURATION = 285;
private final boolean mHideParentOnDisable;
+ protected final Launcher mLauncher;
- protected Launcher mLauncher;
private int mBottomDragPadding;
- protected BaseDropTargetBar mDropTargetBar;
+ protected DropTargetBar mDropTargetBar;
/** Whether this drop target is active for the current drag */
protected boolean mActive;
@@ -80,6 +80,8 @@
public ButtonDropTarget(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ mLauncher = (Launcher) context;
+
Resources resources = getResources();
mBottomDragPadding = resources.getDimensionPixelSize(R.dimen.drop_target_drag_padding);
@@ -109,11 +111,7 @@
}
}
- public void setLauncher(Launcher launcher) {
- mLauncher = launcher;
- }
-
- public void setDropTargetBar(BaseDropTargetBar dropTargetBar) {
+ public void setDropTargetBar(DropTargetBar dropTargetBar) {
mDropTargetBar = dropTargetBar;
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 8d11aaa..4a550ed 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -70,7 +70,10 @@
public final Rect defaultWidgetPadding;
private final int pageIndicatorHeightPx;
private final int defaultPageSpacingPx;
+ private final int topWorkspacePadding;
private float dragViewScale;
+ public float workspaceSpringLoadShrinkFactor;
+ public final int workspaceSpringLoadedBottomSpace;
// Workspace icons
public int iconSizePx;
@@ -92,8 +95,7 @@
public int hotseatCellWidthPx;
public int hotseatCellHeightPx;
public int hotseatIconSizePx;
- private int normalHotseatBarHeightPx, shortHotseatBarHeightPx;
- private int hotseatBarHeightPx; // One of the above.
+ private int hotseatBarHeightPx;
// All apps
public int allAppsNumCols;
@@ -102,15 +104,8 @@
public final int allAppsIconSizePx;
public final float allAppsIconTextSizeSp;
- // QSB
- private int searchBarWidgetInternalPaddingTop, searchBarWidgetInternalPaddingBottom;
- private int searchBarTopPaddingPx;
- private int tallSearchBarNegativeTopPaddingPx, normalSearchBarTopExtraPaddingPx;
- private int searchBarTopExtraPaddingPx; // One of the above.
- private int normalSearchBarBottomPaddingPx, tallSearchBarBottomPaddingPx;
- private int searchBarBottomPaddingPx; // One of the above.
- private int normalSearchBarSpaceHeightPx, tallSearchBarSpaceHeightPx;
- private int searchBarSpaceHeightPx; // One of the above.
+ // Drop Target
+ public int dropTargetBarSizePx;
public DeviceProfile(Context context, InvariantDeviceProfile inv,
Point minSize, Point maxSize,
@@ -140,6 +135,8 @@
res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height);
defaultPageSpacingPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_page_spacing);
+ topWorkspacePadding =
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_top_padding);
overviewModeMinIconZoneHeightPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_min_icon_zone_height);
overviewModeMaxIconZoneHeightPx =
@@ -152,6 +149,9 @@
res.getInteger(R.integer.config_dynamic_grid_overview_icon_zone_percentage) / 100f;
iconDrawablePaddingOriginalPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
+ dropTargetBarSizePx = res.getDimensionPixelSize(R.dimen.dynamic_grid_drop_target_size);
+ workspaceSpringLoadedBottomSpace =
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_min_spring_loaded_space);
// AllApps uses the original non-scaled icon text size
allAppsIconTextSizeSp = inv.iconTextSize;
@@ -195,7 +195,7 @@
float usedHeight = (cellHeightPx * inv.numRows);
// We only care about the top and bottom workspace padding, which is not affected by RTL.
- Rect workspacePadding = getWorkspacePadding(false /* isLayoutRtl */);
+ Rect workspacePadding = getWorkspacePadding();
int maxHeight = (availableHeightPx - workspacePadding.top - workspacePadding.bottom);
if (usedHeight > maxHeight) {
scale = maxHeight / usedHeight;
@@ -211,33 +211,6 @@
iconDrawablePaddingPx = drawablePadding;
hotseatIconSizePx = (int) (Utilities.pxFromDp(inv.hotseatIconSize, dm) * scale);
- // Search Bar
- normalSearchBarSpaceHeightPx = res.getDimensionPixelSize(
- R.dimen.dynamic_grid_search_bar_height);
- tallSearchBarSpaceHeightPx = res.getDimensionPixelSize(
- R.dimen.dynamic_grid_search_bar_height_tall);
- searchBarWidgetInternalPaddingTop = res.getDimensionPixelSize(
- R.dimen.qsb_internal_padding_top);
- searchBarWidgetInternalPaddingBottom = res.getDimensionPixelSize(
- R.dimen.qsb_internal_padding_bottom);
- normalSearchBarTopExtraPaddingPx = res.getDimensionPixelSize(
- R.dimen.dynamic_grid_search_bar_extra_top_padding);
- tallSearchBarNegativeTopPaddingPx = res.getDimensionPixelSize(
- R.dimen.dynamic_grid_search_bar_negative_top_padding_short);
- if (isTablet && !isVerticalBarLayout()) {
- searchBarTopPaddingPx = searchBarWidgetInternalPaddingTop;
- normalSearchBarBottomPaddingPx = searchBarWidgetInternalPaddingBottom +
- res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_bottom_padding_tablet);
- tallSearchBarBottomPaddingPx = normalSearchBarBottomPaddingPx;
- } else {
- searchBarTopPaddingPx = searchBarWidgetInternalPaddingTop;
- normalSearchBarBottomPaddingPx = searchBarWidgetInternalPaddingBottom +
- res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_bottom_padding);
- tallSearchBarBottomPaddingPx = searchBarWidgetInternalPaddingBottom
- + res.getDimensionPixelSize(
- R.dimen.dynamic_grid_search_bar_bottom_negative_padding_short);
- }
-
// Calculate the actual text height
Paint textPaint = new Paint();
textPaint.setTextSize(iconTextSizePx);
@@ -249,11 +222,22 @@
dragViewScale = (iconSizePx + scaleDps) / iconSizePx;
// Hotseat
- normalHotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx;
- shortHotseatBarHeightPx = iconSizePx + 2 * edgeMarginPx;
+ hotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx;
hotseatCellWidthPx = iconSizePx;
hotseatCellHeightPx = iconSizePx;
+ if (!isVerticalBarLayout()) {
+ int expectedWorkspaceHeight = availableHeightPx - hotseatBarHeightPx
+ - pageIndicatorHeightPx - topWorkspacePadding;
+ float minRequiredHeight = dropTargetBarSizePx + workspaceSpringLoadedBottomSpace;
+ workspaceSpringLoadShrinkFactor = Math.min(
+ res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f,
+ 1 - (minRequiredHeight / expectedWorkspaceHeight));
+ } else {
+ workspaceSpringLoadShrinkFactor =
+ res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
+ }
+
// Folder
int folderCellPadding = isTablet || isLandscape ? 6 * edgeMarginPx : 3 * edgeMarginPx;
// Don't let the folder get too close to the edges of the screen.
@@ -281,60 +265,33 @@
allAppsNumPredictiveCols = numPredictiveAppCols;
}
- /** Returns the amount of extra space to allocate to the search bar for vertical padding. */
- private int getSearchBarTotalVerticalPadding() {
- return searchBarTopPaddingPx + searchBarTopExtraPaddingPx + searchBarBottomPaddingPx;
- }
-
/** Returns the width and height of the search bar, ignoring any padding. */
- public Point getSearchBarDimensForWidgetOpts(Resources res) {
- Rect searchBarBounds = getSearchBarBounds(Utilities.isRtl(res));
+ public Point getSearchBarDimensForWidgetOpts() {
if (isVerticalBarLayout()) {
- return new Point(searchBarBounds.width(), searchBarBounds.height());
- }
- int widgetInternalPadding = searchBarWidgetInternalPaddingTop +
- searchBarWidgetInternalPaddingBottom;
- return new Point(searchBarBounds.width(), searchBarSpaceHeightPx + widgetInternalPadding);
- }
-
- /** Returns the search bar bounds in the current orientation */
- public Rect getSearchBarBounds(boolean isLayoutRtl) {
- Rect bounds = new Rect();
- if (isVerticalBarLayout()) {
- if (isLayoutRtl) {
- bounds.set(availableWidthPx - normalSearchBarSpaceHeightPx, edgeMarginPx,
- availableWidthPx, availableHeightPx - edgeMarginPx);
- } else {
- bounds.set(0, edgeMarginPx, normalSearchBarSpaceHeightPx,
- availableHeightPx - edgeMarginPx);
- }
+ return new Point(dropTargetBarSizePx, availableHeightPx - 2 * edgeMarginPx);
} else {
- int boundsBottom = searchBarSpaceHeightPx + getSearchBarTotalVerticalPadding();
+ int gap;
if (isTablet) {
// Pad the left and right of the workspace to ensure consistent spacing
// between all icons
int width = getCurrentWidth();
// XXX: If the icon size changes across orientations, we will have to take
// that into account here too.
- int gap = (int) ((width - 2 * edgeMarginPx -
- (inv.numColumns * cellWidthPx)) / (2 * (inv.numColumns + 1)));
- bounds.set(edgeMarginPx + gap, 0,
- availableWidthPx - (edgeMarginPx + gap), boundsBottom);
+ gap = ((width - 2 * edgeMarginPx
+ - (inv.numColumns * cellWidthPx)) / (2 * (inv.numColumns + 1)))
+ + edgeMarginPx;
} else {
- bounds.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,
- 0,
- availableWidthPx - (desiredWorkspaceLeftRightMarginPx -
- defaultWidgetPadding.right), boundsBottom);
+ gap = desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right;
}
+ return new Point(availableWidthPx - 2 * gap, dropTargetBarSizePx);
}
- return bounds;
}
public Point getCellSize() {
Point result = new Point();
// Since we are only concerned with the overall padding, layout direction does
// not matter.
- Rect padding = getWorkspacePadding(false /* isLayoutRtl */ );
+ Rect padding = getWorkspacePadding();
result.x = calculateCellWidth(availableWidthPx - padding.left - padding.right,
inv.numColumns);
result.y = calculateCellHeight(availableHeightPx - padding.top - padding.bottom,
@@ -343,20 +300,13 @@
}
/** Returns the workspace padding in the specified orientation */
- public Rect getWorkspacePadding(boolean isLayoutRtl) {
- Rect searchBarBounds = getSearchBarBounds(isLayoutRtl);
+ public Rect getWorkspacePadding() {
Rect padding = new Rect();
if (isVerticalBarLayout()) {
- // Pad the left and right of the workspace with search/hotseat bar sizes
- if (isLayoutRtl) {
- padding.set(normalHotseatBarHeightPx, edgeMarginPx,
- searchBarBounds.width(), edgeMarginPx);
- } else {
- padding.set(searchBarBounds.width(), edgeMarginPx,
- normalHotseatBarHeightPx, edgeMarginPx);
- }
+ // in case of isVerticalBarLayout, the hotseat is always on the right and the drop
+ // target bar is on the left, independent of the layout direction.
+ padding.set(dropTargetBarSizePx, edgeMarginPx, hotseatBarHeightPx, edgeMarginPx);
} else {
- int paddingTop = searchBarBounds.bottom;
int paddingBottom = hotseatBarHeightPx + pageIndicatorHeightPx;
if (isTablet) {
// Pad the left and right of the workspace to ensure consistent spacing
@@ -369,14 +319,14 @@
((inv.numColumns - 1) * gapScale * cellWidthPx)));
availablePaddingX = (int) Math.min(availablePaddingX,
width * MAX_HORIZONTAL_PADDING_PERCENT);
- int availablePaddingY = Math.max(0, height - paddingTop - paddingBottom
+ int availablePaddingY = Math.max(0, height - topWorkspacePadding - paddingBottom
- (int) (2 * inv.numRows * cellHeightPx));
- padding.set(availablePaddingX / 2, paddingTop + availablePaddingY / 2,
+ padding.set(availablePaddingX / 2, topWorkspacePadding + availablePaddingY / 2,
availablePaddingX / 2, paddingBottom + availablePaddingY / 2);
} else {
// Pad the top and bottom of the workspace with search/hotseat bar sizes
padding.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,
- paddingTop,
+ topWorkspacePadding,
desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right,
paddingBottom);
}
@@ -384,7 +334,7 @@
return padding;
}
- private int getWorkspacePageSpacing(boolean isLayoutRtl) {
+ private int getWorkspacePageSpacing() {
if (isVerticalBarLayout() || isLargeTablet) {
// In landscape mode the page spacing is set to the default.
return defaultPageSpacingPx;
@@ -392,7 +342,7 @@
// In portrait, we want the pages spaced such that there is no
// overhang of the previous / next page into the current page viewport.
// We assume symmetrical padding in portrait mode.
- return Math.max(defaultPageSpacingPx, 2 * getWorkspacePadding(isLayoutRtl).left);
+ return Math.max(defaultPageSpacingPx, 2 * getWorkspacePadding().left);
}
}
@@ -444,50 +394,28 @@
return visibleChildren;
}
- // TODO(twickham): b/25154513
- public void setSearchBarHeight(int searchBarHeight) {
- if (searchBarHeight == LauncherCallbacks.SEARCH_BAR_HEIGHT_TALL) {
- hotseatBarHeightPx = shortHotseatBarHeightPx;
- searchBarSpaceHeightPx = tallSearchBarSpaceHeightPx;
- searchBarBottomPaddingPx = tallSearchBarBottomPaddingPx;
- searchBarTopExtraPaddingPx = isPhone ? tallSearchBarNegativeTopPaddingPx
- : normalSearchBarTopExtraPaddingPx;
- } else {
- hotseatBarHeightPx = normalHotseatBarHeightPx;
- searchBarSpaceHeightPx = normalSearchBarSpaceHeightPx;
- searchBarBottomPaddingPx = normalSearchBarBottomPaddingPx;
- searchBarTopExtraPaddingPx = normalSearchBarTopExtraPaddingPx;
- }
- }
-
public void layout(Launcher launcher) {
FrameLayout.LayoutParams lp;
boolean hasVerticalBarLayout = isVerticalBarLayout();
final boolean isLayoutRtl = Utilities.isRtl(launcher.getResources());
// Layout the search bar space
- Rect searchBarBounds = getSearchBarBounds(isLayoutRtl);
- View searchBar = launcher.getSearchDropTargetBar();
+ Point searchBarBounds = getSearchBarDimensForWidgetOpts();
+ View searchBar = launcher.getDropTargetBar();
lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams();
- lp.width = searchBarBounds.width();
- lp.height = searchBarBounds.height();
- lp.topMargin = searchBarTopExtraPaddingPx;
+ lp.width = searchBarBounds.x;
+ lp.height = searchBarBounds.y;
+ lp.topMargin = edgeMarginPx;
searchBar.setLayoutParams(lp);
- // Layout the app info bar space
- View appInfoBar = launcher.getAppInfoDropTargetBar();
- lp = (FrameLayout.LayoutParams) appInfoBar.getLayoutParams();
- lp.bottomMargin = hotseatBarHeightPx;
- appInfoBar.setLayoutParams(lp);
-
// Layout the workspace
PagedView workspace = (PagedView) launcher.findViewById(R.id.workspace);
lp = (FrameLayout.LayoutParams) workspace.getLayoutParams();
lp.gravity = Gravity.CENTER;
- Rect padding = getWorkspacePadding(isLayoutRtl);
+ Rect padding = getWorkspacePadding();
workspace.setLayoutParams(lp);
workspace.setPadding(padding.left, padding.top, padding.right, padding.bottom);
- workspace.setPageSpacing(getWorkspacePageSpacing(isLayoutRtl));
+ workspace.setPageSpacing(getWorkspacePageSpacing());
// Layout the hotseat
View hotseat = launcher.findViewById(R.id.hotseat);
@@ -503,7 +431,7 @@
// Vertical hotseat -- The hotseat is fixed in the layout to be on the right of the
// screen regardless of RTL
lp.gravity = Gravity.RIGHT;
- lp.width = normalHotseatBarHeightPx;
+ lp.width = hotseatBarHeightPx;
lp.height = LayoutParams.MATCH_PARENT;
hotseat.findViewById(R.id.layout).setPadding(0, 2 * edgeMarginPx, 0, 2 * edgeMarginPx);
} else if (isTablet) {
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
new file mode 100644
index 0000000..5966af5
--- /dev/null
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -0,0 +1,153 @@
+/*
+ * 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.launcher3;
+
+import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewPropertyAnimator;
+import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AccelerateInterpolator;
+import android.widget.LinearLayout;
+
+import com.android.launcher3.dragndrop.DragController;
+
+/*
+ * The top bar containing various drop targets: Delete/App Info/Uninstall.
+ */
+public class DropTargetBar extends LinearLayout implements DragController.DragListener {
+
+ protected static final int DEFAULT_DRAG_FADE_DURATION = 175;
+ protected static final TimeInterpolator DEFAULT_INTERPOLATOR = new AccelerateInterpolator();
+
+ private final Runnable mFadeAnimationEndRunnable = new Runnable() {
+
+ @Override
+ public void run() {
+ AccessibilityManager am = (AccessibilityManager)
+ getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+ boolean accessibilityEnabled = am.isEnabled();
+ AlphaUpdateListener.updateVisibility(DropTargetBar.this, accessibilityEnabled);
+ }
+ };
+
+ @ViewDebug.ExportedProperty(category = "launcher")
+ protected boolean mDeferOnDragEnd;
+
+ @ViewDebug.ExportedProperty(category = "launcher")
+ protected boolean mVisible = false;
+
+ private ViewPropertyAnimator mCurrentAnimation;
+
+ // Drop targets
+ private ButtonDropTarget mDeleteDropTarget;
+ private ButtonDropTarget mAppInfoDropTarget;
+ private ButtonDropTarget mUninstallDropTarget;
+
+ public DropTargetBar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public DropTargetBar(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ // Get the individual components
+ mDeleteDropTarget = (ButtonDropTarget) findViewById(R.id.delete_target_text);
+ mAppInfoDropTarget = (ButtonDropTarget) findViewById(R.id.info_target_text);
+ mUninstallDropTarget = (ButtonDropTarget) findViewById(R.id.uninstall_target_text);
+
+ mDeleteDropTarget.setDropTargetBar(this);
+ mAppInfoDropTarget.setDropTargetBar(this);
+ mUninstallDropTarget.setDropTargetBar(this);
+
+ // Initialize with hidden state
+ setAlpha(0f);
+ }
+
+ public void setup(DragController dragController) {
+ dragController.addDragListener(this);
+ dragController.setFlingToDeleteDropTarget(mDeleteDropTarget);
+
+ dragController.addDragListener(mDeleteDropTarget);
+ dragController.addDragListener(mAppInfoDropTarget);
+ dragController.addDragListener(mUninstallDropTarget);
+
+ dragController.addDropTarget(mDeleteDropTarget);
+ dragController.addDropTarget(mAppInfoDropTarget);
+ dragController.addDropTarget(mUninstallDropTarget);
+ }
+
+ private void animateToVisibility(boolean isVisible) {
+ if (mVisible != isVisible) {
+ mVisible = isVisible;
+
+ // Cancel any existing animation
+ if (mCurrentAnimation != null) {
+ mCurrentAnimation.cancel();
+ mCurrentAnimation = null;
+ }
+
+ float finalAlpha = mVisible ? 1 : 0;
+ if (Float.compare(getAlpha(), finalAlpha) != 0) {
+ setVisibility(View.VISIBLE);
+ mCurrentAnimation = animate().alpha(finalAlpha)
+ .setInterpolator(DEFAULT_INTERPOLATOR)
+ .setDuration(DEFAULT_DRAG_FADE_DURATION)
+ .withEndAction(mFadeAnimationEndRunnable);
+ }
+
+ }
+ }
+
+ public void enableAccessibleDrag(boolean enable) {
+ mDeleteDropTarget.enableAccessibleDrag(enable);
+ mAppInfoDropTarget.enableAccessibleDrag(enable);
+ mUninstallDropTarget.enableAccessibleDrag(enable);
+ }
+
+ /*
+ * DragController.DragListener implementation
+ */
+ @Override
+ public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
+ animateToVisibility(true);
+ }
+
+ /**
+ * This is called to defer hiding the delete drop target until the drop animation has completed,
+ * instead of hiding immediately when the drag has ended.
+ */
+ protected void deferOnDragEnd() {
+ mDeferOnDragEnd = true;
+ }
+
+ @Override
+ public void onDragEnd() {
+ if (!mDeferOnDragEnd) {
+ animateToVisibility(false);
+ } else {
+ mDeferOnDragEnd = false;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java
index f99c08a..0b9e4ac 100644
--- a/src/com/android/launcher3/FocusHelper.java
+++ b/src/com/android/launcher3/FocusHelper.java
@@ -356,7 +356,7 @@
CellLayout iconLayout = (CellLayout) parent.getParent();
final Workspace workspace = (Workspace) iconLayout.getParent();
final ViewGroup dragLayer = (ViewGroup) workspace.getParent();
- final ViewGroup tabs = (ViewGroup) dragLayer.findViewById(R.id.search_drop_target_bar);
+ final ViewGroup tabs = (ViewGroup) dragLayer.findViewById(R.id.drop_target_bar);
final Hotseat hotseat = (Hotseat) dragLayer.findViewById(R.id.hotseat);
final ItemInfo itemInfo = (ItemInfo) v.getTag();
diff --git a/src/com/android/launcher3/InsettableFrameLayout.java b/src/com/android/launcher3/InsettableFrameLayout.java
index f4bfa45..61edc0f 100644
--- a/src/com/android/launcher3/InsettableFrameLayout.java
+++ b/src/com/android/launcher3/InsettableFrameLayout.java
@@ -9,6 +9,9 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;
+import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.config.FeatureFlags;
+
public class InsettableFrameLayout extends FrameLayout implements
ViewGroup.OnHierarchyChangeListener, Insettable {
@@ -31,6 +34,9 @@
lp.rightMargin += (newInsets.right - oldInsets.right);
lp.bottomMargin += (newInsets.bottom - oldInsets.bottom);
}
+ if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && child instanceof AllAppsContainerView) {
+ lp.setMargins(0, 0, 0, lp.bottomMargin);
+ }
child.setLayoutParams(lp);
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index ca31ea5..e1d292c 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -92,6 +92,7 @@
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.allapps.DefaultAppSearchController;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherActivityInfoCompat;
@@ -251,11 +252,11 @@
private View mAllAppsButton;
private View mWidgetsButton;
- private SearchDropTargetBar mSearchDropTargetBar;
- private AppInfoDropTargetBar mAppInfoDropTargetBar;
+ private DropTargetBar mDropTargetBar;
// Main container view for the all apps screen.
@Thunk AllAppsContainerView mAppsView;
+ AllAppsTransitionController mAllAppsController;
// Main container view and the model for the widget tray screen.
@Thunk WidgetsContainerView mWidgetsView;
@@ -413,7 +414,8 @@
mIconCache = app.getIconCache();
mDragController = new DragController(this);
- mStateTransitionAnimation = new LauncherStateTransitionAnimation(this);
+ mAllAppsController = new AllAppsTransitionController(this);
+ mStateTransitionAnimation = new LauncherStateTransitionAnimation(this, mAllAppsController);
mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
@@ -432,8 +434,6 @@
setContentView(R.layout.launcher);
- app.getInvariantDeviceProfile().landscapeProfile.setSearchBarHeight(getSearchBarHeight());
- app.getInvariantDeviceProfile().portraitProfile.setSearchBarHeight(getSearchBarHeight());
setupViews();
mDeviceProfile.layout(this);
mExtractedColors = new ExtractedColors();
@@ -1339,8 +1339,6 @@
* Finds all the views we need and configure them properly.
*/
private void setupViews() {
- final DragController dragController = mDragController;
-
mLauncherView = findViewById(R.id.launcher);
mFocusHandler = (FocusIndicatorView) findViewById(R.id.focus_indicator);
mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
@@ -1353,7 +1351,8 @@
mWorkspaceBackgroundDrawable = getResources().getDrawable(R.drawable.workspace_bg);
// Setup the drag layer
- mDragLayer.setup(this, dragController);
+
+ mDragLayer.setup(this, mDragController, mAllAppsController);
// Setup the hotseat
mHotseat = (Hotseat) findViewById(R.id.hotseat);
@@ -1367,16 +1366,12 @@
// Setup the workspace
mWorkspace.setHapticFeedbackEnabled(false);
mWorkspace.setOnLongClickListener(this);
- mWorkspace.setup(dragController);
+ mWorkspace.setup(mDragController);
mWorkspace.bindAndInitFirstWorkspaceScreen(null /* recycled qsb */);
- dragController.addDragListener(mWorkspace);
+ mDragController.addDragListener(mWorkspace);
// Get the search/delete/uninstall bar
- mSearchDropTargetBar = (SearchDropTargetBar)
- mDragLayer.findViewById(R.id.search_drop_target_bar);
- // Get the app info bar
- mAppInfoDropTargetBar = (AppInfoDropTargetBar)
- mDragLayer.findViewById(R.id.app_info_drop_target_bar);
+ mDropTargetBar = (DropTargetBar) mDragLayer.findViewById(R.id.drop_target_bar);
// Setup Apps and Widgets
mAppsView = (AllAppsContainerView) findViewById(R.id.apps_view);
@@ -1388,16 +1383,11 @@
}
// Setup the drag controller (drop targets have to be added in reverse order in priority)
- dragController.setDragScoller(mWorkspace);
- dragController.setScrollView(mDragLayer);
- dragController.setMoveTarget(mWorkspace);
- dragController.addDropTarget(mWorkspace);
- if (mSearchDropTargetBar != null) {
- mSearchDropTargetBar.setup(this, dragController);
- }
- if (mAppInfoDropTargetBar != null) {
- mAppInfoDropTargetBar.setup(this, dragController);
- }
+ mDragController.setDragScoller(mWorkspace);
+ mDragController.setScrollView(mDragLayer);
+ mDragController.setMoveTarget(mWorkspace);
+ mDragController.addDropTarget(mWorkspace);
+ mDropTargetBar.setup(mDragController);
if (TestingUtils.MEMORY_DUMP_ENABLED) {
TestingUtils.addWeightWatcher(this);
@@ -1806,12 +1796,8 @@
return mOverviewPanel;
}
- public SearchDropTargetBar getSearchDropTargetBar() {
- return mSearchDropTargetBar;
- }
-
- public AppInfoDropTargetBar getAppInfoDropTargetBar() {
- return mAppInfoDropTargetBar;
+ public DropTargetBar getDropTargetBar() {
+ return mDropTargetBar;
}
public LauncherAppWidgetHost getAppWidgetHost() {
@@ -1940,6 +1926,7 @@
if (mWorkspace.getChildCount() > 0) {
outState.putInt(RUNTIME_STATE_CURRENT_SCREEN,
mWorkspace.getCurrentPageOffsetFromCustomContent());
+
}
super.onSaveInstanceState(outState);
@@ -3163,6 +3150,8 @@
mWorkspace.startReordering(v);
} else {
showOverviewMode(true);
+ mHotseat.requestDisallowInterceptTouchEvent(true);
+
}
} else {
final boolean isAllAppsButton = inHotseat && isAllAppsButtonRank(
@@ -3318,7 +3307,7 @@
/**
* Shows the apps view.
*/
- void showAppsView(boolean animated, boolean resetListToTop, boolean updatePredictedApps,
+ public void showAppsView(boolean animated, boolean resetListToTop, boolean updatePredictedApps,
boolean focusSearchBar) {
if (resetListToTop) {
mAppsView.scrollToTop();
@@ -4034,11 +4023,6 @@
return mDeviceProfile.isVerticalBarLayout();
}
- /** Returns the search bar bounds in pixels. */
- protected Rect getSearchBarBounds() {
- return mDeviceProfile.getSearchBarBounds(Utilities.isRtl(getResources()));
- }
-
public int getSearchBarHeight() {
if (mLauncherCallbacks != null) {
return mLauncherCallbacks.getSearchBarHeight();
diff --git a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
index 28d8052..f245cd3 100644
--- a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
@@ -63,9 +63,8 @@
LauncherAppState app = LauncherAppState.getInstance();
InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
- // We only care out the cell size, which is independent of the the layout direction.
- Rect paddingLand = idp.landscapeProfile.getWorkspacePadding(false /* isLayoutRtl */);
- Rect paddingPort = idp.portraitProfile.getWorkspacePadding(false /* isLayoutRtl */);
+ Rect paddingLand = idp.landscapeProfile.getWorkspacePadding();
+ Rect paddingPort = idp.portraitProfile.getWorkspacePadding();
// 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/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
index 17a5424..ca09f31 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -33,6 +33,8 @@
import android.view.animation.DecelerateInterpolator;
import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.AllAppsTransitionController;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.UiThreadCircularReveal;
import com.android.launcher3.widget.WidgetsContainerView;
@@ -82,6 +84,17 @@
*/
public class LauncherStateTransitionAnimation {
+ /**
+ * animation used for all apps and widget tray when
+ *{@link FeatureFlags#LAUNCHER3_ALL_APPS_PULL_UP} is {@code false}
+ */
+ public static final int CIRCULAR_REVEAL = 0;
+ /**
+ * animation used for all apps and not widget tray when
+ *{@link FeatureFlags#LAUNCHER3_ALL_APPS_PULL_UP} is {@code true}
+ */
+ public static final int PULLUP = 1;
+
private static final float FINAL_REVEAL_ALPHA_FOR_WIDGETS = 0.3f;
/**
@@ -113,9 +126,11 @@
@Thunk Launcher mLauncher;
@Thunk AnimatorSet mCurrentAnimation;
+ AllAppsTransitionController mAllAppsController;
- public LauncherStateTransitionAnimation(Launcher l) {
+ public LauncherStateTransitionAnimation(Launcher l, AllAppsTransitionController allAppsController) {
mLauncher = l;
+ mAllAppsController = allAppsController;
}
/**
@@ -154,9 +169,13 @@
}
}
};
+ int animType = CIRCULAR_REVEAL;
+ if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
+ animType = PULLUP;
+ }
// Only animate the search bar if animating from spring loaded mode back to all apps
mCurrentAnimation = startAnimationToOverlay(fromWorkspaceState,
- Workspace.State.NORMAL_HIDDEN, buttonView, toView, animated, cb);
+ Workspace.State.NORMAL_HIDDEN, buttonView, toView, animated, animType, cb);
}
/**
@@ -167,7 +186,7 @@
final WidgetsContainerView toView = mLauncher.getWidgetsView();
final View buttonView = mLauncher.getWidgetsButton();
mCurrentAnimation = startAnimationToOverlay(fromWorkspaceState,
- Workspace.State.OVERVIEW_HIDDEN, buttonView, toView, animated,
+ Workspace.State.OVERVIEW_HIDDEN, buttonView, toView, animated, CIRCULAR_REVEAL,
new PrivateTransitionCallbacks(FINAL_REVEAL_ALPHA_FOR_WIDGETS){
@Override
void onTransitionComplete() {
@@ -189,8 +208,12 @@
}
if (fromState == Launcher.State.APPS || fromState == Launcher.State.APPS_SPRING_LOADED) {
+ int animType = CIRCULAR_REVEAL;
+ if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
+ animType = PULLUP;
+ }
startAnimationToWorkspaceFromAllApps(fromWorkspaceState, toWorkspaceState,
- animated, onCompleteRunnable);
+ animated, animType, onCompleteRunnable);
} else if (fromState == Launcher.State.WIDGETS ||
fromState == Launcher.State.WIDGETS_SPRING_LOADED) {
startAnimationToWorkspaceFromWidgets(fromWorkspaceState, toWorkspaceState,
@@ -208,7 +231,7 @@
private AnimatorSet startAnimationToOverlay(
final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState,
final View buttonView, final BaseContainerView toView,
- final boolean animated, final PrivateTransitionCallbacks pCb) {
+ final boolean animated, int animType, final PrivateTransitionCallbacks pCb) {
final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
final Resources res = mLauncher.getResources();
final boolean material = Utilities.ATLEAST_LOLLIPOP;
@@ -225,12 +248,35 @@
// Cancel the current animation
cancelAnimation();
- playCommonTransitionAnimations(toWorkspaceState, fromView, toView,
- animated, initialized, animation, revealDuration, layerViews);
-
+ if (!FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
+ playCommonTransitionAnimations(toWorkspaceState, fromView, toView,
+ animated, initialized, animation, revealDuration, layerViews);
+ }
final View contentView = toView.getContentView();
- if (animated && initialized) {
+ if (!animated || !initialized) {
+ toView.setTranslationX(0.0f);
+ toView.setTranslationY(0.0f);
+ toView.setScaleX(1.0f);
+ toView.setScaleY(1.0f);
+ toView.setAlpha(1.0f);
+ toView.setVisibility(View.VISIBLE);
+ toView.bringToFront();
+
+ // Show the content view
+ contentView.setVisibility(View.VISIBLE);
+
+ dispatchOnLauncherTransitionPrepare(fromView, animated, false);
+ dispatchOnLauncherTransitionStart(fromView, animated, false);
+ dispatchOnLauncherTransitionEnd(fromView, animated, false);
+ dispatchOnLauncherTransitionPrepare(toView, animated, false);
+ dispatchOnLauncherTransitionStart(toView, animated, false);
+ dispatchOnLauncherTransitionEnd(toView, animated, false);
+ pCb.onTransitionComplete();
+
+ return null;
+ }
+ if (animType == CIRCULAR_REVEAL) {
// Setup the reveal view animation
final View revealView = toView.getRevealView();
@@ -366,27 +412,40 @@
toView.post(startAnimRunnable);
return animation;
- } else {
- toView.setTranslationX(0.0f);
- toView.setTranslationY(0.0f);
- toView.setScaleX(1.0f);
- toView.setScaleY(1.0f);
- toView.setVisibility(View.VISIBLE);
- toView.bringToFront();
+ } else if (animType == PULLUP) {
+ animation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ dispatchOnLauncherTransitionEnd(fromView, animated, false);
+ dispatchOnLauncherTransitionEnd(toView, animated, false);
+ cleanupAnimation();
+ pCb.onTransitionComplete();
+ }
- // Show the content view
- contentView.setVisibility(View.VISIBLE);
+ });
+ mAllAppsController.animateToAllApps(animation);
dispatchOnLauncherTransitionPrepare(fromView, animated, false);
- dispatchOnLauncherTransitionStart(fromView, animated, false);
- dispatchOnLauncherTransitionEnd(fromView, animated, false);
dispatchOnLauncherTransitionPrepare(toView, animated, false);
- dispatchOnLauncherTransitionStart(toView, animated, false);
- dispatchOnLauncherTransitionEnd(toView, animated, false);
- pCb.onTransitionComplete();
- return null;
+ final AnimatorSet stateAnimation = animation;
+ final Runnable startAnimRunnable = new Runnable() {
+ public void run() {
+ // Check that mCurrentAnimation hasn't changed while
+ // we waited for a layout/draw pass
+ if (mCurrentAnimation != stateAnimation)
+ return;
+ dispatchOnLauncherTransitionStart(fromView, animated, false);
+ dispatchOnLauncherTransitionStart(toView, animated, false);
+
+ toView.requestFocus();
+ stateAnimation.start();
+ }
+ };
+ toView.post(startAnimRunnable);
+ return animation;
}
+ return null;
}
/**
@@ -401,12 +460,6 @@
Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState,
animated, layerViews);
- // Animate the search bar
- final SearchDropTargetBar.State toSearchBarState =
- toWorkspaceState.searchDropTargetBarState;
- mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState,
- animated ? revealDuration : 0, animation);
-
if (animated && initialized) {
// Play the workspace animation
if (workspaceAnim != null) {
@@ -439,7 +492,7 @@
* Starts an animation to the workspace from the apps view.
*/
private void startAnimationToWorkspaceFromAllApps(final Workspace.State fromWorkspaceState,
- final Workspace.State toWorkspaceState, final boolean animated,
+ final Workspace.State toWorkspaceState, final boolean animated, int type,
final Runnable onCompleteRunnable) {
AllAppsContainerView appsView = mLauncher.getAppsView();
// No alpha anim from all apps
@@ -476,7 +529,7 @@
// Only animate the search bar if animating to spring loaded mode from all apps
mCurrentAnimation = startAnimationToWorkspaceFromOverlay(fromWorkspaceState, toWorkspaceState,
mLauncher.getAllAppsButton(), appsView,
- animated, onCompleteRunnable, cb);
+ animated, type, onCompleteRunnable, cb);
}
/**
@@ -506,7 +559,7 @@
mCurrentAnimation = startAnimationToWorkspaceFromOverlay(
fromWorkspaceState, toWorkspaceState,
mLauncher.getWidgetsButton(), widgetsView,
- animated, onCompleteRunnable, cb);
+ animated, CIRCULAR_REVEAL, onCompleteRunnable, cb);
}
/**
@@ -598,7 +651,7 @@
private AnimatorSet startAnimationToWorkspaceFromOverlay(
final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState,
final View buttonView, final BaseContainerView fromView,
- final boolean animated, final Runnable onCompleteRunnable,
+ final boolean animated, int animType, final Runnable onCompleteRunnable,
final PrivateTransitionCallbacks pCb) {
final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
final Resources res = mLauncher.getResources();
@@ -619,10 +672,31 @@
boolean multiplePagesVisible = toWorkspaceState.hasMultipleVisiblePages;
- playCommonTransitionAnimations(toWorkspaceState, fromView, toView,
- animated, initialized, animation, revealDuration, layerViews);
+ if (!FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
+ playCommonTransitionAnimations(toWorkspaceState, fromView, toView,
+ animated, initialized, animation, revealDuration, layerViews);
+ }
+ if (!animated || !initialized) {
+ if (!FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
+ mAllAppsController.finishPullDown();
+ }
+ fromView.setVisibility(View.GONE);
+ dispatchOnLauncherTransitionPrepare(fromView, animated, multiplePagesVisible);
+ dispatchOnLauncherTransitionStart(fromView, animated, true);
+ dispatchOnLauncherTransitionEnd(fromView, animated, true);
+ dispatchOnLauncherTransitionPrepare(toView, animated, multiplePagesVisible);
+ dispatchOnLauncherTransitionStart(toView, animated, true);
+ dispatchOnLauncherTransitionEnd(toView, animated, true);
+ pCb.onTransitionComplete();
- if (animated && initialized) {
+ // Run any queued runnables
+ if (onCompleteRunnable != null) {
+ onCompleteRunnable.run();
+ }
+
+ return null;
+ }
+ if (animType == CIRCULAR_REVEAL) {
final View revealView = fromView.getRevealView();
final View contentView = fromView.getContentView();
@@ -791,23 +865,59 @@
fromView.post(startAnimRunnable);
return animation;
- } else /* if (!(animated && initialized)) */ {
- fromView.setVisibility(View.GONE);
- dispatchOnLauncherTransitionPrepare(fromView, animated, multiplePagesVisible);
- dispatchOnLauncherTransitionStart(fromView, animated, true);
- dispatchOnLauncherTransitionEnd(fromView, animated, true);
- dispatchOnLauncherTransitionPrepare(toView, animated, multiplePagesVisible);
- dispatchOnLauncherTransitionStart(toView, animated, true);
- dispatchOnLauncherTransitionEnd(toView, animated, true);
- pCb.onTransitionComplete();
+ } else if (animType == PULLUP) {
+ animation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ dispatchOnLauncherTransitionEnd(fromView, animated, false);
+ dispatchOnLauncherTransitionEnd(toView, animated, false);
+ cleanupAnimation();
+ pCb.onTransitionComplete();
+ }
- // Run any queued runnables
- if (onCompleteRunnable != null) {
- onCompleteRunnable.run();
- }
+ });
+ mAllAppsController.animateToWorkspace(animation);
- return null;
+ // Dispatch the prepare transition signal
+ dispatchOnLauncherTransitionPrepare(fromView, animated, false);
+ dispatchOnLauncherTransitionPrepare(toView, animated, false);
+
+ animation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ dispatchOnLauncherTransitionEnd(fromView, animated, true);
+ dispatchOnLauncherTransitionEnd(toView, animated, true);
+
+ // Run any queued runnables
+ if (onCompleteRunnable != null) {
+ onCompleteRunnable.run();
+ }
+
+ // This can hold unnecessary references to views.
+ cleanupAnimation();
+ pCb.onTransitionComplete();
+ }
+ });
+
+ final AnimatorSet stateAnimation = animation;
+ final Runnable startAnimRunnable = new Runnable() {
+ public void run() {
+ // Check that mCurrentAnimation hasn't changed while
+ // we waited for a layout/draw pass
+ if (mCurrentAnimation != stateAnimation)
+ return;
+ dispatchOnLauncherTransitionStart(fromView, animated, false);
+ dispatchOnLauncherTransitionStart(toView, animated, false);
+
+ // Focus the new view
+ toView.requestFocus();
+ stateAnimation.start();
+ }
+ };
+ fromView.post(startAnimRunnable);
+ return animation;
}
+ return null;
}
/**
diff --git a/src/com/android/launcher3/PinchToOverviewListener.java b/src/com/android/launcher3/PinchToOverviewListener.java
index 0c8568e..6ee96fc 100644
--- a/src/com/android/launcher3/PinchToOverviewListener.java
+++ b/src/com/android/launcher3/PinchToOverviewListener.java
@@ -21,6 +21,8 @@
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
+import com.android.launcher3.util.TouchController;
+
/**
* Detects pinches and animates the Workspace to/from overview mode.
*
@@ -30,7 +32,8 @@
* @see PinchThresholdManager
* @see PinchAnimationManager
*/
-public class PinchToOverviewListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+public class PinchToOverviewListener extends ScaleGestureDetector.SimpleOnScaleGestureListener
+ implements TouchController {
private static final float OVERVIEW_PROGRESS = 0f;
private static final float WORKSPACE_PROGRESS = 1f;
/**
@@ -63,15 +66,16 @@
return mPinchStarted;
}
- public void onTouchEvent(MotionEvent ev) {
+ public boolean onTouchEvent(MotionEvent ev) {
if (mPinchStarted) {
if (ev.getPointerCount() > 2) {
// Using more than two fingers causes weird behavior, so just cancel the pinch.
cancelPinch(mPreviousProgress, -1);
} else {
- mPinchDetector.onTouchEvent(ev);
+ return mPinchDetector.onTouchEvent(ev);
}
}
+ return false;
}
@Override
diff --git a/src/com/android/launcher3/QsbContainerView.java b/src/com/android/launcher3/QsbContainerView.java
index 0a112d2..f931aba 100644
--- a/src/com/android/launcher3/QsbContainerView.java
+++ b/src/com/android/launcher3/QsbContainerView.java
@@ -18,7 +18,6 @@
import android.app.Activity;
import android.app.Fragment;
-import android.app.FragmentManager;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
@@ -44,8 +43,6 @@
*/
public class QsbContainerView extends FrameLayout {
- private boolean mBound;
-
public QsbContainerView(Context context) {
super(context);
}
@@ -59,17 +56,6 @@
}
@Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- if (!mBound) {
- FragmentManager fm = ((Launcher) getContext()).getFragmentManager();
- fm.beginTransaction().add(R.id.qsb_container, new QsbFragment()).commit();
- mBound = true;
- }
- }
-
- @Override
public void setPadding(int left, int top, int right, int bottom) {
super.setPadding(0, 0, 0, 0);
}
@@ -103,6 +89,8 @@
getContext().registerReceiver(mRebindReceiver, filter);
}
+ private FrameLayout mWrapper;
+
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -110,7 +98,12 @@
if (savedInstanceState != null) {
sSavedWidgetId = savedInstanceState.getInt(QSB_WIDGET_ID, -1);
}
+ mWrapper = new FrameLayout(getContext());
+ mWrapper.addView(createQsb(inflater, mWrapper));
+ return mWrapper;
+ }
+ private View createQsb(LayoutInflater inflater, ViewGroup container) {
Launcher launcher = (Launcher) getActivity();
mWidgetInfo = getSearchWidgetProvider(launcher);
if (mWidgetInfo == null) {
@@ -222,10 +215,9 @@
}
private void rebindFragment() {
- if (getActivity() != null) {
- // Recreate the fragment. This will cause the qsb to be inflated again.
- getActivity().getFragmentManager().beginTransaction()
- .replace(R.id.qsb_container, new QsbFragment()).commit();
+ if (mWrapper != null && getActivity() != null) {
+ mWrapper.removeAllViews();
+ mWrapper.addView(createQsb(getActivity().getLayoutInflater(), mWrapper));
}
}
diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java
deleted file mode 100644
index e43e96c..0000000
--- a/src/com/android/launcher3/SearchDropTargetBar.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.TimeInterpolator;
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.animation.DecelerateInterpolator;
-
-import com.android.launcher3.dragndrop.DragController;
-import com.android.launcher3.util.Thunk;
-
-/*
- * This bar will manage the transition between the QSB search bar and the delete/uninstall drop
- * targets so that each of the individual ButtonDropTargets don't have to.
- */
-public class SearchDropTargetBar extends BaseDropTargetBar {
-
- /** The different states that the search bar space can be in. */
- public enum State {
- INVISIBLE (0f),
- DROP_TARGET (1f);
-
- private final float mDropTargetBarAlpha;
-
- State(float dtbAlpha) {
- mDropTargetBarAlpha = dtbAlpha;
- }
- }
-
-
- @ViewDebug.ExportedProperty(category = "launcher")
- private State mState = State.INVISIBLE;
-
- // Drop targets
- private ButtonDropTarget mDeleteDropTarget;
- private ButtonDropTarget mUninstallDropTarget;
-
- public SearchDropTargetBar(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public SearchDropTargetBar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- // Get the individual components
- mDeleteDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.delete_target_text);
- mUninstallDropTarget = (ButtonDropTarget) mDropTargetBar
- .findViewById(R.id.uninstall_target_text);
-
- mDeleteDropTarget.setDropTargetBar(this);
- mUninstallDropTarget.setDropTargetBar(this);
- }
-
- @Override
- public void setup(Launcher launcher, DragController dragController) {
- dragController.addDragListener(this);
- dragController.setFlingToDeleteDropTarget(mDeleteDropTarget);
-
- dragController.addDragListener(mDeleteDropTarget);
- dragController.addDragListener(mUninstallDropTarget);
-
- dragController.addDropTarget(mDeleteDropTarget);
- dragController.addDropTarget(mUninstallDropTarget);
-
- mDeleteDropTarget.setLauncher(launcher);
- mUninstallDropTarget.setLauncher(launcher);
- }
-
- @Override
- public void showDropTargets() {
- animateToState(State.DROP_TARGET, DEFAULT_DRAG_FADE_DURATION);
- }
-
- @Override
- public void hideDropTargets() {
- animateToState(State.INVISIBLE, DEFAULT_DRAG_FADE_DURATION);
- }
-
- /**
- * Animates the current search bar state to a new state. If the {@param duration} is 0, then
- * the state is applied immediately.
- */
- public void animateToState(State newState, int duration) {
- animateToState(newState, duration, null);
- }
-
- public void animateToState(State newState, int duration, AnimatorSet animation) {
- if (mState != newState) {
- mState = newState;
-
- resetAnimation(duration);
- if (duration > 0) {
- animateAlpha(mDropTargetBar, mState.mDropTargetBarAlpha, DEFAULT_INTERPOLATOR);
- } else {
- mDropTargetBar.setAlpha(mState.mDropTargetBarAlpha);
- AlphaUpdateListener.updateVisibility(mDropTargetBar, mAccessibilityEnabled);
- }
-
- // Start the final animation
- if (duration > 0) {
- if (animation != null) {
- animation.play(mCurrentAnimation);
- } else {
- mCurrentAnimation.start();
- }
- }
- }
- }
-
- @Override
- public void enableAccessibleDrag(boolean enable) {
- mDeleteDropTarget.enableAccessibleDrag(enable);
- mUninstallDropTarget.enableAccessibleDrag(enable);
- }
-}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index faaca72..bf8e314 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -176,26 +176,22 @@
private Matrix mTempMatrix = new Matrix();
private SpringLoadedDragController mSpringLoadedDragController;
- private float mSpringLoadedShrinkFactor;
private float mOverviewModeShrinkFactor;
// State variable that indicates whether the pages are small (ie when you're
// in all apps or customize mode)
enum State {
- NORMAL (SearchDropTargetBar.State.INVISIBLE, false, false),
- NORMAL_HIDDEN (SearchDropTargetBar.State.INVISIBLE, false, false),
- SPRING_LOADED (SearchDropTargetBar.State.DROP_TARGET, false, true),
- OVERVIEW (SearchDropTargetBar.State.INVISIBLE, true, true),
- OVERVIEW_HIDDEN (SearchDropTargetBar.State.INVISIBLE, true, false);
+ NORMAL (false, false),
+ NORMAL_HIDDEN (false, false),
+ SPRING_LOADED (false, true),
+ OVERVIEW (true, true),
+ OVERVIEW_HIDDEN (true, false);
- public final SearchDropTargetBar.State searchDropTargetBarState;
public final boolean shouldUpdateWidget;
public final boolean hasMultipleVisiblePages;
- State(SearchDropTargetBar.State searchBarState, boolean shouldUpdateWidget,
- boolean hasMultipleVisiblePages) {
- searchDropTargetBarState = searchBarState;
+ State(boolean shouldUpdateWidget, boolean hasMultipleVisiblePages) {
this.shouldUpdateWidget = shouldUpdateWidget;
this.hasMultipleVisiblePages = hasMultipleVisiblePages;
}
@@ -316,9 +312,6 @@
mWallpaperManager = WallpaperManager.getInstance(context);
mWallpaperOffset = new WallpaperOffsetInterpolator(this);
-
- mSpringLoadedShrinkFactor =
- res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
mOverviewModeShrinkFactor =
res.getInteger(R.integer.config_workspaceOverviewShrinkPercentage) / 100f;
@@ -347,6 +340,7 @@
// estimate the size of a widget with spans hSpan, vSpan. return MAX_VALUE for each
// dimension if unsuccessful
public int[] estimateItemSize(ItemInfo itemInfo, boolean springLoaded) {
+ float shrinkFactor = mLauncher.getDeviceProfile().workspaceSpringLoadShrinkFactor;
int[] size = new int[2];
if (getChildCount() > 0) {
// Use the first non-custom page to estimate the child position
@@ -355,8 +349,8 @@
size[0] = r.width();
size[1] = r.height();
if (springLoaded) {
- size[0] *= mSpringLoadedShrinkFactor;
- size[1] *= mSpringLoadedShrinkFactor;
+ size[0] *= shrinkFactor;
+ size[1] *= shrinkFactor;
}
return size;
} else {
@@ -1386,7 +1380,6 @@
// TODO(adamcohen): figure out a final effect here. We may need to recommend
// different effects based on device performance. On at least one relatively high-end
// device I've tried, translating the launcher causes things to get quite laggy.
- setTranslationAndAlpha(mLauncher.getSearchDropTargetBar(), transX, alpha);
setTranslationAndAlpha(getPageIndicator(), transX, alpha);
setTranslationAndAlpha(getChildAt(getCurrentPage()), transX, alpha);
setTranslationAndAlpha(mLauncher.getHotseat(), transX, alpha);
@@ -1542,8 +1535,7 @@
// Reset our click listener
setOnClickListener(mLauncher);
}
- mLauncher.getSearchDropTargetBar().enableAccessibleDrag(enable);
- mLauncher.getAppInfoDropTargetBar().enableAccessibleDrag(enable);
+ mLauncher.getDropTargetBar().enableAccessibleDrag(enable);
mLauncher.getHotseat().getLayout()
.enableAccessibleDrag(enable, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
}
@@ -1944,7 +1936,7 @@
int getOverviewModeTranslationY() {
DeviceProfile grid = mLauncher.getDeviceProfile();
- Rect workspacePadding = grid.getWorkspacePadding(Utilities.isRtl(getResources()));
+ Rect workspacePadding = grid.getWorkspacePadding();
int overviewButtonBarHeight = grid.getOverviewModeButtonBarHeight();
int scaledHeight = (int) (mOverviewModeShrinkFactor * getNormalChildHeight());
@@ -1957,15 +1949,26 @@
return -workspaceOffsetTopEdge + overviewOffsetTopEdge;
}
- int getSpringLoadedTranslationY() {
+ float getSpringLoadedTranslationY() {
DeviceProfile grid = mLauncher.getDeviceProfile();
- Rect workspacePadding = grid.getWorkspacePadding(Utilities.isRtl(getResources()));
- int scaledHeight = (int) (mSpringLoadedShrinkFactor * getNormalChildHeight());
- int workspaceTop = mInsets.top + workspacePadding.top;
- int workspaceBottom = getViewportHeight() - mInsets.bottom - workspacePadding.bottom;
- int workspaceHeight = workspaceBottom - workspaceTop;
- // Center the spring-loaded pages by translating it up by half of the reduced height.
- return -(workspaceHeight - scaledHeight) / 2;
+ if (grid.isVerticalBarLayout() || getChildCount() == 0) {
+ return 0;
+ }
+ Rect workspacePadding = grid.getWorkspacePadding();
+
+ float scaledHeight = grid.workspaceSpringLoadShrinkFactor * getNormalChildHeight();
+ float shrunkTop = mInsets.top + grid.dropTargetBarSizePx;
+ float shrunkBottom = getViewportHeight() - mInsets.bottom
+ - workspacePadding.bottom - grid.workspaceSpringLoadedBottomSpace;
+ float totalShrunkSpace = shrunkBottom - shrunkTop;
+
+ float desiredCellTop = shrunkTop + (totalShrunkSpace - scaledHeight) / 2;
+
+ float halfHeight = getHeight() / 2;
+ float myCenter = getTop() + halfHeight;
+ float cellTopFromCenter = halfHeight - getChildAt(0).getTop();
+ float actualCellTop = myCenter - cellTopFromCenter * grid.workspaceSpringLoadShrinkFactor;
+ return (desiredCellTop - actualCellTop) / grid.workspaceSpringLoadShrinkFactor;
}
float getOverviewModeShrinkFactor() {
@@ -2056,7 +2059,12 @@
@Override
public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
if (mPageIndicator instanceof PageIndicatorLine) {
- ((PageIndicatorLine) mPageIndicator).setShouldAutoHide(mState != State.SPRING_LOADED);
+ boolean isNewStateSpringLoaded = mState == State.SPRING_LOADED;
+ ((PageIndicatorLine) mPageIndicator).setShouldAutoHide(!isNewStateSpringLoaded);
+ if (isNewStateSpringLoaded) {
+ // Show the page indicator at the same time as the rest of the transition.
+ showPageIndicatorAtCurrentScroll();
+ }
}
}
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index e268640..0f437c1 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -211,8 +211,7 @@
mOverviewTransitionTime = res.getInteger(R.integer.config_overviewTransitionTime);
mOverlayTransitionTime = res.getInteger(R.integer.config_overlayTransitionTime);
mSpringLoadedTransitionTime = mOverlayTransitionTime / 2;
- mSpringLoadedShrinkFactor =
- res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100f;
+ mSpringLoadedShrinkFactor = mLauncher.getDeviceProfile().workspaceSpringLoadShrinkFactor;
mOverviewModeShrinkFactor =
res.getInteger(R.integer.config_workspaceOverviewShrinkPercentage) / 100f;
mWorkspaceScrimAlpha = res.getInteger(R.integer.config_workspaceScrimAlpha) / 100f;
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index c9bd02c..95ab286 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -20,16 +20,20 @@
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
+import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.method.TextKeyListener;
import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
+import android.widget.LinearLayout;
import com.android.launcher3.AppInfo;
import com.android.launcher3.BaseContainerView;
@@ -40,6 +44,7 @@
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
import com.android.launcher3.ExtendedEditText;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
@@ -178,9 +183,13 @@
mApps.setAdapter(mAdapter);
mLayoutManager = mAdapter.getLayoutManager();
mItemDecoration = mAdapter.getItemDecoration();
- mRecyclerViewTopBottomPadding =
- res.getDimensionPixelSize(R.dimen.all_apps_list_top_bottom_padding);
-
+ if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
+ mRecyclerViewTopBottomPadding = 0;
+ setPadding(0, 0, 0, 0);
+ } else {
+ mRecyclerViewTopBottomPadding =
+ res.getDimensionPixelSize(R.dimen.all_apps_list_top_bottom_padding);
+ }
mSearchQueryBuilder = new SpannableStringBuilder();
Selection.setSelection(mSearchQueryBuilder, 0);
}
@@ -220,6 +229,13 @@
mApps.removeApps(apps);
}
+ public void setSearchBarVisible(boolean visible) {
+ if (visible) {
+ mSearchBarController.setVisibility(View.VISIBLE);
+ } else {
+ mSearchBarController.setVisibility(View.INVISIBLE);
+ }
+ }
/**
* Sets the search bar that shows above the a-z list.
*/
@@ -239,6 +255,10 @@
mAppsRecyclerView.scrollToTop();
}
+ public boolean isScrollAtTop() {
+ return ((LinearLayoutManager) mAppsRecyclerView.getLayoutManager())
+ .findFirstVisibleItemPosition() == 1;
+ }
/**
* Focuses the search field and begins an app search.
*/
@@ -321,13 +341,33 @@
MeasureSpec.getSize(widthMeasureSpec) - mHorizontalPadding,
MeasureSpec.getSize(heightMeasureSpec));
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ int availableWidth = (!mContentBounds.isEmpty() ? mContentBounds.width() :
+ MeasureSpec.getSize(widthMeasureSpec))
+ - 2 * mAppsRecyclerView.getMaxScrollbarWidth();
+ if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
+ if (mNumAppsPerRow != grid.inv.numColumns ||
+ mNumPredictedAppsPerRow != grid.inv.numColumns) {
+ mNumAppsPerRow = grid.inv.numColumns;
+ mNumPredictedAppsPerRow = grid.inv.numColumns;
+
+ mAppsRecyclerView.setNumAppsPerRow(grid, mNumAppsPerRow);
+ mAdapter.setNumAppsPerRow(mNumAppsPerRow);
+ mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow, new FullMergeAlgorithm());
+ if (mNumAppsPerRow > 0) {
+ int iconSize = availableWidth / mNumAppsPerRow;
+ int iconSpacing = (iconSize - grid.allAppsIconSizePx) / 2;
+ }
+ }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ return;
+ }
+
+ // --- remove START when {@code FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP} is enabled. ---
+
// Update the number of items in the grid before we measure the view
// TODO: mSectionNamesMargin is currently 0, but also account for it,
// if it's enabled in the future.
- int availableWidth = (!mContentBounds.isEmpty() ? mContentBounds.width() :
- MeasureSpec.getSize(widthMeasureSpec))
- - 2 * mAppsRecyclerView.getMaxScrollbarWidth();
- DeviceProfile grid = mLauncher.getDeviceProfile();
grid.updateAppsViewNumCols(getResources(), availableWidth);
if (mNumAppsPerRow != grid.allAppsNumCols ||
mNumPredictedAppsPerRow != grid.allAppsNumPredictiveCols) {
@@ -346,6 +386,8 @@
mAdapter.setNumAppsPerRow(mNumAppsPerRow);
mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow, mergeAlgorithm);
+ // TODO: should we not do all this complicated computation but just match the
+ // numAppsPerRow with the workspace?
if (mNumAppsPerRow > 0) {
int iconSize = availableWidth / mNumAppsPerRow;
int iconSpacing = (iconSize - grid.allAppsIconSizePx) / 2;
@@ -353,6 +395,7 @@
}
}
+ // --- remove END when {@code FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP} is enabled. ---
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@@ -385,6 +428,24 @@
MarginLayoutParams lp = (MarginLayoutParams) mSearchContainer.getLayoutParams();
lp.leftMargin = bgPadding.left;
lp.rightMargin = bgPadding.right;
+
+ if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
+ MarginLayoutParams mlp = (MarginLayoutParams) mAppsRecyclerView.getLayoutParams();
+
+ int navBarHeight = 84; /* replace with mInset.height() in dragLayer */
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ int height = navBarHeight + grid.hotseatCellHeightPx;
+
+ mlp.topMargin = height;
+ mAppsRecyclerView.setLayoutParams(mlp);
+
+ LinearLayout.LayoutParams llp =
+ (LinearLayout.LayoutParams) mSearchInput.getLayoutParams();
+ llp.topMargin = navBarHeight;
+ mSearchInput.setLayoutParams(llp);
+
+ lp.height = height;
+ }
mSearchContainer.setLayoutParams(lp);
}
@@ -437,6 +498,7 @@
// Return early if this is not initiated from a touch
if (!v.isInTouchMode()) return false;
// When we have exited all apps or are in transition, disregard long clicks
+
if (!mLauncher.isAppsViewVisible() ||
mLauncher.getWorkspace().isSwitchingState()) return false;
// Return if global dragging is not enabled
diff --git a/src/com/android/launcher3/allapps/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/AllAppsSearchBarController.java
index a4bea8d..ac35932 100644
--- a/src/com/android/launcher3/allapps/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/AllAppsSearchBarController.java
@@ -49,6 +49,9 @@
protected DefaultAppSearchAlgorithm mSearchAlgorithm;
protected InputMethodManager mInputMethodManager;
+ public void setVisibility(int visibility) {
+ mInput.setVisibility(visibility);
+ }
/**
* Sets the references to the apps model and the search result callback.
*/
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
new file mode 100644
index 0000000..1428c2f
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -0,0 +1,347 @@
+package com.android.launcher3.allapps;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+
+import com.android.launcher3.Hotseat;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAnimUtils;
+import com.android.launcher3.util.TouchController;
+
+/**
+ * Handles AllApps view transition.
+ * 1) Slides all apps view using direct manipulation
+ * 2) When finger is released, animate to either top or bottom accordingly.
+ *
+ * Algorithm:
+ * If release velocity > THRES1, snap according to the direction of movement.
+ * If release velocity < THRES1, snap according to either top or bottom depending on whether it's
+ * closer to top or closer to the page indicator.
+ */
+public class AllAppsTransitionController implements TouchController, VerticalPullDetector.Listener {
+
+ private static final String TAG = "AllAppsTrans";
+ private static final boolean DBG = false;
+
+ private static final float ANIMATION_DURATION = 500;
+
+ private AllAppsContainerView mAppsView;
+ private Hotseat mHotseat;
+ private Drawable mHotseatBackground;
+ private float mHotseatAlpha;
+ private View mWorkspaceCurPage;
+
+ private final Launcher mLauncher;
+ private final VerticalPullDetector mDetector;
+
+ // Animation in this class is controlled by a single variable {@link mProgressTransY}.
+ // Visually, it represents top y coordinate of the all apps container. Using the
+ // {@link mTranslation} as the denominator, this fraction value ranges in [0, 1].
+ private float mProgressTransY; // numerator
+ private float mTranslation = -1; // denominator
+
+ private float mAnimationDuration;
+ private float mCurY;
+
+ private AnimatorSet mCurrentAnimation;
+
+ public AllAppsTransitionController(Launcher launcher) {
+ mLauncher = launcher;
+ mDetector = new VerticalPullDetector(launcher);
+ mDetector.setListener(this);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ init();
+ if (mLauncher.getWorkspace().isInOverviewMode() ||
+ mLauncher.isWidgetsViewVisible()) {
+ return false;
+ }
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mDetector.setAllAppsState(mLauncher.isAllAppsVisible(), mAppsView.isScrollAtTop());
+ }
+ mDetector.onTouchEvent(ev);
+ return mDetector.mScrolling;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ return mDetector.onTouchEvent(ev);
+ }
+
+ private void init() {
+ if (mAppsView != null) {
+ return;
+ }
+ mAppsView = mLauncher.getAppsView();
+ mHotseat = mLauncher.getHotseat();
+ mWorkspaceCurPage = mLauncher.getWorkspace().getChildAt(
+ mLauncher.getWorkspace().getCurrentPage());
+
+ if (mHotseatBackground == null) {
+ mHotseatBackground = mHotseat.getBackground();
+ mHotseatAlpha = mHotseatBackground.getAlpha() / 255f;
+ }
+ }
+
+ @Override
+ public void onScrollStart(boolean start) {
+ cancelAnimation();
+ mCurrentAnimation = LauncherAnimUtils.createAnimatorSet();
+ mCurY = mAppsView.getTranslationY();
+ preparePull(start);
+
+ }
+
+ /**
+ * @param start {@code true} if start of new drag.
+ */
+ public void preparePull(boolean start) {
+ if (start) {
+ if (!mLauncher.isAllAppsVisible()) {
+ mHotseat.setBackground(null);
+ mAppsView.setVisibility(View.VISIBLE);
+ mAppsView.getContentView().setVisibility(View.VISIBLE);
+ mAppsView.setAlpha(mHotseatAlpha);
+ mAppsView.setSearchBarVisible(false);
+
+ if (mTranslation < 0) {
+ mTranslation = mHotseat.getTop();
+ setProgress(mTranslation);
+ }
+ } else {
+ mLauncher.getWorkspace().setVisibility(View.VISIBLE);
+ mLauncher.getWorkspace().setAlpha(1f);
+ mLauncher.getWorkspace().onLauncherTransitionPrepare(mLauncher, false, false);
+ mWorkspaceCurPage.setVisibility(View.VISIBLE);
+ mAppsView.setSearchBarVisible(false);
+ setLightStatusBar(false);
+ }
+ }
+ mHotseat.setVisibility(View.VISIBLE);
+ mHotseat.bringToFront();
+ }
+
+ private void setLightStatusBar(boolean enable) {
+ int systemUiFlags = mLauncher.getWindow().getDecorView().getSystemUiVisibility();
+ if (enable) {
+ mLauncher.getWindow().getDecorView().setSystemUiVisibility(systemUiFlags
+ | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+
+ } else {
+ mLauncher.getWindow().getDecorView().setSystemUiVisibility(systemUiFlags
+ & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+
+ }
+ }
+
+ private final Interpolator mAlphaInterpolator = new DecelerateInterpolator(.5f);
+
+ @Override
+ public boolean onScroll(float displacement, float velocity) {
+ if (mAppsView == null) {
+ return false; // early termination.
+ }
+ if (0 <= mCurY + displacement && mCurY + displacement < mTranslation) {
+ setProgress(mCurY + displacement);
+ }
+ return true;
+ }
+
+ /**
+ * @param progress y value of the border between hotseat and all apps
+ */
+ public void setProgress(float progress) {
+ mProgressTransY = progress;
+ float alpha = calcAlphaAllApps(progress);
+ float workspaceHotseatAlpha = Math.max(mHotseatAlpha, 1 - alpha);
+ setTransAndAlpha(mAppsView, progress, Math.max(mHotseatAlpha, alpha));
+ setTransAndAlpha(mWorkspaceCurPage, -mTranslation + progress, workspaceHotseatAlpha);
+ setTransAndAlpha(mHotseat, -mTranslation + progress, workspaceHotseatAlpha);
+ }
+
+ public float getProgress() {
+ return mProgressTransY;
+ }
+
+ private float calcAlphaAllApps(float progress) {
+ return mAlphaInterpolator.getInterpolation((mTranslation - progress)/mTranslation);
+ }
+
+ private void setTransAndAlpha(View v, float transY, float alpha) {
+ if (v != null) {
+ v.setTranslationY(transY);
+ v.setAlpha(alpha);
+ }
+ }
+
+ @Override
+ public void onScrollEnd(float velocity, boolean fling) {
+ if (mAppsView == null) {
+ return; // early termination.
+ }
+
+ if (fling) {
+ if (velocity < 0) {
+ calculateDuration(velocity, mAppsView.getTranslationY());
+ showAppsView(); // Flinging in UP direction
+ } else {
+ calculateDuration(velocity, Math.abs(mTranslation - mAppsView.getTranslationY()));
+ showWorkspace(); // Flinging in DOWN direction
+ }
+ // snap to top or bottom using the release velocity
+ } else {
+ if (mAppsView.getTranslationY() > mTranslation / 2) {
+ calculateDuration(velocity, Math.abs(mTranslation - mAppsView.getTranslationY()));
+ showWorkspace(); // Released in the bottom half
+ } else {
+ calculateDuration(velocity, Math.abs(mAppsView.getTranslationY()));
+ showAppsView(); // Released in the top half
+ }
+ }
+ }
+
+ private void calculateDuration(float velocity, float disp) {
+ // TODO: make these values constants after tuning.
+ float velocityDivisor = Math.max(1, 0.75f * velocity);
+ float travelDistance = Math.max(0.2f, disp / mTranslation);
+ mAnimationDuration = Math.max(100, ANIMATION_DURATION / velocityDivisor * travelDistance);
+ if (true) { // MERONG
+ Log.d(TAG, String.format("calculateDuration=%f, v=%f, d=%f", mAnimationDuration, velocity, disp));
+ }
+ }
+
+ /**
+ * Depending on the current state of the launcher, either just
+ * 1) animate
+ * 2) animate and do all the state updates.
+ */
+ private void showAppsView() {
+ if (mLauncher.isAllAppsVisible()) {
+ animateToAllApps(mCurrentAnimation);
+ mCurrentAnimation.start();
+ } else {
+ mLauncher.showAppsView(true /* animated */, true /* resetListToTop */,
+ true /* updatePredictedApps */, false /* focusSearchBar */);
+ }
+ }
+
+ /**
+ * Depending on the current state of the launcher, either just
+ * 1) animate
+ * 2) animate and do all the state updates.
+ */
+ private void showWorkspace() {
+ if (mLauncher.isAllAppsVisible()) {
+ mLauncher.showWorkspace(true /* animated */);
+ } else {
+ animateToWorkspace(mCurrentAnimation);
+ mCurrentAnimation.start();
+ }
+ }
+
+ public void animateToAllApps(AnimatorSet animationOut) {
+ if ((mAppsView = mLauncher.getAppsView()) == null || animationOut == null){
+ return;
+ }
+ if (!mDetector.mScrolling) {
+ preparePull(true);
+ }
+ mCurY = mAppsView.getTranslationY();
+ final float fromAllAppsTop = mAppsView.getTranslationY();
+ final float toAllAppsTop = 0;
+
+ ObjectAnimator driftAndAlpha = ObjectAnimator.ofFloat(this, "progress",
+ fromAllAppsTop, toAllAppsTop);
+ driftAndAlpha.setDuration((long) mAnimationDuration);
+ animationOut.play(driftAndAlpha);
+
+ animationOut.addListener(new AnimatorListenerAdapter() {
+ boolean canceled = false;
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ canceled = true;
+ }
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (canceled) {
+ return;
+ } else {
+ finishPullUp();
+ cleanUpAnimation();
+ mDetector.finishedScrolling();
+ }
+ }});
+ mCurrentAnimation = animationOut;
+ }
+
+ private void finishPullUp() {
+ mAppsView.setSearchBarVisible(true);
+ mHotseat.setVisibility(View.INVISIBLE);
+ setProgress(0f);
+ setLightStatusBar(true);
+ }
+
+ public void animateToWorkspace(AnimatorSet animationOut) {
+ if ((mAppsView = mLauncher.getAppsView()) == null || animationOut == null){
+ return;
+ }
+ if(!mDetector.mScrolling) {
+ preparePull(true);
+ }
+ final float fromAllAppsTop = mAppsView.getTranslationY();
+ final float toAllAppsTop = mTranslation;
+
+ ObjectAnimator driftAndAlpha = ObjectAnimator.ofFloat(this, "progress",
+ fromAllAppsTop, toAllAppsTop);
+ driftAndAlpha.setDuration((long) mAnimationDuration);
+ animationOut.play(driftAndAlpha);
+
+ animationOut.addListener(new AnimatorListenerAdapter() {
+ boolean canceled = false;
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ canceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (canceled) {
+ return;
+ } else {
+ finishPullDown();
+ cleanUpAnimation();
+ mDetector.finishedScrolling();
+ }
+ }});
+ mCurrentAnimation = animationOut;
+ }
+
+ public void finishPullDown() {
+ mAppsView.setVisibility(View.INVISIBLE);
+ mHotseat.setBackground(mHotseatBackground);
+ mHotseat.setVisibility(View.VISIBLE);
+ setProgress(mTranslation);
+ setLightStatusBar(false);
+ }
+
+ private void cancelAnimation() {
+ if (mCurrentAnimation != null) {
+ mCurrentAnimation.cancel();
+ mCurrentAnimation = null;
+ }
+ }
+
+ private void cleanUpAnimation() {
+ mCurrentAnimation = null;
+ }
+}
diff --git a/src/com/android/launcher3/allapps/VerticalPullDetector.java b/src/com/android/launcher3/allapps/VerticalPullDetector.java
new file mode 100644
index 0000000..4cc921c
--- /dev/null
+++ b/src/com/android/launcher3/allapps/VerticalPullDetector.java
@@ -0,0 +1,196 @@
+package com.android.launcher3.allapps;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+/**
+ * One dimensional scroll gesture detector for all apps container pull up interaction.
+ */
+public class VerticalPullDetector {
+
+ private static final String TAG = "ScrollGesture";
+ private static final boolean DBG = false;
+
+ private float mTouchSlop;
+
+ private boolean mAllAppsVisible;
+ private boolean mAllAppsScrollAtTop;
+
+ /**
+ * The minimum release velocity in pixels per millisecond that triggers fling..
+ */
+ private static final float RELEASE_VELOCITY_PX_MS = 1.7f;
+
+ /**
+ * The time constant used to calculate dampening in the low-pass filter of scroll velocity.
+ * Cutoff frequency is set at 10 Hz.
+ */
+ public static final float SCROLL_VELOCITY_DAMPENING_RC = 1000f / (2f * (float) Math.PI * 10);
+
+ /* Scroll state, this is set to true during dragging and animation. */
+ boolean mScrolling;
+
+
+ float mDownY;
+ float mDownMillis;
+
+ float mLastY;
+ float mLastMillis;
+
+ float mVelocity;
+ float mLastDisplacement;
+ float mDisplacement;
+
+ /* scroll started during previous animation */
+ boolean mSubtractSlop = true;
+
+ /* Client of this gesture detector can register a callback. */
+ Listener mListener;
+
+ public void setListener(Listener l) {
+ mListener = l;
+ }
+
+ interface Listener{
+ /**
+ * @param start when should
+ */
+ void onScrollStart(boolean start);
+ boolean onScroll(float displacement, float velocity);
+ void onScrollEnd(float velocity, boolean fling);
+ }
+
+ public VerticalPullDetector(Context context) {
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ }
+
+ public void setAllAppsState(boolean allAppsVisible, boolean scrollAtTop) {
+ mAllAppsVisible = allAppsVisible;
+ mAllAppsScrollAtTop = scrollAtTop;
+ }
+
+ private boolean shouldScrollStart() {
+ if (mAllAppsVisible && mDisplacement > mTouchSlop && mAllAppsScrollAtTop) {
+ return true;
+ }
+ if (!mAllAppsVisible && mDisplacement < -mTouchSlop) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean onTouchEvent(MotionEvent ev) {
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mDownMillis = ev.getDownTime();
+ mDownY = ev.getY();
+ mLastDisplacement = 0;
+ mVelocity = 0;
+
+ if (mScrolling) {
+ reportScrollStart(true /* recatch */);
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ mDisplacement = computeDisplacement(ev);
+ mVelocity = computeVelocity(ev, mVelocity);
+
+ if (!mScrolling && shouldScrollStart()) {
+ mScrolling = true;
+ reportScrollStart(false /* recatch */);
+ }
+ if (mScrolling && mListener != null) {
+ reportScroll();
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ // These are synthetic events and there is no need to update internal values.
+ if (mScrolling && mListener != null) {
+ reportScrollEnd();
+ }
+ break;
+ default:
+ //TODO: add multi finger tracking by tracking active pointer.
+ break;
+ }
+ // Do house keeping.
+ mLastDisplacement = mDisplacement;
+
+ mLastY = ev.getY();
+ mLastMillis = ev.getEventTime();
+
+ return true;
+ }
+
+ public void finishedScrolling() {
+ mScrolling = false;
+ }
+
+ private boolean reportScrollStart(boolean recatch) {
+ mListener.onScrollStart(!recatch);
+ if (DBG) {
+ Log.d(TAG, "onScrollStart recatch:" + recatch);
+ }
+ return true;
+ }
+
+ private boolean reportScroll() {
+ float delta = mDisplacement - mLastDisplacement;
+ if (delta != 0) {
+ if (DBG) {
+ Log.d(TAG, String.format("onScroll disp=%.1f, velocity=%.1f",
+ mDisplacement, mVelocity));
+ }
+ return mListener.onScroll(mDisplacement - (mSubtractSlop? mTouchSlop : 0), mVelocity);
+ }
+ return true;
+ }
+
+ private void reportScrollEnd() {
+ if (DBG) {
+ Log.d(TAG, String.format("onScrolEnd disp=%.1f, velocity=%.1f",
+ mDisplacement, mVelocity));
+ }
+ mListener.onScrollEnd(mVelocity, Math.abs(mVelocity) > RELEASE_VELOCITY_PX_MS);
+ }
+ /**
+ * Computes the damped velocity using the two motion events and the previous velocity.
+ */
+ private float computeVelocity(MotionEvent to, float previousVelocity) {
+ float delta = computeDelta(to);
+
+ float deltaTimeMillis = to.getEventTime() - mLastMillis;
+ float velocity = (deltaTimeMillis > 0) ? (delta / deltaTimeMillis) : 0;
+ if (Math.abs(previousVelocity) < 0.001f) {
+ return velocity;
+ }
+
+ float alpha = computeDampeningFactor(deltaTimeMillis);
+ return interpolate(previousVelocity, velocity, alpha);
+ }
+
+ private float computeDisplacement(MotionEvent to) {
+ return to.getY() - mDownY;
+ }
+
+ private float computeDelta(MotionEvent to) {
+ return to.getY() - mLastY;
+ }
+
+ /**
+ * Returns a time-dependent dampening factor using delta time.
+ */
+ private static float computeDampeningFactor(float deltaTime) {
+ return deltaTime / (SCROLL_VELOCITY_DAMPENING_RC + deltaTime);
+ }
+
+ /**
+ * Returns the linear interpolation between two values
+ */
+ private static float interpolate(float from, float to, float alpha) {
+ return (1.0f - alpha) * from + alpha * to;
+ }
+}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index f4470f3..af5ff58 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -46,6 +46,7 @@
import com.android.launcher3.Workspace;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.TouchController;
import java.util.ArrayList;
import java.util.HashSet;
@@ -53,7 +54,7 @@
/**
* Class for initiating a drag within a view or across multiple views.
*/
-public class DragController implements DragDriver.EventListener {
+public class DragController implements DragDriver.EventListener, TouchController {
private static final String TAG = "Launcher.DragController";
/** Indicates the drag is a move. */
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 9bb6cec..472da44 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -29,7 +29,6 @@
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -43,6 +42,7 @@
import android.widget.TextView;
import com.android.launcher3.AppWidgetResizeFrame;
+import com.android.launcher3.BaseContainerView;
import com.android.launcher3.CellLayout;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.ItemInfo;
@@ -51,15 +51,18 @@
import com.android.launcher3.LauncherAppWidgetHostView;
import com.android.launcher3.PinchToOverviewListener;
import com.android.launcher3.R;
-import com.android.launcher3.SearchDropTargetBar;
+import com.android.launcher3.DropTargetBar;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
+import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.TouchController;
import java.util.ArrayList;
@@ -117,6 +120,11 @@
// Related to pinch-to-go-to-overview gesture.
private PinchToOverviewListener mPinchListener = null;
+
+ // Handles all apps pull up interaction
+ private AllAppsTransitionController mAllAppsController;
+
+ private TouchController mActiveController;
/**
* Used to create a new DragLayer from XML.
*
@@ -138,9 +146,11 @@
mIsRtl = Utilities.isRtl(res);
}
- public void setup(Launcher launcher, DragController controller) {
+ public void setup(Launcher launcher, DragController dragController,
+ AllAppsTransitionController allAppsTransitionController) {
mLauncher = launcher;
- mDragController = controller;
+ mDragController = dragController;
+ mAllAppsController = allAppsTransitionController;
boolean isAccessibilityEnabled = ((AccessibilityManager) mLauncher.getSystemService(
Context.ACCESSIBILITY_SERVICE)).isEnabled();
@@ -173,31 +183,17 @@
private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect);
- if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
- return true;
- }
- return false;
+ return mHitRect.contains((int) ev.getX(), (int) ev.getY());
}
private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
getDescendantRectRelativeToSelf(folder, mHitRect);
- if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
- return true;
- }
- return false;
+ return mHitRect.contains((int) ev.getX(), (int) ev.getY());
}
private boolean isEventOverDropTargetBar(MotionEvent ev) {
- getDescendantRectRelativeToSelf(mLauncher.getSearchDropTargetBar(), mHitRect);
- if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
- return true;
- }
-
- getDescendantRectRelativeToSelf(mLauncher.getAppInfoDropTargetBar(), mHitRect);
- if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
- return true;
- }
- return false;
+ getDescendantRectRelativeToSelf(mLauncher.getDropTargetBar(), mHitRect);
+ return mHitRect.contains((int) ev.getX(), (int) ev.getY());
}
private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
@@ -246,6 +242,7 @@
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
+
if (action == MotionEvent.ACTION_DOWN) {
if (handleTouchDown(ev, true)) {
return true;
@@ -258,11 +255,21 @@
}
clearAllResizeFrames();
- if (mPinchListener != null && mPinchListener.onInterceptTouchEvent(ev)) {
- // Stop listening for scrolling etc. (onTouchEvent() handles the rest of the pinch.)
+ if (mDragController.onInterceptTouchEvent(ev)) {
+ mActiveController = mDragController;
return true;
}
- return mDragController.onInterceptTouchEvent(ev);
+ if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && mAllAppsController.onInterceptTouchEvent(ev)) {
+ mActiveController = mAllAppsController;
+ return true;
+ }
+
+ if (mPinchListener != null && mPinchListener.onInterceptTouchEvent(ev)) {
+ // Stop listening for scrolling etc. (onTouchEvent() handles the rest of the pinch.)
+ mActiveController = mPinchListener;
+ return true;
+ }
+ return false;
}
@Override
@@ -334,7 +341,7 @@
return super.onRequestSendAccessibilityEvent(child, event);
}
- if (isInAccessibleDrag() && child instanceof SearchDropTargetBar) {
+ if (isInAccessibleDrag() && child instanceof DropTargetBar) {
return super.onRequestSendAccessibilityEvent(child, event);
}
// Skip propagating onRequestSendAccessibilityEvent all for other children
@@ -352,8 +359,7 @@
childrenForAccessibility.add(currentFolder);
if (isInAccessibleDrag()) {
- childrenForAccessibility.add(mLauncher.getSearchDropTargetBar());
- childrenForAccessibility.add(mLauncher.getAppInfoDropTargetBar());
+ childrenForAccessibility.add(mLauncher.getDropTargetBar());
}
} else {
super.addChildrenForAccessibility(childrenForAccessibility);
@@ -375,11 +381,6 @@
int x = (int) ev.getX();
int y = (int) ev.getY();
- // This is only reached if a pinch was started from onInterceptTouchEvent();
- // this continues sending events for it.
- if (mPinchListener != null) {
- mPinchListener.onTouchEvent(ev);
- }
if (action == MotionEvent.ACTION_DOWN) {
if (handleTouchDown(ev, false)) {
@@ -406,7 +407,10 @@
}
}
if (handled) return true;
- return mDragController.onTouchEvent(ev);
+ if (mActiveController != null) {
+ return mActiveController.onTouchEvent(ev);
+ }
+ return false;
}
@Override
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 6df296e..af93707 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -318,7 +318,7 @@
@Override
public void enableAccessibleDrag(boolean enable) {
- mLauncher.getSearchDropTargetBar().enableAccessibleDrag(enable);
+ mLauncher.getDropTargetBar().enableAccessibleDrag(enable);
for (int i = 0; i < mContent.getChildCount(); i++) {
mContent.getPageAt(i).enableAccessibleDrag(enable, CellLayout.FOLDER_ACCESSIBILITY_DRAG);
}
@@ -1054,7 +1054,7 @@
int top = Math.min(Math.max(sTempRect.top, centeredTop),
sTempRect.top + sTempRect.height() - height);
- int distFromEdgeOfScreen = grid.getWorkspacePadding(isLayoutRtl()).left + getPaddingLeft();
+ int distFromEdgeOfScreen = grid.getWorkspacePadding().left + getPaddingLeft();
if (grid.isPhone && (grid.availableWidthPx - width) < 4 * distFromEdgeOfScreen) {
// Center the folder if it is very close to being centered anyway, by virtue of
@@ -1093,7 +1093,7 @@
private int getContentAreaHeight() {
DeviceProfile grid = mLauncher.getDeviceProfile();
- Rect workspacePadding = grid.getWorkspacePadding(mContent.mIsRtl);
+ Rect workspacePadding = grid.getWorkspacePadding();
int maxContentAreaHeight = grid.availableHeightPx -
workspacePadding.top - workspacePadding.bottom -
mFooterHeight;
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorLine.java b/src/com/android/launcher3/pageindicators/PageIndicatorLine.java
index bfb4f33..aec708c 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorLine.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorLine.java
@@ -27,18 +27,29 @@
public class PageIndicatorLine extends PageIndicator {
private static final String TAG = "PageIndicatorLine";
- private static final int LINE_FADE_DURATION = ViewConfiguration.getScrollBarFadeDuration();
+ private static final int LINE_ANIMATE_DURATION = ViewConfiguration.getScrollBarFadeDuration();
private static final int LINE_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
public static final int WHITE_ALPHA = (int) (0.70f * 255);
public static final int BLACK_ALPHA = (int) (0.65f * 255);
+ private static final int LINE_ALPHA_ANIMATOR_INDEX = 0;
+ private static final int NUM_PAGES_ANIMATOR_INDEX = 1;
+ private static final int TOTAL_SCROLL_ANIMATOR_INDEX = 2;
+
+ private ValueAnimator[] mAnimators = new ValueAnimator[3];
+
private final Handler mDelayedLineFadeHandler = new Handler(Looper.getMainLooper());
private boolean mShouldAutoHide = true;
- private ValueAnimator mLineAlphaAnimator;
- private int mAlpha = 0;
- private float mProgress = 0f;
+ // The alpha of the line when it is showing.
+ private int mActiveAlpha = 0;
+ // The alpha that the line is being animated to or already at (either 0 or mActiveAlpha).
+ private int mToAlpha;
+ // A float value representing the number of pages, to allow for an animation when it changes.
+ private float mNumPagesFloat;
+ private int mCurrentScroll;
+ private int mTotalScroll;
private Paint mLinePaint;
private static final Property<PageIndicatorLine, Integer> PAINT_ALPHA
@@ -55,6 +66,34 @@
}
};
+ private static final Property<PageIndicatorLine, Float> NUM_PAGES
+ = new Property<PageIndicatorLine, Float>(Float.class, "num_pages") {
+ @Override
+ public Float get(PageIndicatorLine obj) {
+ return obj.mNumPagesFloat;
+ }
+
+ @Override
+ public void set(PageIndicatorLine obj, Float numPages) {
+ obj.mNumPagesFloat = numPages;
+ obj.invalidate();
+ }
+ };
+
+ private static final Property<PageIndicatorLine, Integer> TOTAL_SCROLL
+ = new Property<PageIndicatorLine, Integer>(Integer.class, "total_scroll") {
+ @Override
+ public Integer get(PageIndicatorLine obj) {
+ return obj.mTotalScroll;
+ }
+
+ @Override
+ public void set(PageIndicatorLine obj, Integer totalScroll) {
+ obj.mTotalScroll = totalScroll;
+ obj.invalidate();
+ }
+ };
+
private Runnable mHideLineRunnable = new Runnable() {
@Override
public void run() {
@@ -78,13 +117,15 @@
@Override
protected void onDraw(Canvas canvas) {
- if (mNumPages == 0) {
+ if (mTotalScroll == 0 || mNumPagesFloat == 0) {
return;
}
+ // Compute and draw line rect.
+ float progress = Utilities.boundToRange(((float) mCurrentScroll) / mTotalScroll, 0f, 1f);
int availableWidth = canvas.getWidth();
- int lineWidth = availableWidth / mNumPages;
- int lineLeft = (int) (mProgress * (availableWidth - lineWidth));
+ int lineWidth = (int) (availableWidth / mNumPagesFloat);
+ int lineLeft = (int) (progress * (availableWidth - lineWidth));
int lineRight = lineLeft + lineWidth;
canvas.drawRect(lineLeft, 0, lineRight, canvas.getHeight(), mLinePaint);
}
@@ -94,9 +135,16 @@
if (getAlpha() == 0) {
return;
}
- animateLineToAlpha(mAlpha);
- mProgress = Utilities.boundToRange(((float) currentScroll) / totalScroll, 0f, 1f);;
- invalidate();
+ animateLineToAlpha(mActiveAlpha);
+
+ mCurrentScroll = currentScroll;
+ if (mTotalScroll == 0) {
+ mTotalScroll = totalScroll;
+ } else if (mTotalScroll != totalScroll) {
+ animateToTotalScroll(totalScroll);
+ } else {
+ invalidate();
+ }
if (mShouldAutoHide) {
hideAfterDelay();
@@ -114,7 +162,9 @@
@Override
protected void onPageCountChanged() {
- invalidate();
+ if (Float.compare(mNumPages, mNumPagesFloat) != 0) {
+ animateToNumPages(mNumPages);
+ }
}
public void setShouldAutoHide(boolean shouldAutoHide) {
@@ -137,9 +187,9 @@
if (color != Color.TRANSPARENT) {
color = ColorUtils.setAlphaComponent(color, 255);
if (color == Color.BLACK) {
- mAlpha = BLACK_ALPHA;
+ mActiveAlpha = BLACK_ALPHA;
} else if (color == Color.WHITE) {
- mAlpha = WHITE_ALPHA;
+ mActiveAlpha = WHITE_ALPHA;
} else {
Log.e(TAG, "Setting workspace page indicators to an unsupported color: #"
+ Integer.toHexString(color));
@@ -150,22 +200,44 @@
}
private void animateLineToAlpha(int alpha) {
- if (mLineAlphaAnimator != null) {
- // An animation is already running, so ignore the new animation request unless we are
- // trying to hide the line, in which case we always allow the animation.
- if (alpha != 0) {
- return;
- }
- mLineAlphaAnimator.cancel();
+ if (alpha == mToAlpha) {
+ // Ignore the new animation if it is going to the same alpha as the current animation.
+ return;
}
- mLineAlphaAnimator = ObjectAnimator.ofInt(this, PAINT_ALPHA, alpha);
- mLineAlphaAnimator.addListener(new AnimatorListenerAdapter() {
+ mToAlpha = alpha;
+ setupAndRunAnimation(ObjectAnimator.ofInt(this, PAINT_ALPHA, alpha),
+ LINE_ALPHA_ANIMATOR_INDEX);
+ }
+
+ private void animateToNumPages(int numPages) {
+ setupAndRunAnimation(ObjectAnimator.ofFloat(this, NUM_PAGES, numPages),
+ NUM_PAGES_ANIMATOR_INDEX);
+ }
+
+ private void animateToTotalScroll(int totalScroll) {
+ setupAndRunAnimation(ObjectAnimator.ofInt(this, TOTAL_SCROLL, totalScroll),
+ TOTAL_SCROLL_ANIMATOR_INDEX);
+ }
+
+ /**
+ * Starts the given animator and stores it in the provided index in {@link #mAnimators} until
+ * the animation ends.
+ *
+ * If an animator is already at the index (i.e. it is already playing), it is canceled and
+ * replaced with the new animator.
+ */
+ private void setupAndRunAnimation(ValueAnimator animator, final int animatorIndex) {
+ if (mAnimators[animatorIndex] != null) {
+ mAnimators[animatorIndex].cancel();
+ }
+ mAnimators[animatorIndex] = animator;
+ mAnimators[animatorIndex].addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- mLineAlphaAnimator = null;
+ mAnimators[animatorIndex] = null;
}
});
- mLineAlphaAnimator.setDuration(LINE_FADE_DURATION);
- mLineAlphaAnimator.start();
+ mAnimators[animatorIndex].setDuration(LINE_ANIMATE_DURATION);
+ mAnimators[animatorIndex].start();
}
}
diff --git a/src/com/android/launcher3/util/TouchController.java b/src/com/android/launcher3/util/TouchController.java
new file mode 100644
index 0000000..d1409c8
--- /dev/null
+++ b/src/com/android/launcher3/util/TouchController.java
@@ -0,0 +1,8 @@
+package com.android.launcher3.util;
+
+import android.view.MotionEvent;
+
+public interface TouchController {
+ boolean onTouchEvent(MotionEvent ev);
+ boolean onInterceptTouchEvent(MotionEvent ev);
+}
diff --git a/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java b/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java
index 476eb0a..35f686f 100644
--- a/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java
+++ b/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java
@@ -116,75 +116,4 @@
// Add more tests for other devices, however, running them once on a single device is enough
// for verifying that for a platform version, the WindowManager and DisplayMetrics is
// working as intended.
-
- /**
- * Make sure that the height for the QSB is what we expect in normal mode.
- */
- public void testQsbNormalHeight() {
- Resources resources = getContext().getResources();
- DeviceProfile landscapeProfile = mInvariantProfile.landscapeProfile;
- DeviceProfile portraitProfile = mInvariantProfile.portraitProfile;
- landscapeProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_NORMAL);
- portraitProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_NORMAL);
- Rect portraitBounds = portraitProfile.getSearchBarBounds(true); // RTL shouldn't matter.
- int portraitHeight = (int) Utilities.dpiFromPx(portraitBounds.height(),
- resources.getDisplayMetrics());
- Rect landscapeBounds = landscapeProfile.getSearchBarBounds(true); // RTL shouldn't matter.
- int landscapeHeight = (int) Utilities.dpiFromPx(landscapeBounds.height(),
- resources.getDisplayMetrics());
- if (portraitProfile.isTablet) {
- assertEquals(8 + 48 + 24, portraitHeight);
- } else {
- assertEquals(8 + 48 + 12, portraitHeight);
- }
- // Make sure the height that we pass in the widget options bundle is the height of the
- // search bar + 8dps padding top and bottom.
- Point portraitDimens = portraitProfile.getSearchBarDimensForWidgetOpts(resources);
- int portraitWidgetOptsHeight = portraitDimens.y;
- Point landscapeDimens = landscapeProfile.getSearchBarDimensForWidgetOpts(resources);
- int landscapeWidgetOptsHeight = landscapeDimens.y;
- assertEquals(8 + 48 + 8, (int) Utilities.dpiFromPx(portraitWidgetOptsHeight,
- resources.getDisplayMetrics()));
- if (!landscapeProfile.isVerticalBarLayout()) {
- assertEquals(portraitHeight, landscapeHeight);
- assertEquals(portraitWidgetOptsHeight, landscapeWidgetOptsHeight);
- }
- }
-
- /**
- * Make sure that the height for the QSB is what we expect in tall mode.
- */
- public void testQsbTallHeight() {
- Resources resources = getContext().getResources();
- DeviceProfile landscapeProfile = mInvariantProfile.landscapeProfile;
- DeviceProfile portraitProfile = mInvariantProfile.portraitProfile;
- landscapeProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_TALL);
- portraitProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_TALL);
- Rect portraitBounds = portraitProfile.getSearchBarBounds(true); // RTL shouldn't matter.
- int portraitHeight = (int) Utilities.dpiFromPx(portraitBounds.height(),
- resources.getDisplayMetrics());
- Rect landscapeBounds = landscapeProfile.getSearchBarBounds(true); // RTL shouldn't matter.
- int landscapeHeight = (int) Utilities.dpiFromPx(landscapeBounds.height(),
- resources.getDisplayMetrics());
- if (portraitProfile.isPhone) {
- // This fails on some devices due to http://b/26884580 (portraitHeight is 101, not 100).
- // TODO: Remove the comparision against 101 once b/26884580 is fixed
- // assertEquals(4 + 94 + 2, portraitHeight);
- assertTrue(portraitHeight == (4 + 94 + 2) || portraitHeight == (4 + 95 + 2));
- } else {
- assertEquals(8 + 94 + 24, portraitHeight);
- }
- // Make sure the height that we pass in the widget options bundle is the height of the
- // search bar + 8dps padding top and bottom.
- Point portraitDimens = portraitProfile.getSearchBarDimensForWidgetOpts(resources);
- int portraitWidgetOptsHeight = portraitDimens.y;
- Point landscapeDimens = landscapeProfile.getSearchBarDimensForWidgetOpts(resources);
- int landscapeWidgetOptsHeight = landscapeDimens.y;
- assertEquals(8 + 94 + 8, (int) Utilities.dpiFromPx(portraitWidgetOptsHeight,
- resources.getDisplayMetrics()));
- if (!landscapeProfile.isVerticalBarLayout()) {
- assertEquals(portraitHeight, landscapeHeight);
- assertEquals(portraitWidgetOptsHeight, landscapeWidgetOptsHeight);
- }
- }
}