Update KeyboardQuickSwitch for TAPL testing
- Added a res id to KeyboardQuickSwitchView for TAPL testing - Updated KeyboardQuickSwitch focus and scroll initialization - Logging KeyEvents for TAPL testing - Updated scrolling logic to wait for initial layout - Fixed activity leak in KeyboardQuickSwitchViewController Flag: ENABLE_KEYBOARD_QUICK_SWITCH Bug: 267520665 Test: TaplTestsKeyboardQuickSwitch Change-Id: I1d45d948c0e185504d994f7ef1d34f173c2243a9
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
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:id="@+id/keyboard_quick_switch_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/keyboard_quick_switch_margin_top"
|
||||
|
||||
@@ -46,6 +46,8 @@ import com.android.app.animation.Interpolators;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimatedFloat;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.shared.TestProtocol;
|
||||
import com.android.quickstep.util.GroupTask;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -360,11 +362,8 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
|
||||
OPEN_OUTLINE_INTERPOLATOR));
|
||||
}
|
||||
});
|
||||
if (currentFocusIndexOverride == -1) {
|
||||
initializeScroll(/* index= */ 0, /* shouldTruncateTarget= */ false);
|
||||
} else {
|
||||
animateFocusMove(-1, currentFocusIndexOverride);
|
||||
}
|
||||
animateFocusMove(-1, currentFocusIndexOverride == -1
|
||||
? Math.min(mContent.getChildCount(), 1) : currentFocusIndexOverride);
|
||||
displayedContent.setVisibility(VISIBLE);
|
||||
setVisibility(VISIBLE);
|
||||
requestFocus();
|
||||
@@ -413,7 +412,8 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
|
||||
// there are more tasks
|
||||
initializeScroll(
|
||||
firstVisibleTaskIndex,
|
||||
/* shouldTruncateTarget= */ firstVisibleTaskIndex != toIndex);
|
||||
/* shouldTruncateTarget= */ firstVisibleTaskIndex != 0
|
||||
&& firstVisibleTaskIndex != toIndex);
|
||||
} else if (toIndex > fromIndex || toIndex == 0) {
|
||||
// Scrolling to next task view
|
||||
if (mIsRtl) {
|
||||
@@ -438,6 +438,13 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
|
||||
focusAnimation.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
TestLogging.recordKeyEvent(
|
||||
TestProtocol.SEQUENCE_MAIN, "KeyboardQuickSwitchView key event", event);
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
return (mViewCallbacks != null
|
||||
@@ -454,56 +461,80 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
|
||||
return;
|
||||
}
|
||||
if (mIsRtl) {
|
||||
scrollRightTo(
|
||||
task, shouldTruncateTarget, /* smoothScroll= */ false);
|
||||
} else {
|
||||
scrollLeftTo(
|
||||
task, shouldTruncateTarget, /* smoothScroll= */ false);
|
||||
task,
|
||||
shouldTruncateTarget,
|
||||
/* smoothScroll= */ false,
|
||||
/* waitForLayout= */ true);
|
||||
} else {
|
||||
scrollRightTo(
|
||||
task,
|
||||
shouldTruncateTarget,
|
||||
/* smoothScroll= */ false,
|
||||
/* waitForLayout= */ true);
|
||||
}
|
||||
}
|
||||
|
||||
private void scrollRightTo(@NonNull View targetTask) {
|
||||
scrollRightTo(targetTask, /* shouldTruncateTarget= */ false, /* smoothScroll= */ true);
|
||||
scrollRightTo(
|
||||
targetTask,
|
||||
/* shouldTruncateTarget= */ false,
|
||||
/* smoothScroll= */ true,
|
||||
/* waitForLayout= */ false);
|
||||
}
|
||||
|
||||
private void scrollRightTo(
|
||||
@NonNull View targetTask, boolean shouldTruncateTarget, boolean smoothScroll) {
|
||||
@NonNull View targetTask,
|
||||
boolean shouldTruncateTarget,
|
||||
boolean smoothScroll,
|
||||
boolean waitForLayout) {
|
||||
if (!mDisplayingRecentTasks) {
|
||||
return;
|
||||
}
|
||||
if (smoothScroll && !shouldScroll(targetTask, shouldTruncateTarget)) {
|
||||
return;
|
||||
}
|
||||
int scrollTo = targetTask.getLeft() - mSpacing
|
||||
+ (shouldTruncateTarget ? targetTask.getWidth() / 2 : 0);
|
||||
// Scroll so that the focused task is to the left of the list
|
||||
if (smoothScroll) {
|
||||
mScrollView.smoothScrollTo(scrollTo, 0);
|
||||
} else {
|
||||
mScrollView.scrollTo(scrollTo, 0);
|
||||
}
|
||||
runScrollCommand(waitForLayout, () -> {
|
||||
int scrollTo = targetTask.getLeft() - mSpacing
|
||||
+ (shouldTruncateTarget ? targetTask.getWidth() / 2 : 0);
|
||||
// Scroll so that the focused task is to the left of the list
|
||||
if (smoothScroll) {
|
||||
mScrollView.smoothScrollTo(scrollTo, 0);
|
||||
} else {
|
||||
mScrollView.scrollTo(scrollTo, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void scrollLeftTo(@NonNull View targetTask) {
|
||||
scrollLeftTo(targetTask, /* shouldTruncateTarget= */ false, /* smoothScroll= */ true);
|
||||
scrollLeftTo(
|
||||
targetTask,
|
||||
/* shouldTruncateTarget= */ false,
|
||||
/* smoothScroll= */ true,
|
||||
/* waitForLayout= */ false);
|
||||
}
|
||||
|
||||
private void scrollLeftTo(
|
||||
@NonNull View targetTask, boolean shouldTruncateTarget, boolean smoothScroll) {
|
||||
@NonNull View targetTask,
|
||||
boolean shouldTruncateTarget,
|
||||
boolean smoothScroll,
|
||||
boolean waitForLayout) {
|
||||
if (!mDisplayingRecentTasks) {
|
||||
return;
|
||||
}
|
||||
if (smoothScroll && !shouldScroll(targetTask, shouldTruncateTarget)) {
|
||||
return;
|
||||
}
|
||||
int scrollTo = targetTask.getRight() + mSpacing - mScrollView.getWidth()
|
||||
- (shouldTruncateTarget ? targetTask.getWidth() / 2 : 0);
|
||||
// Scroll so that the focused task is to the right of the list
|
||||
if (smoothScroll) {
|
||||
mScrollView.smoothScrollTo(scrollTo, 0);
|
||||
} else {
|
||||
mScrollView.scrollTo(scrollTo, 0);
|
||||
}
|
||||
runScrollCommand(waitForLayout, () -> {
|
||||
int scrollTo = targetTask.getRight() + mSpacing - mScrollView.getWidth()
|
||||
- (shouldTruncateTarget ? targetTask.getWidth() / 2 : 0);
|
||||
// Scroll so that the focused task is to the right of the list
|
||||
if (smoothScroll) {
|
||||
mScrollView.smoothScrollTo(scrollTo, 0);
|
||||
} else {
|
||||
mScrollView.scrollTo(scrollTo, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean shouldScroll(@NonNull View targetTask, boolean shouldTruncateTarget) {
|
||||
@@ -514,6 +545,21 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
|
||||
return isTargetTruncated && !shouldTruncateTarget;
|
||||
}
|
||||
|
||||
private void runScrollCommand(boolean waitForLayout, @NonNull Runnable scrollCommand) {
|
||||
if (!waitForLayout) {
|
||||
scrollCommand.run();
|
||||
return;
|
||||
}
|
||||
mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(
|
||||
new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
scrollCommand.run();
|
||||
mScrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected KeyboardQuickSwitchTaskView getTaskAt(int index) {
|
||||
return !mDisplayingRecentTasks || index < 0 || index >= mContent.getChildCount()
|
||||
|
||||
@@ -24,7 +24,7 @@ import android.view.View;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorListeners;
|
||||
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
|
||||
import com.android.launcher3.taskbar.overlay.TaskbarOverlayDragLayer;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
@@ -92,27 +92,19 @@ public class KeyboardQuickSwitchViewController {
|
||||
|
||||
protected void closeQuickSwitchView(boolean animate) {
|
||||
if (mCloseAnimation != null) {
|
||||
if (animate) {
|
||||
// Let currently-running animation finish.
|
||||
return;
|
||||
} else {
|
||||
mCloseAnimation.cancel();
|
||||
// Let currently-running animation finish.
|
||||
if (!animate) {
|
||||
mCloseAnimation.end();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!animate) {
|
||||
mCloseAnimation = null;
|
||||
onCloseComplete();
|
||||
return;
|
||||
}
|
||||
mCloseAnimation = mKeyboardQuickSwitchView.getCloseAnimation();
|
||||
|
||||
mCloseAnimation.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
mCloseAnimation = null;
|
||||
onCloseComplete();
|
||||
}
|
||||
});
|
||||
mCloseAnimation.addListener(AnimatorListeners.forEndCallback(this::onCloseComplete));
|
||||
mCloseAnimation.start();
|
||||
}
|
||||
|
||||
@@ -160,6 +152,7 @@ public class KeyboardQuickSwitchViewController {
|
||||
}
|
||||
|
||||
private void onCloseComplete() {
|
||||
mCloseAnimation = null;
|
||||
mOverlayContext.getDragLayer().removeView(mKeyboardQuickSwitchView);
|
||||
mControllerCallbacks.onCloseComplete();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user