桌面taskbar 上滑、 长按
手势导航下判断是否是上滑显示taskbar还是固定显示taskbar,主要受SharedPreferences TASKBAR_PINNING对应的值影响
mIsTaskbarPinned = LauncherPrefs.get(displayInfoContext).get(TASKBAR_PINNING);// taskbar是否固定显示,为false则是上滑显示清扫,为true则是长按底部边缘
com/android/launcher3/util/DisplayController.java
public boolean isTransientTaskbar() {
if (navigationMode != NavigationMode.NO_BUTTON) { // 判断是否是手势导航
return false;
}
if (Utilities.isRunningInTestHarness()) {
// TODO(b/258604917): Once ENABLE_TASKBAR_PINNING is enabled, remove usage of
// sTransientTaskbarStatusForTests and update test to directly
// toggle shared preference to switch transient taskbar on/off.
return sTransientTaskbarStatusForTests;
}
if (enableTaskbarPinning()) {
if (mIsInDesktopMode) {
return !mIsTaskbarPinnedInDesktopMode;
}
return !mIsTaskbarPinned; // 判断taskbar是否是固定显示的
}
return true;
}
1、长按小白条弹出taskbar,固定显示taskbar
quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
@Override
public void onMotionEvent(MotionEvent ev) {
mLongPressDetector.onTouchEvent(ev);
.............
}
mLongPressDetector = new GestureDetector(context, new SimpleOnGestureListener() {
@Override
public void onLongPress(MotionEvent motionEvent) {
onLongPressDetected(motionEvent);
}
});
private void onLongPressDetected(MotionEvent motionEvent) {
if (mTaskbarActivityContext != null
&& isInArea(motionEvent.getRawX())
&& !mIsTransientTaskbar) {
boolean taskBarPressed = mTaskbarActivityContext.onLongPressToUnstashTaskbar();
if (taskBarPressed) {
setActive(motionEvent);
}
}
}
quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
public boolean onLongPressToUnstashTaskbar() {
return mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
}
quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
public boolean onLongPressToUnstashTaskbar() {
if (!isStashed()) {
// We only listen for long press on the nav region to unstash the taskbar. To stash the
// taskbar, we use an OnLongClickListener on TaskbarView instead.
return false;
}
if (!canCurrentlyManuallyUnstash()) {
return false;
}
if (updateAndAnimateIsManuallyStashedInApp(false)) {
mControllers.taskbarActivityContext.getDragLayer().performHapticFeedback(LONG_PRESS);
return true;
}
return false;
}
quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
public boolean updateAndAnimateIsManuallyStashedInApp(boolean isManuallyStashedInApp) {
if (!supportsManualStashing()) {
return false;
}
if (hasAnyFlag(FLAG_STASHED_IN_APP_MANUAL) != isManuallyStashedInApp) {
mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_KEY, isManuallyStashedInApp).apply();
updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
applyState();
return true;
}
return false;
}
public void applyState() {
applyState(hasAnyFlag(FLAG_IN_SETUP) ? 0 : TASKBAR_STASH_DURATION);
}
public void applyState(long duration) {
Animator animator = createApplyStateAnimator(duration);
if (animator != null) {
animator.start();
}
}
2025-02-26 08:41:09.080 26567-26567 TaskbarStashController com.android.launcher D createApplyStateAnimator: duration=300; mState=1; java.lang.Throwable
at com.android.launcher3.taskbar.TaskbarStashController.createApplyStateAnimator(TaskbarStashController.java:1140)
at com.android.launcher3.taskbar.TaskbarStashController.applyState(TaskbarStashController.java:1120)
at com.android.launcher3.taskbar.TaskbarStashController.applyState(TaskbarStashController.java:1116)
at com.android.launcher3.taskbar.TaskbarStashController.updateAndAnimateIsManuallyStashedInApp(TaskbarStashController.java:1695)
at com.android.launcher3.taskbar.TaskbarStashController.onLongPressToUnstashTaskbar(TaskbarStashController.java:1723)
at com.android.launcher3.taskbar.TaskbarActivityContext.onLongPressToUnstashTaskbar(TaskbarActivityContext.java:1727)
at com.android.quickstep.inputconsumers.TaskbarUnstashInputConsumer.onLongPressDetected(TaskbarUnstashInputConsumer.java:520)
at com.android.quickstep.inputconsumers.TaskbarUnstashInputConsumer.access$000(TaskbarUnstashInputConsumer.java:71)
at com.android.quickstep.inputconsumers.TaskbarUnstashInputConsumer$1.onLongPress(TaskbarUnstashInputConsumer.java:152)
at android.view.GestureDetector.dispatchLongPress(GestureDetector.java:934)
at android.view.GestureDetector.-$$Nest$mdispatchLongPress(Unknown Source:0)
at android.view.GestureDetector$GestureHandler.handleMessage(GestureDetector.java:334)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loopOnce(Looper.java:233)
at android.os.Looper.loop(Looper.java:318)
at android.app.ActivityThread.main(ActivityThread.java:9318)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:892)
2、长按taskbar显示小白条,可以通过上滑显示taskbar
com/android/launcher3/taskbar/TaskbarView.java
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
targetGravity = -1;
if (isShown()) {
Rect rect = getIconLayoutBounds();
if (event.getY() > rect.top && event.getY() < rect.bottom) {
if (event.getX() < rect.left) {
targetGravity = isLayoutRtl() ? Gravity.END : Gravity.START;
} else if (event.getX() > rect.right) {
targetGravity = isLayoutRtl() ? Gravity.START : Gravity.END;
}
}
}
}
if (mControllerCallbacks.onTouchEvent(event)) {
int oldAction = event.getAction();
try {
event.setAction(MotionEvent.ACTION_CANCEL);
return super.onTouchEvent(event);
} finally {
event.setAction(oldAction);
}
}
return super.onTouchEvent(event);
}
com/android/launcher3/taskbar/TaskbarViewCallbacks.java
public boolean onTouchEvent(MotionEvent motionEvent) {
final float x = motionEvent.getRawX();
final float y = motionEvent.getRawY();
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = x;
mDownY = y;
mControllers.taskbarStashController.startStashHint(/* animateForward = */ true);
mCanceledStashHint = false;
postCheckForLongPress();
break;
case MotionEvent.ACTION_MOVE:
if (!mCanceledStashHint && squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop) {
mControllers.taskbarStashController.startStashHint(/* animateForward= */ false);
mCanceledStashHint = true;
cancelLongPress();
return true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (!mCanceledStashHint) {
mControllers.taskbarStashController.startStashHint( /* animateForward= */ false);
cancelLongPress();
}
break;
}
return false;
}
2025-02-26 08:43:38.437 26567-26567 TaskbarStashController com.android.launcher D createApplyStateAnimator: duration=300; mState=65537; java.lang.Throwable
at com.android.launcher3.taskbar.TaskbarStashController.createApplyStateAnimator(TaskbarStashController.java:1140)
at com.android.launcher3.taskbar.TaskbarStashController.applyState(TaskbarStashController.java:1120)
at com.android.launcher3.taskbar.TaskbarStashController.applyState(TaskbarStashController.java:1116)
at com.android.launcher3.taskbar.TaskbarStashController.updateAndAnimateIsManuallyStashedInApp(TaskbarStashController.java:1695)
at com.android.launcher3.taskbar.TaskbarViewCallbacks.lambda$getBackgroundOnLongClickListener$2$com-android-launcher3-taskbar-TaskbarViewCallbacks(TaskbarViewCallbacks.java:98)
at com.android.launcher3.taskbar.TaskbarViewCallbacks$$ExternalSyntheticLambda2.onLongClick(D8$$SyntheticClass:0)
at com.android.launcher3.taskbar.TaskbarViewCallbacks.lambda$postCheckForLongPress$3$com-android-launcher3-taskbar-TaskbarViewCallbacks(TaskbarViewCallbacks.java:168)
at com.android.launcher3.taskbar.TaskbarViewCallbacks$$ExternalSyntheticLambda1.run(D8$$SyntheticClass:0)
at android.os.Handler.handleCallback(Handler.java:959)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loopOnce(Looper.java:233)
at android.os.Looper.loop(Looper.java:318)
at android.app.ActivityThread.main(ActivityThread.java:9318)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:892)
com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
public void onMotionEvent(MotionEvent ev) {
if (enableScalingRevealHomeAnimation() && mIsTransientTaskbar) {
checkVelocityForTaskbarBackground(ev);
}
if (mState != STATE_ACTIVE) {
boolean isStashedTaskbarHovered = isMouseEvent(ev) && isStashedTaskbarHovered((int) ev.getX(), (int) ev.getY());
// Only show the transient task bar if the touch events are on the screen.
if (!isTrackpadMotionEvent(ev)) {
final float x = ev.getRawX();
final float y = ev.getRawY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = ev.getPointerId(0);
mDownPos.set(ev.getX(), ev.getY());
mLastPos.set(mDownPos);
mHasPassedTaskbarNavThreshold = false;
mTaskbarActivityContext.setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_TOUCHING, true);
if (mTransitionCallback != null && !mIsTaskbarAllAppsOpen) {
mTransitionCallback.onActionDown();
}
if (mIsTransientTaskbar && isInBubbleBarArea(x)) {
mIsInBubbleBarArea = true;
}
break;
case MotionEvent.ACTION_POINTER_UP:
int ptrIdx = ev.getActionIndex();
int ptrId = ev.getPointerId(ptrIdx);
if (ptrId == mActivePointerId) {
final int newPointerIdx = ptrIdx == 0 ? 1 : 0;
mDownPos.set(
ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x),
ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y));
mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
mActivePointerId = ev.getPointerId(newPointerIdx);
}
break;
case MotionEvent.ACTION_MOVE:
int pointerIndex = ev.findPointerIndex(mActivePointerId);
if (pointerIndex == INVALID_POINTER_ID) {
break;
}
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
float dX = mLastPos.x - mDownPos.x;
float dY = mLastPos.y - mDownPos.y;
if (!mIsPassedBubbleBarSlop && mIsInBubbleBarArea) {
boolean passedSlop = Math.abs(dY) > mTouchSlop || Math.abs(dX) > mTouchSlop;
if (passedSlop) {
mIsPassedBubbleBarSlop = true;
mIsVerticalGestureOverBubbleBar = Math.abs(dY) > Math.abs(dX);
if (mIsVerticalGestureOverBubbleBar) {
setActive(ev);
}
}
}
if (mIsTransientTaskbar) {
boolean passedTaskbarNavThreshold = dY < 0 && Math.abs(dY) >= mTaskbarNavThreshold;
if (!mHasPassedTaskbarNavThreshold && passedTaskbarNavThreshold && !mGestureState.isInExtendedSlopRegion()) {
mHasPassedTaskbarNavThreshold = true;
if (mIsInBubbleBarArea && mIsVerticalGestureOverBubbleBar) {
mTaskbarActivityContext.onSwipeToOpenBubblebar(); // 上滑显示BubbleBar,最终调用掉SystemUI中去显示
} else {
mTaskbarActivityContext.onSwipeToUnstashTaskbar(); // 上滑显示taskbar并做动画
}
}
if (dY < 0) {
dY = -OverScroll.dampedScroll(-dY, mTaskbarNavThresholdY);
if (mTransitionCallback != null && !mIsTaskbarAllAppsOpen) {
mTransitionCallback.onActionMove(dY);
}
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
cleanupAfterMotionEvent();
break;
case MotionEvent.ACTION_BUTTON_RELEASE:
if (isStashedTaskbarHovered) {
mOverviewCommandHelper.addCommand(OverviewCommandHelper.TYPE_HOME);
}
break;
}
}
boolean isMovingInBubbleBarArea = mIsInBubbleBarArea && ev.getAction() == ACTION_MOVE;
if (!isStashedTaskbarHovered) {
// if we're moving in the bubble bar area but we haven't passed the slop yet, don't
// propagate to the delegate, until we can determine the direction of the gesture.
if (!isMovingInBubbleBarArea || mIsPassedBubbleBarSlop) {
mDelegate.onMotionEvent(ev);
}
}
} else if (mIsVerticalGestureOverBubbleBar) {
// if we get here then this gesture is a vertical swipe over the bubble bar.
// we're also active and there's no need to delegate any additional motion events. the
// rest of the gesture will be handled here.
switch (ev.getAction()) {
case ACTION_MOVE:
int pointerIndex = ev.findPointerIndex(mActivePointerId);
if (pointerIndex == INVALID_POINTER_ID) {
break;
}
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
float dY = mLastPos.y - mDownPos.y;
// bubble bar swipe gesture uses the same threshold as the taskbar.
boolean passedTaskbarNavThreshold = dY < 0 && Math.abs(dY) >= mTaskbarNavThreshold;
if (!mHasPassedTaskbarNavThreshold && passedTaskbarNavThreshold) {
mHasPassedTaskbarNavThreshold = true;
mTaskbarActivityContext.onSwipeToOpenBubblebar(); // 上滑显示BubbleBar,最终调用掉SystemUI中去显示
}
break;
case ACTION_UP:
case ACTION_CANCEL:
cleanupAfterMotionEvent();
break;
}
}
}
public void onSwipeToUnstashTaskbar() {
boolean wasStashed = mControllers.taskbarStashController.isStashed();
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(/* stash= */ false); // 上滑显示taskbar并做动画
boolean isStashed = mControllers.taskbarStashController.isStashed();
if (isStashed != wasStashed) {
VibratorWrapper.INSTANCE.get(this).vibrateForTaskbarUnstash();
}
mControllers.taskbarEduTooltipController.hide();
}