Files
Flexera-Launcher/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java
T
vadimt f6ef879cf4 Moving all sources that are shared between Launcher and TAPL in one directory
This will help SysUI test team (who uses TAPL) to set up Gradle build for their tests.

Bug: 202567877, 234414088
Test: presubmit
Change-Id: I3d923ea4b54d1a4c3d2b345be09692727d30433e
2022-07-27 20:18:46 +00:00

174 lines
6.5 KiB
Java

/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.uioverrides.touchcontrollers;
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL_APPS_EDU;
import static com.android.launcher3.AbstractFloatingView.getOpenView;
import static com.android.launcher3.LauncherState.HINT_STATE_TWO_BUTTON;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import android.animation.ValueAnimator;
import android.os.SystemClock;
import android.view.MotionEvent;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.AllAppsEduView;
/**
* Touch controller for handling edge swipes in 2-button mode
*/
public class TwoButtonNavbarTouchController extends AbstractStateChangeTouchController {
private static final int MAX_NUM_SWIPES_TO_TRIGGER_EDU = 3;
private static final String TAG = "2BtnNavbarTouchCtrl";
private final boolean mIsTransposed;
// If true, we will finish the current animation instantly on second touch.
private boolean mFinishFastOnSecondTouch;
private int mContinuousTouchCount = 0;
public TwoButtonNavbarTouchController(Launcher l) {
super(l, l.getDeviceProfile().isVerticalBarLayout()
? SingleAxisSwipeDetector.HORIZONTAL : SingleAxisSwipeDetector.VERTICAL);
mIsTransposed = l.getDeviceProfile().isVerticalBarLayout();
}
@Override
protected boolean canInterceptTouch(MotionEvent ev) {
boolean canIntercept = canInterceptTouchInternal(ev);
if (!canIntercept) {
mContinuousTouchCount = 0;
}
return canIntercept;
}
private boolean canInterceptTouchInternal(MotionEvent ev) {
if (mCurrentAnimation != null) {
if (mFinishFastOnSecondTouch) {
mCurrentAnimation.getAnimationPlayer().end();
}
// If we are already animating from a previous state, we can intercept.
return true;
}
if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
return false;
}
if ((ev.getEdgeFlags() & EDGE_NAV_BAR) == 0) {
return false;
}
if (!mIsTransposed && mLauncher.isInState(OVERVIEW)) {
return true;
}
return mLauncher.isInState(NORMAL);
}
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
boolean intercept = super.onControllerInterceptTouchEvent(ev);
return intercept;
}
@Override
protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
if (mIsTransposed) {
boolean draggingFromNav =
mLauncher.getDeviceProfile().isSeascape() == isDragTowardPositive;
return draggingFromNav ? HINT_STATE_TWO_BUTTON : NORMAL;
} else {
LauncherState startState = mStartState != null ? mStartState : fromState;
return isDragTowardPositive ^ (startState == OVERVIEW) ? HINT_STATE_TWO_BUTTON : NORMAL;
}
}
@Override
protected void onReinitToState(LauncherState newToState) {
super.onReinitToState(newToState);
}
@Override
protected void updateSwipeCompleteAnimation(ValueAnimator animator, long expectedDuration,
LauncherState targetState, float velocity, boolean isFling) {
super.updateSwipeCompleteAnimation(animator, expectedDuration, targetState,
velocity, isFling);
mFinishFastOnSecondTouch = !mIsTransposed && mFromState == NORMAL;
if (targetState == HINT_STATE_TWO_BUTTON) {
// We were going to HINT_STATE_TWO_BUTTON, but end that animation immediately so we go
// to OVERVIEW instead.
animator.setDuration(0);
}
}
@Override
protected float getShiftRange() {
// Should be in sync with TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT
return LayoutUtils.getDefaultSwipeHeight(mLauncher, mLauncher.getDeviceProfile());
}
@Override
protected float initCurrentAnimation() {
float range = getShiftRange();
long maxAccuracy = (long) (2 * range);
mCurrentAnimation = mLauncher.getStateManager().createAnimationToNewWorkspace(mToState,
maxAccuracy);
return (mLauncher.getDeviceProfile().isSeascape() ? 1 : -1) / range;
}
@Override
protected void updateProgress(float fraction) {
super.updateProgress(fraction);
// We have reached HINT_STATE, end the gesture now to go to OVERVIEW.
if (fraction >= 1 && mToState == HINT_STATE_TWO_BUTTON) {
final long now = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(now, now,
MotionEvent.ACTION_UP, 0.0f, 0.0f, 0);
mDetector.onTouchEvent(event);
event.recycle();
}
}
@Override
protected void onSwipeInteractionCompleted(LauncherState targetState) {
super.onSwipeInteractionCompleted(targetState);
if (!mIsTransposed) {
mContinuousTouchCount++;
}
if (mStartState == NORMAL && targetState == HINT_STATE_TWO_BUTTON) {
SystemUiProxy.INSTANCE.get(mLauncher).onOverviewShown(true, TAG);
} else if (targetState == NORMAL
&& mContinuousTouchCount >= MAX_NUM_SWIPES_TO_TRIGGER_EDU) {
mContinuousTouchCount = 0;
if (getOpenView(mLauncher, TYPE_ALL_APPS_EDU) == null) {
AllAppsEduView.show(mLauncher);
}
}
mStartState = null;
}
}