diff --git a/quickstep/res/drawable/gesture_tutorial_finger_dot.xml b/quickstep/res/drawable/gesture_tutorial_finger_dot.xml
new file mode 100644
index 0000000000..5f8aafd30a
--- /dev/null
+++ b/quickstep/res/drawable/gesture_tutorial_finger_dot.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/quickstep/res/drawable/gesture_tutorial_motion_back.xml b/quickstep/res/drawable/gesture_tutorial_motion_back.xml
deleted file mode 100644
index a6860fac64..0000000000
--- a/quickstep/res/drawable/gesture_tutorial_motion_back.xml
+++ /dev/null
@@ -1,1233 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/quickstep/res/drawable/gesture_tutorial_motion_home_dark_mode.xml b/quickstep/res/drawable/gesture_tutorial_motion_home_dark_mode.xml
deleted file mode 100644
index aff35c1bce..0000000000
--- a/quickstep/res/drawable/gesture_tutorial_motion_home_dark_mode.xml
+++ /dev/null
@@ -1,1254 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/quickstep/res/drawable/gesture_tutorial_motion_home_light_mode.xml b/quickstep/res/drawable/gesture_tutorial_motion_home_light_mode.xml
deleted file mode 100644
index 98d97ad62d..0000000000
--- a/quickstep/res/drawable/gesture_tutorial_motion_home_light_mode.xml
+++ /dev/null
@@ -1,1254 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/quickstep/res/drawable/gesture_tutorial_motion_overview_dark_mode.xml b/quickstep/res/drawable/gesture_tutorial_motion_overview_dark_mode.xml
deleted file mode 100644
index b007d20f34..0000000000
--- a/quickstep/res/drawable/gesture_tutorial_motion_overview_dark_mode.xml
+++ /dev/null
@@ -1,1623 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/drawable/gesture_tutorial_ripple.xml b/quickstep/res/drawable/gesture_tutorial_ripple.xml
similarity index 100%
rename from res/drawable/gesture_tutorial_ripple.xml
rename to quickstep/res/drawable/gesture_tutorial_ripple.xml
diff --git a/quickstep/res/drawable/mock_conversation.xml b/quickstep/res/drawable/mock_conversation.xml
deleted file mode 100644
index 272d9ed8a8..0000000000
--- a/quickstep/res/drawable/mock_conversation.xml
+++ /dev/null
@@ -1,212 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/quickstep/res/drawable/mock_conversations_list.xml b/quickstep/res/drawable/mock_conversations_list.xml
deleted file mode 100644
index 2dbc88f0bf..0000000000
--- a/quickstep/res/drawable/mock_conversations_list.xml
+++ /dev/null
@@ -1,361 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/quickstep/res/drawable/mock_webpage_dark_mode.xml b/quickstep/res/drawable/mock_webpage_dark_mode.xml
deleted file mode 100644
index 93b22b7d31..0000000000
--- a/quickstep/res/drawable/mock_webpage_dark_mode.xml
+++ /dev/null
@@ -1,251 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/quickstep/res/drawable/mock_webpage_light_mode.xml b/quickstep/res/drawable/mock_webpage_light_mode.xml
deleted file mode 100644
index 98abb92ab7..0000000000
--- a/quickstep/res/drawable/mock_webpage_light_mode.xml
+++ /dev/null
@@ -1,263 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_dialog.xml b/quickstep/res/layout/gesture_tutorial_dialog.xml
index 59bf7b965c..db6ec8533f 100644
--- a/quickstep/res/layout/gesture_tutorial_dialog.xml
+++ b/quickstep/res/layout/gesture_tutorial_dialog.xml
@@ -1,4 +1,18 @@
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_mock_conversation_list.xml b/quickstep/res/layout/gesture_tutorial_mock_conversation_list.xml
new file mode 100644
index 0000000000..ad6b165019
--- /dev/null
+++ b/quickstep/res/layout/gesture_tutorial_mock_conversation_list.xml
@@ -0,0 +1,394 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_mock_webpage.xml b/quickstep/res/layout/gesture_tutorial_mock_webpage.xml
new file mode 100644
index 0000000000..ab00a113b4
--- /dev/null
+++ b/quickstep/res/layout/gesture_tutorial_mock_webpage.xml
@@ -0,0 +1,274 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/quickstep/res/values-night/colors.xml b/quickstep/res/values-night/colors.xml
new file mode 100644
index 0000000000..c3b253654e
--- /dev/null
+++ b/quickstep/res/values-night/colors.xml
@@ -0,0 +1,25 @@
+
+
+
+
+ #99000000
+
+ #000000
+
+ #202124
+ #3c4043
+
+
\ No newline at end of file
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index 17980f0eeb..47552924ef 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -14,8 +14,6 @@
limitations under the License.
-->
- #FFFFFFFF
- #99000000
#fff
#39000000
@@ -31,4 +29,40 @@
#EBffffff
#99000000
+
+
+ #FFFFFFFF
+
+ #f9f9f9
+ #A0C2F9
+ #6DA1FF
+
+ #3C4043
+ #FF000000
+ #B7F29F
+
+
+ #f1f3f4
+ #e8eaed
+ #dadce0
+ #bdc1c6
+ #e8eaed
+ #dadce0
+ #dadce0
+
+
+ #dadce0
+ #e8eaed
+ #f8f9fa
+ #9aa0a6
+ #bdc1c6
+ #bdc1c6
+
+
+ #f1f3f4
+ #6e7175
+ #9a9a9a
+ #e8eaed
+ #80868b
+ #bdc1c6
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialController.java
index 957f776ae4..2f3a912fb4 100644
--- a/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialController.java
@@ -68,7 +68,6 @@ final class AssistantGestureTutorialController extends TutorialController {
showFeedback(R.string.assistant_gesture_feedback_swipe_too_far_from_corner);
break;
case ASSISTANT_COMPLETED:
- hideFeedback(true);
showRippleEffect(null);
showFeedback(R.string.assistant_gesture_tutorial_playground_subtitle);
break;
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index 3cb22f4ffe..f2402e31de 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -18,10 +18,9 @@ package com.android.quickstep.interaction;
import static com.android.quickstep.interaction.TutorialController.TutorialType.BACK_NAVIGATION;
import static com.android.quickstep.interaction.TutorialController.TutorialType.BACK_NAVIGATION_COMPLETE;
+import android.annotation.LayoutRes;
import android.graphics.PointF;
-import androidx.appcompat.content.res.AppCompatResources;
-
import com.android.launcher3.R;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
@@ -44,8 +43,18 @@ final class BackGestureTutorialController extends TutorialController {
}
@Override
- protected int getMockAppTaskThumbnailResId(boolean forDarkMode) {
- return R.drawable.mock_conversation;
+ protected int getMockAppTaskLayoutResId() {
+ return getMockAppTaskCurrentPageLayoutResId();
+ }
+
+ @LayoutRes
+ int getMockAppTaskCurrentPageLayoutResId() {
+ return R.layout.gesture_tutorial_mock_conversation;
+ }
+
+ @LayoutRes
+ int getMockAppTaskPreviousPageLayoutResId() {
+ return R.layout.gesture_tutorial_mock_conversation_list;
}
@Override
@@ -70,10 +79,8 @@ final class BackGestureTutorialController extends TutorialController {
switch (result) {
case BACK_COMPLETED_FROM_LEFT:
case BACK_COMPLETED_FROM_RIGHT:
- mTutorialFragment.releaseGestureVideoView();
- hideFeedback(true);
- mFakeTaskView.setBackground(AppCompatResources.getDrawable(mContext,
- R.drawable.mock_conversations_list));
+ mTutorialFragment.releaseFeedbackAnimation();
+ updateFakeAppTaskViewLayout(getMockAppTaskPreviousPageLayoutResId());
int subtitleResId = mTutorialFragment.isAtFinalStep()
? R.string.back_gesture_feedback_complete_without_follow_up
: R.string.back_gesture_feedback_complete_with_overview_follow_up;
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
index 1740f68cc1..f54734d525 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
@@ -15,6 +15,10 @@
*/
package com.android.quickstep.interaction;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.view.MotionEvent;
import android.view.View;
@@ -23,18 +27,76 @@ import androidx.annotation.Nullable;
import com.android.launcher3.R;
import com.android.quickstep.interaction.TutorialController.TutorialType;
+import java.util.ArrayList;
+
/** Shows the Back gesture interactive tutorial. */
public class BackGestureTutorialFragment extends TutorialFragment {
+
@Nullable
@Override
- Integer getFeedbackVideoResId(boolean forDarkMode) {
- return R.drawable.gesture_tutorial_motion_back;
+ Integer getEdgeAnimationResId() {
+ return R.drawable.gesture_tutorial_loop_back;
}
@Nullable
@Override
- Integer getGestureVideoResId() {
- return R.drawable.gesture_tutorial_loop_back;
+ protected Animator createGestureAnimation() {
+ if (!(mTutorialController instanceof BackGestureTutorialController)) {
+ return null;
+ }
+ BackGestureTutorialController controller =
+ (BackGestureTutorialController) mTutorialController;
+ float fingerDotStartTranslationX = (float) -(mRootView.getWidth() / 2);
+
+ AnimatorSet fingerDotAppearanceAnimator = controller.createFingerDotAppearanceAnimatorSet();
+ fingerDotAppearanceAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ mFingerDotView.setTranslationX(fingerDotStartTranslationX);
+ }
+ });
+
+ ObjectAnimator translationAnimator = ObjectAnimator.ofFloat(
+ mFingerDotView, View.TRANSLATION_X, fingerDotStartTranslationX, 0);
+ translationAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ controller.updateFakeAppTaskViewLayout(
+ controller.getMockAppTaskPreviousPageLayoutResId());
+ }
+ });
+ translationAnimator.setDuration(1000);
+
+ Animator animationPause = controller.createAnimationPause();
+ animationPause.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ controller.updateFakeAppTaskViewLayout(
+ controller.getMockAppTaskCurrentPageLayoutResId());
+ }
+ });
+ ArrayList animators = new ArrayList<>();
+
+ animators.add(fingerDotAppearanceAnimator);
+ animators.add(translationAnimator);
+ animators.add(controller.createFingerDotDisappearanceAnimatorSet());
+ animators.add(animationPause);
+
+ AnimatorSet finalAnimation = new AnimatorSet();
+ finalAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
+ controller.updateFakeAppTaskViewLayout(
+ controller.getMockAppTaskCurrentPageLayoutResId());
+ }
+ });
+ finalAnimation.playSequentially(animators);
+
+ return finalAnimation;
}
@Override
@@ -49,6 +111,7 @@ public class BackGestureTutorialFragment extends TutorialFragment {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
+ releaseFeedbackAnimation();
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN && mTutorialController != null) {
mTutorialController.setRippleHotspot(motionEvent.getX(), motionEvent.getY());
}
diff --git a/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java b/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
index 0521db4d1b..7465db3025 100644
--- a/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
+++ b/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
@@ -282,9 +282,7 @@ public class EdgeBackGesturePanel extends View {
.setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));
int currentNightMode =
context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
- mPaint.setColor(context.getColor(currentNightMode == Configuration.UI_MODE_NIGHT_YES
- ? R.color.back_arrow_color_light
- : R.color.back_arrow_color_dark));
+ mPaint.setColor(context.getColor(R.color.gesture_tutorial_back_arrow_color));
loadDimens();
updateArrowDirection();
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
index 819c91c55b..307a8fd230 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -42,8 +42,8 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll
}
@Override
- protected int getMockAppTaskThumbnailResId(boolean forDarkMode) {
- return forDarkMode ? R.drawable.mock_webpage_dark_mode : R.drawable.mock_webpage_light_mode;
+ protected int getMockAppTaskLayoutResId() {
+ return R.layout.gesture_tutorial_mock_webpage;
}
@Override
@@ -80,7 +80,7 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll
case HOME_NAVIGATION:
switch (result) {
case HOME_GESTURE_COMPLETED: {
- mTutorialFragment.releaseGestureVideoView();
+ mTutorialFragment.releaseFeedbackAnimation();
animateFakeTaskViewHome(finalVelocity, null);
int subtitleResId = mTutorialFragment.isAtFinalStep()
? R.string.home_gesture_feedback_complete_without_follow_up
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
index 9572637b0f..dcae07d88d 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
@@ -15,25 +15,73 @@
*/
package com.android.quickstep.interaction;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.view.MotionEvent;
+import android.view.View;
+
import androidx.annotation.Nullable;
import com.android.launcher3.R;
import com.android.quickstep.interaction.TutorialController.TutorialType;
+import java.util.ArrayList;
+
/** Shows the Home gesture interactive tutorial. */
public class HomeGestureTutorialFragment extends TutorialFragment {
+
@Nullable
@Override
- Integer getFeedbackVideoResId(boolean forDarkMode) {
- return forDarkMode
- ? R.drawable.gesture_tutorial_motion_home_dark_mode
- : R.drawable.gesture_tutorial_motion_home_light_mode;
+ Integer getEdgeAnimationResId() {
+ return R.drawable.gesture_tutorial_loop_home;
}
@Nullable
@Override
- Integer getGestureVideoResId() {
- return R.drawable.gesture_tutorial_loop_home;
+ protected Animator createGestureAnimation() {
+ if (!(mTutorialController instanceof HomeGestureTutorialController)) {
+ return null;
+ }
+ float fingerDotStartTranslationY = (float) mRootView.getFullscreenHeight() / 2;
+ HomeGestureTutorialController controller =
+ (HomeGestureTutorialController) mTutorialController;
+
+ AnimatorSet fingerDotAppearanceAnimator = controller.createFingerDotAppearanceAnimatorSet();
+ fingerDotAppearanceAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ mFingerDotView.setTranslationY(fingerDotStartTranslationY);
+ }
+ });
+
+ Animator animationPause = controller.createAnimationPause();
+ animationPause.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ controller.resetFakeTaskView();
+ }
+ });
+ ArrayList animators = new ArrayList<>();
+
+ animators.add(fingerDotAppearanceAnimator);
+ animators.add(controller.createFingerDotHomeSwipeAnimator(fingerDotStartTranslationY));
+ animators.add(controller.createFingerDotDisappearanceAnimatorSet());
+ animators.add(animationPause);
+
+ AnimatorSet finalAnimation = new AnimatorSet();
+ finalAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
+ controller.resetFakeTaskView();
+ }
+ });
+ finalAnimation.playSequentially(animators);
+
+ return finalAnimation;
}
@Override
@@ -45,4 +93,10 @@ public class HomeGestureTutorialFragment extends TutorialFragment {
Class extends TutorialController> getControllerClass() {
return HomeGestureTutorialController.class;
}
+
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ releaseFeedbackAnimation();
+ return super.onTouch(view, motionEvent);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
index 77ddb2b320..b38a641b0e 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -49,8 +49,8 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
}
@Override
- protected int getMockAppTaskThumbnailResId(boolean forDarkMode) {
- return R.drawable.mock_conversations_list;
+ protected int getMockAppTaskLayoutResId() {
+ return R.layout.gesture_tutorial_mock_conversation_list;
}
@Override
@@ -98,13 +98,8 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
showFeedback(R.string.overview_gesture_feedback_swipe_too_far_from_edge);
break;
case OVERVIEW_GESTURE_COMPLETED:
- mTutorialFragment.releaseGestureVideoView();
- PendingAnimation anim = new PendingAnimation(300);
- anim.setFloat(mTaskViewSwipeUpAnimation
- .getCurrentShift(), AnimatedFloat.VALUE, 1, ACCEL);
- AnimatorSet animset = anim.buildAnim();
- animset.start();
- mRunningWindowAnim = SwipeUpAnimationLogic.RunningWindowAnim.wrap(animset);
+ mTutorialFragment.releaseFeedbackAnimation();
+ animateTaskViewToOverview();
onMotionPaused(true /*arbitrary value*/);
int subtitleResId = mTutorialFragment.getNumSteps() > 1
&& mTutorialFragment.isAtFinalStep()
@@ -126,4 +121,13 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
break;
}
}
+
+ public void animateTaskViewToOverview() {
+ PendingAnimation anim = new PendingAnimation(300);
+ anim.setFloat(mTaskViewSwipeUpAnimation
+ .getCurrentShift(), AnimatedFloat.VALUE, 1, ACCEL);
+ AnimatorSet animset = anim.buildAnim();
+ animset.start();
+ mRunningWindowAnim = SwipeUpAnimationLogic.RunningWindowAnim.wrap(animset);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
index d2ec327c81..968412bedc 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
@@ -15,25 +15,96 @@
*/
package com.android.quickstep.interaction;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.view.MotionEvent;
+import android.view.View;
+
import androidx.annotation.Nullable;
import com.android.launcher3.R;
import com.android.quickstep.interaction.TutorialController.TutorialType;
+import java.util.ArrayList;
+
/** Shows the Overview gesture interactive tutorial. */
public class OverviewGestureTutorialFragment extends TutorialFragment {
+
@Nullable
@Override
- Integer getFeedbackVideoResId(boolean forDarkMode) {
- return forDarkMode
- ? R.drawable.gesture_tutorial_motion_overview_dark_mode
- : R.drawable.gesture_tutorial_motion_overview_light_mode;
+ Integer getEdgeAnimationResId() {
+ return R.drawable.gesture_tutorial_loop_overview;
}
@Nullable
@Override
- Integer getGestureVideoResId() {
- return R.drawable.gesture_tutorial_loop_overview;
+ protected Animator createGestureAnimation() {
+ if (!(mTutorialController instanceof OverviewGestureTutorialController)) {
+ return null;
+ }
+ float fingerDotStartTranslationY = (float) mRootView.getFullscreenHeight() / 2;
+ OverviewGestureTutorialController controller =
+ (OverviewGestureTutorialController) mTutorialController;
+
+ AnimatorSet fingerDotAppearanceAnimator = controller.createFingerDotAppearanceAnimatorSet();
+ fingerDotAppearanceAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+
+ mFingerDotView.setTranslationY(fingerDotStartTranslationY);
+ }
+ });
+
+ Animator swipeAnimator =
+ controller.createFingerDotOverviewSwipeAnimator(fingerDotStartTranslationY);
+ swipeAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mFakePreviousTaskView.setVisibility(View.VISIBLE);
+ controller.onMotionPaused(true /*arbitrary value*/);
+ }
+ });
+
+ AnimatorSet fingerDotDisappearanceAnimator =
+ controller.createFingerDotDisappearanceAnimatorSet();
+ fingerDotDisappearanceAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ controller.animateTaskViewToOverview();
+ }
+ });
+
+ Animator animationPause = controller.createAnimationPause();
+ animationPause.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ controller.resetFakeTaskView();
+ }
+ });
+ ArrayList animators = new ArrayList<>();
+
+ animators.add(fingerDotAppearanceAnimator);
+ animators.add(swipeAnimator);
+ animators.add(controller.createAnimationPause());
+ animators.add(fingerDotDisappearanceAnimator);
+ animators.add(animationPause);
+
+ AnimatorSet finalAnimation = new AnimatorSet();
+ finalAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
+ controller.resetFakeTaskView();
+ }
+ });
+ finalAnimation.playSequentially(animators);
+
+ return finalAnimation;
}
@Override
@@ -45,4 +116,10 @@ public class OverviewGestureTutorialFragment extends TutorialFragment {
Class extends TutorialController> getControllerClass() {
return OverviewGestureTutorialController.class;
}
+
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ releaseFeedbackAnimation();
+ return super.onTouch(view, motionEvent);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
index db1afc2012..ac0c17d72f 100644
--- a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
+++ b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
@@ -16,8 +16,10 @@
package com.android.quickstep.interaction;
import android.content.Context;
+import android.graphics.Insets;
import android.util.AttributeSet;
import android.view.MotionEvent;
+import android.view.WindowInsets;
import android.widget.RelativeLayout;
import androidx.fragment.app.FragmentManager;
@@ -41,4 +43,13 @@ public class RootSandboxLayout extends RelativeLayout {
return ((TutorialFragment) FragmentManager.findFragment(this))
.onInterceptTouch(motionEvent);
}
+
+ /**
+ * Returns this view's fullscreen height. This method is agnostic of this view's actual height.
+ */
+ public int getFullscreenHeight() {
+ Insets insets = getRootWindowInsets().getInsets(WindowInsets.Type.systemBars());
+
+ return getHeight() + insets.top + insets.bottom;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 04b147cc1a..c2c8f61b19 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -25,6 +25,7 @@ import static com.android.quickstep.interaction.TutorialController.TutorialType.
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Outline;
@@ -32,7 +33,6 @@ import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
-import android.util.DisplayMetrics;
import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewOutlineProvider;
@@ -63,23 +63,24 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
private static final int FAKE_PREVIOUS_TASK_MARGIN = Utilities.dpToPx(12);
+ private static final long HOME_SWIPE_ANIMATION_DURATION_MILLIS = 625;
+ private static final long OVERVIEW_SWIPE_ANIMATION_DURATION_MILLIS = 1000;
+
final ViewSwipeUpAnimation mTaskViewSwipeUpAnimation;
private float mFakeTaskViewRadius;
- private Rect mFakeTaskViewRect = new Rect();
+ private final Rect mFakeTaskViewRect = new Rect();
RunningWindowAnim mRunningWindowAnim;
private boolean mShowTasks = false;
private boolean mShowPreviousTasks = false;
- private AnimatorListenerAdapter mResetTaskView = new AnimatorListenerAdapter() {
+ private final AnimatorListenerAdapter mResetTaskView = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mFakeHotseatView.setVisibility(View.INVISIBLE);
mFakeIconView.setVisibility(View.INVISIBLE);
if (mTutorialFragment.getActivity() != null) {
- DisplayMetrics displayMetrics =
- mTutorialFragment.getResources().getDisplayMetrics();
- int height = displayMetrics.heightPixels;
- int width = displayMetrics.widthPixels;
+ int height = mTutorialFragment.getRootView().getFullscreenHeight();
+ int width = mTutorialFragment.getRootView().getWidth();
mFakeTaskViewRect.set(0, 0, width, height);
}
mFakeTaskViewRadius = 0;
@@ -108,9 +109,8 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
.copy(mContext);
mTaskViewSwipeUpAnimation.initDp(dp);
- DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
- int height = displayMetrics.heightPixels;
- int width = displayMetrics.widthPixels;
+ int height = mTutorialFragment.getRootView().getFullscreenHeight();
+ int width = mTutorialFragment.getRootView().getWidth();
mFakeTaskViewRect.set(0, 0, width, height);
mFakeTaskViewRadius = 0;
@@ -138,7 +138,6 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
/** Fades the task view, optionally after animating to a fake Overview. */
void fadeOutFakeTaskView(boolean toOverviewFirst, boolean reset,
@Nullable Runnable onEndRunnable) {
- hideFeedback(true);
cancelRunningAnimation();
PendingAnimation anim = new PendingAnimation(300);
if (toOverviewFirst) {
@@ -184,6 +183,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
}
void resetFakeTaskView() {
+ mFakeTaskView.setVisibility(View.VISIBLE);
PendingAnimation anim = new PendingAnimation(300);
anim.setFloat(mTaskViewSwipeUpAnimation
.getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
@@ -195,7 +195,6 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
}
void animateFakeTaskViewHome(PointF finalVelocity, @Nullable Runnable onEndRunnable) {
- hideFeedback(true);
cancelRunningAnimation();
mFakePreviousTaskView.setVisibility(View.INVISIBLE);
mFakeHotseatView.setVisibility(View.VISIBLE);
@@ -218,9 +217,6 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
if (mGestureCompleted) {
return;
}
- if (displacement != null) {
- hideFeedback(true);
- }
if (mTutorialType == HOME_NAVIGATION_COMPLETE
|| mTutorialType == OVERVIEW_NAVIGATION_COMPLETE) {
mFakeTaskView.setVisibility(View.INVISIBLE);
@@ -336,6 +332,44 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
}
}
+ protected Animator createFingerDotHomeSwipeAnimator(float fingerDotStartTranslationY) {
+ Animator homeSwipeAnimator = createFingerDotSwipeUpAnimator(fingerDotStartTranslationY)
+ .setDuration(HOME_SWIPE_ANIMATION_DURATION_MILLIS);
+
+ homeSwipeAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ animateFakeTaskViewHome(
+ new PointF(
+ 0f,
+ fingerDotStartTranslationY / HOME_SWIPE_ANIMATION_DURATION_MILLIS),
+ null);
+ }
+ });
+
+ return homeSwipeAnimator;
+ }
+
+ protected Animator createFingerDotOverviewSwipeAnimator(float fingerDotStartTranslationY) {
+ return createFingerDotSwipeUpAnimator(fingerDotStartTranslationY)
+ .setDuration(OVERVIEW_SWIPE_ANIMATION_DURATION_MILLIS);
+ }
+
+
+ private Animator createFingerDotSwipeUpAnimator(float fingerDotStartTranslationY) {
+ ValueAnimator swipeAnimator = ValueAnimator.ofFloat(0f, 1f);
+
+ swipeAnimator.addUpdateListener(valueAnimator -> {
+ float gestureProgress =
+ -fingerDotStartTranslationY * valueAnimator.getAnimatedFraction();
+ setNavBarGestureProgress(gestureProgress);
+ mFingerDotView.setTranslationY(fingerDotStartTranslationY + gestureProgress);
+ });
+
+ return swipeAnimator;
+ }
+
private class FakeTransformParams extends TransformParams {
@Override
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 4b4e7e6753..77bfc31c30 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -16,25 +16,32 @@
package com.android.quickstep.interaction;
import static android.view.View.GONE;
+import static android.view.View.NO_ID;
+import static android.view.View.inflate;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Button;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.CallSuper;
import androidx.annotation.DrawableRes;
+import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
@@ -48,18 +55,25 @@ import com.android.launcher3.views.ClipIconView;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback;
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureAttemptCallback;
+import java.util.ArrayList;
+
abstract class TutorialController implements BackGestureAttemptCallback,
NavBarGestureAttemptCallback {
private static final String TAG = "TutorialController";
+ private static final float FINGER_DOT_VISIBLE_ALPHA = 0.6f;
+ private static final float FINGER_DOT_SMALL_SCALE = 0.7f;
+ private static final int FINGER_DOT_ANIMATION_DURATION_MILLIS = 500;
+
private static final String PIXEL_TIPS_APP_PACKAGE_NAME = "com.google.android.apps.tips";
private static final CharSequence DEFAULT_PIXEL_TIPS_APP_NAME = "Pixel Tips";
- private static final int FEEDBACK_ANIMATION_MS = 250;
+ private static final int FEEDBACK_ANIMATION_MS = 133;
private static final int RIPPLE_VISIBLE_MS = 300;
private static final int GESTURE_ANIMATION_DELAY_MS = 1500;
private static final int ADVANCE_TUTORIAL_TIMEOUT_MS = 4000;
+ private static final long GESTURE_ANIMATION_PAUSE_DURATION_MILLIS = 1000;
final TutorialFragment mTutorialFragment;
TutorialType mTutorialType;
@@ -68,17 +82,17 @@ abstract class TutorialController implements BackGestureAttemptCallback,
final TextView mCloseButton;
final ViewGroup mFeedbackView;
final TextView mFeedbackTitleView;
- final ImageView mFeedbackVideoView;
- final ImageView mGestureVideoView;
+ final ImageView mEdgeGestureVideoView;
final RelativeLayout mFakeLauncherView;
final ImageView mFakeHotseatView;
final ClipIconView mFakeIconView;
- final View mFakeTaskView;
+ final FrameLayout mFakeTaskView;
final View mFakePreviousTaskView;
final View mRippleView;
final RippleDrawable mRippleDrawable;
final Button mActionButton;
final TutorialStepIndicator mTutorialStepView;
+ final ImageView mFingerDotView;
private final AlertDialog mSkipTutorialDialog;
protected boolean mGestureCompleted = false;
@@ -87,7 +101,8 @@ abstract class TutorialController implements BackGestureAttemptCallback,
// views before posting new callbacks.
private final Runnable mTitleViewCallback;
@Nullable private Runnable mFeedbackViewCallback;
- @Nullable private Runnable mFeedbackVideoViewCallback;
+ @Nullable private Runnable mFakeTaskViewCallback;
+ private final Runnable mShowFeedbackRunnable;
TutorialController(TutorialFragment tutorialFragment, TutorialType tutorialType) {
mTutorialFragment = tutorialFragment;
@@ -100,8 +115,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view);
mFeedbackTitleView = mFeedbackView.findViewById(
R.id.gesture_tutorial_fragment_feedback_title);
- mFeedbackVideoView = rootView.findViewById(R.id.gesture_tutorial_feedback_video);
- mGestureVideoView = rootView.findViewById(R.id.gesture_tutorial_gesture_video);
+ mEdgeGestureVideoView = rootView.findViewById(R.id.gesture_tutorial_edge_gesture_video);
mFakeLauncherView = rootView.findViewById(R.id.gesture_tutorial_fake_launcher_view);
mFakeHotseatView = rootView.findViewById(R.id.gesture_tutorial_fake_hotseat_view);
mFakeIconView = rootView.findViewById(R.id.gesture_tutorial_fake_icon_view);
@@ -113,10 +127,34 @@ abstract class TutorialController implements BackGestureAttemptCallback,
mActionButton = rootView.findViewById(R.id.gesture_tutorial_fragment_action_button);
mTutorialStepView =
rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_tutorial_step);
+ mFingerDotView = rootView.findViewById(R.id.gesture_tutorial_finger_dot);
mSkipTutorialDialog = createSkipTutorialDialog();
mTitleViewCallback = () -> mFeedbackTitleView.sendAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ mShowFeedbackRunnable = () -> {
+ mFeedbackView.setAlpha(0f);
+ mFeedbackView.setScaleX(0.95f);
+ mFeedbackView.setScaleY(0.95f);
+ mFeedbackView.setVisibility(View.VISIBLE);
+ mFeedbackView.animate()
+ .setDuration(FEEDBACK_ANIMATION_MS)
+ .alpha(1f)
+ .scaleX(1f)
+ .scaleY(1f)
+ .withEndAction(() -> {
+ if (mGestureCompleted && !mTutorialFragment.isAtFinalStep()) {
+ if (mFeedbackViewCallback != null) {
+ mFeedbackView.removeCallbacks(mFeedbackViewCallback);
+ }
+ mFeedbackViewCallback = mTutorialFragment::continueTutorial;
+ mFeedbackView.postDelayed(mFeedbackViewCallback,
+ ADVANCE_TUTORIAL_TIMEOUT_MS);
+ }
+ })
+ .start();
+ mFeedbackTitleView.postDelayed(mTitleViewCallback, FEEDBACK_ANIMATION_MS);
+ };
}
private void showSkipTutorialDialog() {
@@ -134,9 +172,9 @@ abstract class TutorialController implements BackGestureAttemptCallback,
return R.drawable.default_sandbox_mock_launcher;
}
- @DrawableRes
- protected int getMockAppTaskThumbnailResId(boolean forDarkMode) {
- return R.drawable.default_sandbox_app_task_thumbnail;
+ @LayoutRes
+ protected int getMockAppTaskLayoutResId() {
+ return View.NO_ID;
}
@DrawableRes
@@ -173,17 +211,10 @@ abstract class TutorialController implements BackGestureAttemptCallback,
mFeedbackView.setTranslationY(0);
return;
}
- AnimatedVectorDrawable tutorialAnimation = mTutorialFragment.getTutorialAnimation();
- AnimatedVectorDrawable gestureAnimation = mTutorialFragment.getGestureAnimation();
-
- if (tutorialAnimation != null && gestureAnimation != null) {
- TextView title = mFeedbackView.findViewById(
- R.id.gesture_tutorial_fragment_feedback_title);
-
- playFeedbackVideo(tutorialAnimation, gestureAnimation, () -> {
- mFeedbackView.setTranslationY(0);
- title.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
- }, true);
+ Animator gestureAnimation = mTutorialFragment.getGestureAnimation();
+ AnimatedVectorDrawable edgeAnimation = mTutorialFragment.getEdgeAnimation();
+ if (gestureAnimation != null && edgeAnimation != null) {
+ playFeedbackAnimation(gestureAnimation, edgeAnimation, mShowFeedbackRunnable, true);
}
}
@@ -215,8 +246,13 @@ abstract class TutorialController implements BackGestureAttemptCallback,
int subtitleResId,
boolean isGestureSuccessful,
boolean useGestureAnimationDelay) {
- mFeedbackTitleView.setText(titleResId);
mFeedbackTitleView.removeCallbacks(mTitleViewCallback);
+ if (mFeedbackViewCallback != null) {
+ mFeedbackView.removeCallbacks(mFeedbackViewCallback);
+ mFeedbackViewCallback = null;
+ }
+
+ mFeedbackTitleView.setText(titleResId);
TextView subtitle =
mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_subtitle);
subtitle.setText(subtitleResId);
@@ -226,77 +262,68 @@ abstract class TutorialController implements BackGestureAttemptCallback,
showActionButton();
}
- if (mFeedbackVideoViewCallback != null) {
- mFeedbackVideoView.removeCallbacks(mFeedbackVideoViewCallback);
- mFeedbackVideoViewCallback = null;
+ if (mFakeTaskViewCallback != null) {
+ mFakeTaskView.removeCallbacks(mFakeTaskViewCallback);
+ mFakeTaskViewCallback = null;
}
}
mGestureCompleted = isGestureSuccessful;
- AnimatedVectorDrawable tutorialAnimation = mTutorialFragment.getTutorialAnimation();
- AnimatedVectorDrawable gestureAnimation = mTutorialFragment.getGestureAnimation();
- if (tutorialAnimation != null && gestureAnimation != null) {
- if (!isGestureSuccessful) {
- playFeedbackVideo(tutorialAnimation, gestureAnimation, () -> {
- mFeedbackView.setTranslationY(
- -mFeedbackView.getHeight() - mFeedbackView.getTop());
- mFeedbackView.setVisibility(View.VISIBLE);
- mFeedbackView.animate()
- .setDuration(FEEDBACK_ANIMATION_MS)
- .translationY(0)
- .start();
- mFeedbackTitleView.postDelayed(mTitleViewCallback, FEEDBACK_ANIMATION_MS);
- }, useGestureAnimationDelay);
- return;
- } else {
- mTutorialFragment.releaseFeedbackVideoView();
- }
+ Animator gestureAnimation = mTutorialFragment.getGestureAnimation();
+ AnimatedVectorDrawable edgeAnimation = mTutorialFragment.getEdgeAnimation();
+ if (!isGestureSuccessful && gestureAnimation != null && edgeAnimation != null) {
+ playFeedbackAnimation(
+ gestureAnimation,
+ edgeAnimation,
+ mShowFeedbackRunnable,
+ useGestureAnimationDelay);
+ return;
+ } else {
+ mTutorialFragment.releaseFeedbackAnimation();
}
- mFeedbackView.setTranslationY(-mFeedbackView.getHeight() - mFeedbackView.getTop());
- mFeedbackView.setVisibility(View.VISIBLE);
- mFeedbackView.animate()
- .setDuration(FEEDBACK_ANIMATION_MS)
- .translationY(0)
- .withEndAction(() -> {
- if (isGestureSuccessful && !mTutorialFragment.isAtFinalStep()) {
- if (mFeedbackViewCallback != null) {
- mFeedbackView.removeCallbacks(mFeedbackViewCallback);
- }
- mFeedbackViewCallback = mTutorialFragment::continueTutorial;
- mFeedbackView.postDelayed(mFeedbackViewCallback,
- ADVANCE_TUTORIAL_TIMEOUT_MS);
- }
- })
- .start();
- mFeedbackTitleView.postDelayed(mTitleViewCallback, FEEDBACK_ANIMATION_MS);
+ mFeedbackViewCallback = mShowFeedbackRunnable;
+
+ mFeedbackView.post(mFeedbackViewCallback);
}
- void hideFeedback(boolean releaseFeedbackVideo) {
+ void hideFeedback() {
+ cancelQueuedGestureAnimation();
mFeedbackView.clearAnimation();
mFeedbackView.setVisibility(View.INVISIBLE);
- if (releaseFeedbackVideo) {
- mTutorialFragment.releaseFeedbackVideoView();
- }
}
- private void playFeedbackVideo(
- @NonNull AnimatedVectorDrawable tutorialAnimation,
- @NonNull AnimatedVectorDrawable gestureAnimation,
+ void cancelQueuedGestureAnimation() {
+ if (mFeedbackViewCallback != null) {
+ mFeedbackView.removeCallbacks(mFeedbackViewCallback);
+ mFeedbackViewCallback = null;
+ }
+ if (mFakeTaskViewCallback != null) {
+ mFakeTaskView.removeCallbacks(mFakeTaskViewCallback);
+ mFakeTaskViewCallback = null;
+ }
+ mFeedbackTitleView.removeCallbacks(mTitleViewCallback);
+ }
+
+ private void playFeedbackAnimation(
+ @NonNull Animator gestureAnimation,
+ @NonNull AnimatedVectorDrawable edgeAnimation,
@NonNull Runnable onStartRunnable,
boolean useGestureAnimationDelay) {
- if (tutorialAnimation.isRunning()) {
- tutorialAnimation.reset();
+ if (gestureAnimation.isRunning()) {
+ gestureAnimation.cancel();
}
- tutorialAnimation.registerAnimationCallback(new Animatable2.AnimationCallback() {
-
+ if (edgeAnimation.isRunning()) {
+ edgeAnimation.reset();
+ }
+ gestureAnimation.addListener(new AnimatorListenerAdapter() {
@Override
- public void onAnimationStart(Drawable drawable) {
- super.onAnimationStart(drawable);
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
- mGestureVideoView.setVisibility(GONE);
- if (gestureAnimation.isRunning()) {
- gestureAnimation.stop();
+ mEdgeGestureVideoView.setVisibility(GONE);
+ if (edgeAnimation.isRunning()) {
+ edgeAnimation.stop();
}
if (!useGestureAnimationDelay) {
@@ -305,37 +332,25 @@ abstract class TutorialController implements BackGestureAttemptCallback,
}
@Override
- public void onAnimationEnd(Drawable drawable) {
- super.onAnimationEnd(drawable);
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
- mGestureVideoView.setVisibility(View.VISIBLE);
- gestureAnimation.start();
+ mEdgeGestureVideoView.setVisibility(View.VISIBLE);
+ edgeAnimation.start();
- tutorialAnimation.unregisterAnimationCallback(this);
+ gestureAnimation.removeListener(this);
}
});
- if (mFeedbackViewCallback != null) {
- mFeedbackVideoView.removeCallbacks(mFeedbackViewCallback);
- mFeedbackViewCallback = null;
- }
- if (mFeedbackVideoViewCallback != null) {
- mFeedbackVideoView.removeCallbacks(mFeedbackVideoViewCallback);
- mFeedbackVideoViewCallback = null;
- }
+ cancelQueuedGestureAnimation();
if (useGestureAnimationDelay) {
mFeedbackViewCallback = onStartRunnable;
- mFeedbackVideoViewCallback = () -> {
- mFeedbackVideoView.setVisibility(View.VISIBLE);
- tutorialAnimation.start();
- };
+ mFakeTaskViewCallback = gestureAnimation::start;
- mFeedbackVideoView.setVisibility(View.GONE);
mFeedbackView.post(mFeedbackViewCallback);
- mFeedbackVideoView.postDelayed(mFeedbackVideoViewCallback, GESTURE_ANIMATION_DELAY_MS);
+ mFakeTaskView.postDelayed(mFakeTaskViewCallback, GESTURE_ANIMATION_DELAY_MS);
} else {
- mFeedbackVideoView.setVisibility(View.VISIBLE);
- tutorialAnimation.start();
+ gestureAnimation.start();
}
}
@@ -360,7 +375,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
@CallSuper
void transitToController() {
- hideFeedback(false);
+ hideFeedback();
hideActionButton();
updateSubtext();
updateDrawables();
@@ -395,6 +410,17 @@ abstract class TutorialController implements BackGestureAttemptCallback,
mActionButton.setOnClickListener(this::onActionButtonClicked);
}
+ void updateFakeAppTaskViewLayout(@LayoutRes int mockAppTaskLayoutResId) {
+ mFakeTaskView.removeAllViews();
+ if (mockAppTaskLayoutResId != NO_ID) {
+ mFakeTaskView.addView(
+ inflate(mContext, mockAppTaskLayoutResId, null),
+ new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ }
+ }
+
private void updateSubtext() {
mTutorialStepView.setTutorialProgress(
mTutorialFragment.getCurrentStep(), mTutorialFragment.getNumSteps());
@@ -404,15 +430,12 @@ abstract class TutorialController implements BackGestureAttemptCallback,
if (mContext != null) {
mTutorialFragment.getRootView().setBackground(AppCompatResources.getDrawable(
mContext, getMockWallpaperResId()));
- mTutorialFragment.updateFeedbackVideo();
+ mTutorialFragment.updateFeedbackAnimation();
mFakeLauncherView.setBackgroundColor(
- mContext.getColor(Utilities.isDarkTheme(mContext)
- ? R.color.fake_wallpaper_color_dark_mode
- : R.color.fake_wallpaper_color_light_mode));
+ mContext.getColor(R.color.gesture_tutorial_fake_wallpaper_color));
mFakeHotseatView.setImageDrawable(AppCompatResources.getDrawable(
mContext, getMockHotseatResId()));
- mFakeTaskView.setBackground(AppCompatResources.getDrawable(
- mContext, getMockAppTaskThumbnailResId(Utilities.isDarkTheme(mContext))));
+ updateFakeAppTaskViewLayout(getMockAppTaskLayoutResId());
mFakeTaskView.animate().alpha(1).setListener(
AnimatorListeners.forSuccessCallback(() -> mFakeTaskView.animate().cancel()));
mFakePreviousTaskView.setBackground(AppCompatResources.getDrawable(
@@ -485,6 +508,52 @@ abstract class TutorialController implements BackGestureAttemptCallback,
return null;
}
+ protected AnimatorSet createFingerDotAppearanceAnimatorSet() {
+ ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(
+ mFingerDotView, View.ALPHA, 0f, FINGER_DOT_VISIBLE_ALPHA);
+ ObjectAnimator yScaleAnimator = ObjectAnimator.ofFloat(
+ mFingerDotView, View.SCALE_Y, FINGER_DOT_SMALL_SCALE, 1f);
+ ObjectAnimator xScaleAnimator = ObjectAnimator.ofFloat(
+ mFingerDotView, View.SCALE_X, FINGER_DOT_SMALL_SCALE, 1f);
+ ArrayList animators = new ArrayList<>();
+
+ animators.add(alphaAnimator);
+ animators.add(xScaleAnimator);
+ animators.add(yScaleAnimator);
+
+ AnimatorSet appearanceAnimatorSet = new AnimatorSet();
+
+ appearanceAnimatorSet.playTogether(animators);
+ appearanceAnimatorSet.setDuration(FINGER_DOT_ANIMATION_DURATION_MILLIS);
+
+ return appearanceAnimatorSet;
+ }
+
+ protected AnimatorSet createFingerDotDisappearanceAnimatorSet() {
+ ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(
+ mFingerDotView, View.ALPHA, FINGER_DOT_VISIBLE_ALPHA, 0f);
+ ObjectAnimator yScaleAnimator = ObjectAnimator.ofFloat(
+ mFingerDotView, View.SCALE_Y, 1f, FINGER_DOT_SMALL_SCALE);
+ ObjectAnimator xScaleAnimator = ObjectAnimator.ofFloat(
+ mFingerDotView, View.SCALE_X, 1f, FINGER_DOT_SMALL_SCALE);
+ ArrayList animators = new ArrayList<>();
+
+ animators.add(alphaAnimator);
+ animators.add(xScaleAnimator);
+ animators.add(yScaleAnimator);
+
+ AnimatorSet appearanceAnimatorSet = new AnimatorSet();
+
+ appearanceAnimatorSet.playTogether(animators);
+ appearanceAnimatorSet.setDuration(FINGER_DOT_ANIMATION_DURATION_MILLIS);
+
+ return appearanceAnimatorSet;
+ }
+
+ protected Animator createAnimationPause() {
+ return ValueAnimator.ofFloat(0f, 1f).setDuration(GESTURE_ANIMATION_PAUSE_DURATION_MILLIS);
+ }
+
/** Denotes the type of the tutorial. */
enum TutorialType {
BACK_NAVIGATION,
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 7637450a1a..52ec9b39f0 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -15,6 +15,8 @@
*/
package com.android.quickstep.interaction;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -29,6 +31,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.widget.ImageView;
@@ -38,7 +41,6 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.quickstep.interaction.TutorialController.TutorialType;
abstract class TutorialFragment extends Fragment implements OnTouchListener {
@@ -49,13 +51,14 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
TutorialType mTutorialType;
@Nullable TutorialController mTutorialController = null;
RootSandboxLayout mRootView;
+ View mFingerDotView;
+ View mFakePreviousTaskView;
EdgeBackGestureHandler mEdgeBackGestureHandler;
NavBarGestureHandler mNavBarGestureHandler;
- private ImageView mFeedbackVideoView;
- private ImageView mGestureVideoView;
+ private ImageView mEdgeGestureVideoView;
- @Nullable private AnimatedVectorDrawable mTutorialAnimation = null;
- @Nullable private AnimatedVectorDrawable mGestureAnimation = null;
+ @Nullable private Animator mGestureAnimation = null;
+ @Nullable private AnimatedVectorDrawable mEdgeAnimation = null;
private boolean mIntroductionShown = false;
private boolean mFragmentStopped = false;
@@ -96,24 +99,26 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
return null;
}
- @Nullable Integer getFeedbackVideoResId(boolean forDarkMode) {
- return null;
- }
-
- @Nullable Integer getGestureVideoResId() {
+ @Nullable Integer getEdgeAnimationResId() {
return null;
}
@Nullable
- AnimatedVectorDrawable getTutorialAnimation() {
- return mTutorialAnimation;
- }
-
- @Nullable
- AnimatedVectorDrawable getGestureAnimation() {
+ Animator getGestureAnimation() {
return mGestureAnimation;
}
+ @Nullable
+ AnimatedVectorDrawable getEdgeAnimation() {
+ return mEdgeAnimation;
+ }
+
+
+ @Nullable
+ protected Animator createGestureAnimation() {
+ return null;
+ }
+
abstract TutorialController createController(TutorialType type);
abstract Class extends TutorialController> getControllerClass();
@@ -147,21 +152,22 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
return insets;
});
mRootView.setOnTouchListener(this);
- mFeedbackVideoView = mRootView.findViewById(R.id.gesture_tutorial_feedback_video);
- mGestureVideoView = mRootView.findViewById(R.id.gesture_tutorial_gesture_video);
+ mEdgeGestureVideoView = mRootView.findViewById(R.id.gesture_tutorial_edge_gesture_video);
+ mFingerDotView = mRootView.findViewById(R.id.gesture_tutorial_finger_dot);
+ mFakePreviousTaskView = mRootView.findViewById(
+ R.id.gesture_tutorial_fake_previous_task_view);
return mRootView;
}
@Override
public void onStop() {
super.onStop();
- releaseFeedbackVideoView();
- releaseGestureVideoView();
+ releaseFeedbackAnimation();
mFragmentStopped = true;
}
void initializeFeedbackVideoView() {
- if (!updateFeedbackVideo()) {
+ if (!updateFeedbackAnimation()) {
return;
}
@@ -176,87 +182,90 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
}
}
- boolean updateFeedbackVideo() {
- if (getContext() == null) {
+ boolean updateFeedbackAnimation() {
+ if (!updateEdgeAnimation()) {
return false;
}
- Integer feedbackVideoResId = getFeedbackVideoResId(Utilities.isDarkTheme(getContext()));
-
- if (feedbackVideoResId == null || !updateGestureVideo()) {
- return false;
- }
- mTutorialAnimation = (AnimatedVectorDrawable) getContext().getDrawable(feedbackVideoResId);
-
- if (mTutorialAnimation != null) {
- mTutorialAnimation.registerAnimationCallback(new Animatable2.AnimationCallback() {
-
- @Override
- public void onAnimationStart(Drawable drawable) {
- super.onAnimationStart(drawable);
-
- mFeedbackVideoView.setVisibility(View.VISIBLE);
- }
-
- @Override
- public void onAnimationEnd(Drawable drawable) {
- super.onAnimationEnd(drawable);
-
- releaseFeedbackVideoView();
- }
- });
- }
- mFeedbackVideoView.setImageDrawable(mTutorialAnimation);
-
- return true;
- }
-
- boolean updateGestureVideo() {
- Integer gestureVideoResId = getGestureVideoResId();
- if (gestureVideoResId == null || getContext() == null) {
- return false;
- }
- mGestureAnimation = (AnimatedVectorDrawable) getContext().getDrawable(gestureVideoResId);
+ mGestureAnimation = createGestureAnimation();
if (mGestureAnimation != null) {
- mGestureAnimation.registerAnimationCallback(new Animatable2.AnimationCallback() {
+ mGestureAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ mFingerDotView.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
+ mFingerDotView.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mFingerDotView.setVisibility(View.GONE);
+ }
+ });
+ }
+
+ return mGestureAnimation != null;
+ }
+
+ boolean updateEdgeAnimation() {
+ Integer edgeAnimationResId = getEdgeAnimationResId();
+ if (edgeAnimationResId == null || getContext() == null) {
+ return false;
+ }
+ mEdgeAnimation = (AnimatedVectorDrawable) getContext().getDrawable(edgeAnimationResId);
+
+ if (mEdgeAnimation != null) {
+ mEdgeAnimation.registerAnimationCallback(new Animatable2.AnimationCallback() {
@Override
public void onAnimationEnd(Drawable drawable) {
super.onAnimationEnd(drawable);
- mGestureAnimation.start();
+ mEdgeAnimation.start();
}
});
}
- mGestureVideoView.setImageDrawable(mGestureAnimation);
+ mEdgeGestureVideoView.setImageDrawable(mEdgeAnimation);
- return true;
+ return mEdgeAnimation != null;
}
- void releaseFeedbackVideoView() {
- if (mTutorialAnimation != null && mTutorialAnimation.isRunning()) {
- mTutorialAnimation.stop();
+ void releaseFeedbackAnimation() {
+ if (mTutorialController != null) {
+ mTutorialController.cancelQueuedGestureAnimation();
}
-
- mFeedbackVideoView.setVisibility(View.GONE);
- }
-
- void releaseGestureVideoView() {
if (mGestureAnimation != null && mGestureAnimation.isRunning()) {
- mGestureAnimation.stop();
+ mGestureAnimation.cancel();
+ }
+ if (mEdgeAnimation != null && mEdgeAnimation.isRunning()) {
+ mEdgeAnimation.stop();
}
- mGestureVideoView.setVisibility(View.GONE);
+ mEdgeGestureVideoView.setVisibility(View.GONE);
}
@Override
public void onResume() {
super.onResume();
+ releaseFeedbackAnimation();
if (mFragmentStopped && mTutorialController != null) {
mTutorialController.showFeedback();
mFragmentStopped = false;
} else {
- changeController(mTutorialType);
+ mRootView.getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ changeController(mTutorialType);
+ mRootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ }
+ });
}
}
@@ -292,6 +301,7 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
mEdgeBackGestureHandler.registerBackGestureAttemptCallback(mTutorialController);
mNavBarGestureHandler.registerNavBarGestureAttemptCallback(mTutorialController);
mTutorialType = tutorialType;
+
initializeFeedbackVideoView();
}
diff --git a/res/drawable/gesture_tutorial_motion_overview_light_mode.xml b/res/drawable/gesture_tutorial_motion_overview_light_mode.xml
deleted file mode 100644
index 75887c9352..0000000000
--- a/res/drawable/gesture_tutorial_motion_overview_light_mode.xml
+++ /dev/null
@@ -1,1587 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index cc5c5a39d3..5020127440 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -36,15 +36,6 @@
#E0E0E0
- #A0C2F9
- #6DA1FF
- #000000
- #f9f9f9
-
- #3C4043
- #FF000000
- #B7F29F
-
#FFF
#F1F3F4
#E0E0E0