Add a no recent tasks message to the keyboard quick switch view

Flag: ENABLE_KEYBOARD_QUICK_SWITCH
Fixes: 280652620
Test: launched the keyboard quick switch with 0, <=6 and >6 tasks launched
Change-Id: I560707645b83b79ba2203460e62e4c540f5da421
This commit is contained in:
Schneider Victor-tulias
2023-05-10 11:43:25 -07:00
parent 8f23be7b6f
commit b29355c192
8 changed files with 88 additions and 19 deletions

View File

@@ -41,8 +41,8 @@
android:layout_height="@dimen/keyboard_quick_switch_recents_icon_size"
android:layout_marginBottom="8dp"
android:src="@drawable/ic_empty_recents"
android:tint="?androidprv:attr/materialColorOnSurface"
app:tint="?androidprv:attr/materialColorOnSurface"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/text"
@@ -50,7 +50,7 @@
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
style="@style/KeyboardQuickSwitchOverview"
style="@style/KeyboardQuickSwitchText"
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@@ -15,6 +15,7 @@
-->
<com.android.launcher3.taskbar.KeyboardQuickSwitchView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -27,6 +28,43 @@
android:focusableInTouchMode="true"
app:layout_ignoreInsets="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/no_recent_items_pane"
android:layout_width="match_parent"
android:layout_height="@dimen/keyboard_quick_switch_taskview_height"
android:paddingVertical="@dimen/keyboard_quick_switch_view_spacing"
android:alpha="0"
android:visibility="gone">
<ImageView
android:id="@+id/no_recent_items_icon"
android:layout_width="@dimen/keyboard_quick_switch_no_recent_items_icon_size"
android:layout_height="@dimen/keyboard_quick_switch_no_recent_items_icon_size"
android:layout_marginBottom="@dimen/keyboard_quick_switch_no_recent_items_icon_margin"
android:src="@drawable/ic_empty_recents"
android:tint="?androidprv:attr/materialColorOnSurfaceInverse"
android:importantForAccessibility="no"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/no_recent_items_text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
style="@style/KeyboardQuickSwitchText.OnBackground"
android:id="@+id/no_recent_items_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/recents_empty_message"
app:layout_constraintTop_toBottomOf="@id/no_recent_items_icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<HorizontalScrollView
android:id="@+id/scroll_view"
android:layout_width="wrap_content"
@@ -34,7 +72,7 @@
android:fillViewport="true"
android:scrollbars="none"
android:alpha="0"
android:visibility="invisible"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"

View File

@@ -379,4 +379,6 @@
<dimen name="keyboard_quick_switch_split_view_spacing">2dp</dimen>
<dimen name="keyboard_quick_switch_view_radius">28dp</dimen>
<dimen name="keyboard_quick_switch_task_view_radius">16dp</dimen>
<dimen name="keyboard_quick_switch_no_recent_items_icon_size">24dp</dimen>
<dimen name="keyboard_quick_switch_no_recent_items_icon_margin">8dp</dimen>
</resources>

View File

@@ -295,6 +295,7 @@
=1{Show # more app.}
other{Show # more apps.}
}</string>
<!-- Accessibility label for quick switch tiles showing split tasks [CHAR LIMIT=NONE] -->
<string name="quick_switch_split_task"><xliff:g id="app_name_1" example="Chrome">%1$s</xliff:g> and <xliff:g id="app_name_2" example="Gmail">%2$s</xliff:g></string>
</resources>

View File

@@ -215,13 +215,17 @@
<item name="android:textSize">14sp</item>
</style>
<style name="KeyboardQuickSwitchOverview">
<style name="KeyboardQuickSwitchText">
<item name="fontFamily">google-sans-text</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
<item name="lineHeight">20sp</item>
</style>
<style name="KeyboardQuickSwitchText.OnBackground" parent="KeyboardQuickSwitchText">
<item name="android:textColor">?androidprv:attr/materialColorOnSurfaceInverse</item>
</style>
<style name="GestureTutorialActivity"
parent="@style/AppTheme">
<item name="background">@android:color/transparent</item>

View File

@@ -129,8 +129,8 @@ public final class KeyboardQuickSwitchController implements
*/
int launchFocusedTask() {
// Return -1 so that the RecentsView is not incorrectly opened when the user closes the
// quick switch view by tapping the screen.
return mQuickSwitchViewController == null
// quick switch view by tapping the screen or when there are no recent tasks.
return mQuickSwitchViewController == null || mTasks.isEmpty()
? -1 : mQuickSwitchViewController.launchFocusedTask();
}

View File

@@ -85,6 +85,8 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
private final AnimatedFloat mOutlineAnimationProgress = new AnimatedFloat(
this::invalidateOutline);
private boolean mDisplayingRecentTasks;
private View mNoRecentItemsPane;
private HorizontalScrollView mScrollView;
private ConstraintLayout mContent;
@@ -119,6 +121,7 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mNoRecentItemsPane = findViewById(R.id.no_recent_items_pane);
mScrollView = findViewById(R.id.scroll_view);
mContent = findViewById(R.id.content);
@@ -204,10 +207,6 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
boolean updateTasks,
int currentFocusIndexOverride,
@NonNull KeyboardQuickSwitchViewController.ViewCallbacks viewCallbacks) {
if (groupTasks.isEmpty()) {
// Do not show the quick switch view.
return;
}
mViewCallbacks = viewCallbacks;
Resources resources = context.getResources();
int width = resources.getDimensionPixelSize(R.dimen.keyboard_quick_switch_taskview_width);
@@ -237,6 +236,7 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
resources.getString(R.string.quick_switch_overflow),
Locale.getDefault()).format(args));
}
mDisplayingRecentTasks = !groupTasks.isEmpty();
getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@@ -262,13 +262,16 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
alphaAnimation.setDuration(ALPHA_ANIMATION_DURATION_MS);
closeAnimation.play(alphaAnimation);
View displayedContent = mDisplayingRecentTasks ? mScrollView : mNoRecentItemsPane;
Animator translationYAnimation = ObjectAnimator.ofFloat(
mScrollView, TRANSLATION_Y, 0, -Utilities.dpToPx(CONTENT_START_TRANSLATION_Y_DP));
displayedContent,
TRANSLATION_Y,
0, -Utilities.dpToPx(CONTENT_START_TRANSLATION_Y_DP));
translationYAnimation.setDuration(CONTENT_TRANSLATION_Y_ANIMATION_DURATION_MS);
translationYAnimation.setInterpolator(CLOSE_TRANSLATION_Y_INTERPOLATOR);
closeAnimation.play(translationYAnimation);
Animator contentAlphaAnimation = ObjectAnimator.ofFloat(mScrollView, ALPHA, 1f, 0f);
Animator contentAlphaAnimation = ObjectAnimator.ofFloat(displayedContent, ALPHA, 1f, 0f);
contentAlphaAnimation.setDuration(CONTENT_ALPHA_ANIMATION_DURATION_MS);
closeAnimation.play(contentAlphaAnimation);
@@ -300,19 +303,24 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
alphaAnimation.setDuration(ALPHA_ANIMATION_DURATION_MS);
mOpenAnimation.play(alphaAnimation);
View displayedContent = mDisplayingRecentTasks ? mScrollView : mNoRecentItemsPane;
Animator translationXAnimation = ObjectAnimator.ofFloat(
mScrollView, TRANSLATION_X, -Utilities.dpToPx(CONTENT_START_TRANSLATION_X_DP), 0);
displayedContent,
TRANSLATION_X,
-Utilities.dpToPx(CONTENT_START_TRANSLATION_X_DP), 0);
translationXAnimation.setDuration(CONTENT_TRANSLATION_X_ANIMATION_DURATION_MS);
translationXAnimation.setInterpolator(OPEN_TRANSLATION_X_INTERPOLATOR);
mOpenAnimation.play(translationXAnimation);
Animator translationYAnimation = ObjectAnimator.ofFloat(
mScrollView, TRANSLATION_Y, -Utilities.dpToPx(CONTENT_START_TRANSLATION_Y_DP), 0);
displayedContent,
TRANSLATION_Y,
-Utilities.dpToPx(CONTENT_START_TRANSLATION_Y_DP), 0);
translationYAnimation.setDuration(CONTENT_TRANSLATION_Y_ANIMATION_DURATION_MS);
translationYAnimation.setInterpolator(OPEN_TRANSLATION_Y_INTERPOLATOR);
mOpenAnimation.play(translationYAnimation);
Animator contentAlphaAnimation = ObjectAnimator.ofFloat(mScrollView, ALPHA, 0f, 1f);
Animator contentAlphaAnimation = ObjectAnimator.ofFloat(displayedContent, ALPHA, 0f, 1f);
contentAlphaAnimation.setStartDelay(CONTENT_ALPHA_ANIMATION_START_DELAY_MS);
contentAlphaAnimation.setDuration(CONTENT_ALPHA_ANIMATION_DURATION_MS);
mOpenAnimation.play(contentAlphaAnimation);
@@ -353,7 +361,7 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
} else {
animateFocusMove(-1, currentFocusIndexOverride);
}
mScrollView.setVisibility(VISIBLE);
displayedContent.setVisibility(VISIBLE);
setVisibility(VISIBLE);
requestFocus();
}
@@ -372,6 +380,9 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
}
protected void animateFocusMove(int fromIndex, int toIndex) {
if (!mDisplayingRecentTasks) {
return;
}
KeyboardQuickSwitchTaskView focusedTask = getTaskAt(toIndex);
if (focusedTask == null) {
return;
@@ -425,11 +436,15 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
return (mViewCallbacks != null && mViewCallbacks.onKeyUp(keyCode, event, mIsRtl))
return (mViewCallbacks != null
&& mViewCallbacks.onKeyUp(keyCode, event, mIsRtl, mDisplayingRecentTasks))
|| super.onKeyUp(keyCode, event);
}
private void initializeScroll(int index, boolean shouldTruncateTarget) {
if (!mDisplayingRecentTasks) {
return;
}
View task = getTaskAt(index);
if (task == null) {
return;
@@ -449,6 +464,9 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
private void scrollRightTo(
@NonNull View targetTask, boolean shouldTruncateTarget, boolean smoothScroll) {
if (!mDisplayingRecentTasks) {
return;
}
if (smoothScroll && !shouldScroll(targetTask, shouldTruncateTarget)) {
return;
}
@@ -468,6 +486,9 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
private void scrollLeftTo(
@NonNull View targetTask, boolean shouldTruncateTarget, boolean smoothScroll) {
if (!mDisplayingRecentTasks) {
return;
}
if (smoothScroll && !shouldScroll(targetTask, shouldTruncateTarget)) {
return;
}
@@ -491,7 +512,7 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
@Nullable
protected KeyboardQuickSwitchTaskView getTaskAt(int index) {
return index < 0 || index >= mContent.getChildCount()
return !mDisplayingRecentTasks || index < 0 || index >= mContent.getChildCount()
? null : (KeyboardQuickSwitchTaskView) mContent.getChildAt(index);
}
}

View File

@@ -169,7 +169,7 @@ public class KeyboardQuickSwitchViewController {
class ViewCallbacks {
boolean onKeyUp(int keyCode, KeyEvent event, boolean isRTL) {
boolean onKeyUp(int keyCode, KeyEvent event, boolean isRTL, boolean allowTraversal) {
if (keyCode != KeyEvent.KEYCODE_TAB
&& keyCode != KeyEvent.KEYCODE_DPAD_RIGHT
&& keyCode != KeyEvent.KEYCODE_DPAD_LEFT
@@ -181,6 +181,9 @@ public class KeyboardQuickSwitchViewController {
closeQuickSwitchView(true);
return true;
}
if (!allowTraversal) {
return false;
}
boolean traverseBackwards = (keyCode == KeyEvent.KEYCODE_TAB && event.isShiftPressed())
|| (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT && !isRTL)
|| (keyCode == KeyEvent.KEYCODE_DPAD_LEFT && isRTL);