Merge "Base: Predictive Back, add support for large screens when swiping" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b067a895d1
@@ -54,10 +54,42 @@ public interface BackAnimation {
|
||||
void setTriggerBack(boolean triggerBack);
|
||||
|
||||
/**
|
||||
* Sets the threshold values that defining edge swipe behavior.
|
||||
* @param progressThreshold the max threshold to keep linear progressing back animation.
|
||||
* Sets the threshold values that define edge swipe behavior.<br>
|
||||
* <br>
|
||||
* <h1>How does {@code nonLinearFactor} work?</h1>
|
||||
* <pre>
|
||||
* screen screen screen
|
||||
* width width width
|
||||
* |——————| |————————————| |————————————————————|
|
||||
* A B A B C A
|
||||
* 1 +——————+—————+ 1 +————————————+ 1 +————————————+———————+
|
||||
* | / | | —/| | | —————/|
|
||||
* | / | | —/ | | ——/ |
|
||||
* | / | | —/ | | ——/ | |
|
||||
* | / | | —/ | | ——/ | |
|
||||
* | / | | —/ | | ——/ | |
|
||||
* |/ | |—/ | |—/ | |
|
||||
* 0 +————————————+ 0 +————————————+ 0 +————————————+———————+
|
||||
* B B B
|
||||
* </pre>
|
||||
* Three devices with different widths (smaller, equal, and wider) relative to the progress
|
||||
* threshold are shown in the graphs.<br>
|
||||
* - A is the width of the screen<br>
|
||||
* - B is the progress threshold (horizontal swipe distance where progress is linear)<br>
|
||||
* - C equals B + (A - B) * nonLinearFactor<br>
|
||||
* <br>
|
||||
* If A is less than or equal to B, {@code progress} for the swipe distance between:<br>
|
||||
* - [0, A] will scale linearly between [0, 1].<br>
|
||||
* If A is greater than B, {@code progress} for swipe distance between:<br>
|
||||
* - [0, B] will scale linearly between [0, B / C]<br>
|
||||
* - (B, A] will scale non-linearly and reach 1.
|
||||
*
|
||||
* @param linearDistance up to this distance progress continues linearly. B in the graph above.
|
||||
* @param maxDistance distance at which the progress will be 1f. A in the graph above.
|
||||
* @param nonLinearFactor This value is used to calculate the target if the screen is wider
|
||||
* than the progress threshold.
|
||||
*/
|
||||
void setSwipeThresholds(float progressThreshold);
|
||||
void setSwipeThresholds(float linearDistance, float maxDistance, float nonLinearFactor);
|
||||
|
||||
/**
|
||||
* Sets the system bar listener to control the system bar color.
|
||||
|
||||
@@ -301,9 +301,12 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSwipeThresholds(float progressThreshold) {
|
||||
public void setSwipeThresholds(
|
||||
float linearDistance,
|
||||
float maxDistance,
|
||||
float nonLinearFactor) {
|
||||
mShellExecutor.execute(() -> BackAnimationController.this.setSwipeThresholds(
|
||||
progressThreshold));
|
||||
linearDistance, maxDistance, nonLinearFactor));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -509,7 +512,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
// Constraints - absolute values
|
||||
float minVelocity = mFlingAnimationUtils.getMinVelocityPxPerSecond();
|
||||
float maxVelocity = mFlingAnimationUtils.getHighVelocityPxPerSecond();
|
||||
float maxX = mTouchTracker.getMaxX(); // px
|
||||
float maxX = mTouchTracker.getMaxDistance(); // px
|
||||
float maxFlingDistance = maxX * MAX_FLING_PROGRESS; // px
|
||||
|
||||
// Current state
|
||||
@@ -605,8 +608,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
mTouchTracker.setTriggerBack(triggerBack);
|
||||
}
|
||||
|
||||
private void setSwipeThresholds(float progressThreshold) {
|
||||
mTouchTracker.setProgressThreshold(progressThreshold);
|
||||
private void setSwipeThresholds(
|
||||
float linearDistance,
|
||||
float maxDistance,
|
||||
float nonLinearFactor) {
|
||||
mTouchTracker.setProgressThresholds(linearDistance, maxDistance, nonLinearFactor);
|
||||
}
|
||||
|
||||
private void invokeOrCancelBack() {
|
||||
|
||||
@@ -28,11 +28,13 @@ import android.window.BackMotionEvent;
|
||||
* Helper class to record the touch location for gesture and generate back events.
|
||||
*/
|
||||
class TouchTracker {
|
||||
private static final String PREDICTIVE_BACK_PROGRESS_THRESHOLD_PROP =
|
||||
"persist.wm.debug.predictive_back_progress_threshold";
|
||||
private static final int PROGRESS_THRESHOLD = SystemProperties
|
||||
.getInt(PREDICTIVE_BACK_PROGRESS_THRESHOLD_PROP, -1);
|
||||
private float mProgressThreshold;
|
||||
private static final String PREDICTIVE_BACK_LINEAR_DISTANCE_PROP =
|
||||
"persist.wm.debug.predictive_back_linear_distance";
|
||||
private static final int LINEAR_DISTANCE = SystemProperties
|
||||
.getInt(PREDICTIVE_BACK_LINEAR_DISTANCE_PROP, -1);
|
||||
private float mLinearDistance = LINEAR_DISTANCE;
|
||||
private float mMaxDistance;
|
||||
private float mNonLinearFactor;
|
||||
/**
|
||||
* Location of the latest touch event
|
||||
*/
|
||||
@@ -125,17 +127,42 @@ class TouchTracker {
|
||||
// the location everytime back is restarted after being cancelled.
|
||||
float startX = mTriggerBack ? mInitTouchX : mStartThresholdX;
|
||||
float deltaX = Math.abs(startX - touchX);
|
||||
float maxX = getMaxX();
|
||||
maxX = maxX == 0 ? 1 : maxX;
|
||||
return MathUtils.constrain(deltaX / maxX, 0, 1);
|
||||
float linearDistance = mLinearDistance;
|
||||
float maxDistance = getMaxDistance();
|
||||
maxDistance = maxDistance == 0 ? 1 : maxDistance;
|
||||
float progress;
|
||||
if (linearDistance < maxDistance) {
|
||||
// Up to linearDistance it behaves linearly, then slowly reaches 1f.
|
||||
|
||||
// maxDistance is composed of linearDistance + nonLinearDistance
|
||||
float nonLinearDistance = maxDistance - linearDistance;
|
||||
float initialTarget = linearDistance + nonLinearDistance * mNonLinearFactor;
|
||||
|
||||
boolean isLinear = deltaX <= linearDistance;
|
||||
if (isLinear) {
|
||||
progress = deltaX / initialTarget;
|
||||
} else {
|
||||
float nonLinearDeltaX = deltaX - linearDistance;
|
||||
float nonLinearProgress = nonLinearDeltaX / nonLinearDistance;
|
||||
float currentTarget = MathUtils.lerp(
|
||||
/* start = */ initialTarget,
|
||||
/* stop = */ maxDistance,
|
||||
/* amount = */ nonLinearProgress);
|
||||
progress = deltaX / currentTarget;
|
||||
}
|
||||
} else {
|
||||
// Always linear behavior.
|
||||
progress = deltaX / maxDistance;
|
||||
}
|
||||
return MathUtils.constrain(progress, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum X value (in pixels).
|
||||
* Maximum distance in pixels.
|
||||
* Progress is considered to be completed (1f) when this limit is exceeded.
|
||||
*/
|
||||
float getMaxX() {
|
||||
return PROGRESS_THRESHOLD >= 0 ? PROGRESS_THRESHOLD : mProgressThreshold;
|
||||
float getMaxDistance() {
|
||||
return mMaxDistance;
|
||||
}
|
||||
|
||||
BackMotionEvent createProgressEvent(float progress) {
|
||||
@@ -149,7 +176,14 @@ class TouchTracker {
|
||||
/* departingAnimationTarget = */ null);
|
||||
}
|
||||
|
||||
public void setProgressThreshold(float progressThreshold) {
|
||||
mProgressThreshold = progressThreshold;
|
||||
public void setProgressThresholds(float linearDistance, float maxDistance,
|
||||
float nonLinearFactor) {
|
||||
if (LINEAR_DISTANCE >= 0) {
|
||||
mLinearDistance = LINEAR_DISTANCE;
|
||||
} else {
|
||||
mLinearDistance = linearDistance;
|
||||
}
|
||||
mMaxDistance = maxDistance;
|
||||
mNonLinearFactor = nonLinearFactor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.wm.shell.back;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.window.BackEvent;
|
||||
import android.window.BackMotionEvent;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TouchTrackerTest {
|
||||
private static final float FAKE_THRESHOLD = 400;
|
||||
private static final float INITIAL_X_LEFT_EDGE = 5;
|
||||
private static final float INITIAL_X_RIGHT_EDGE = FAKE_THRESHOLD - INITIAL_X_LEFT_EDGE;
|
||||
private TouchTracker mTouchTracker;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mTouchTracker = new TouchTracker();
|
||||
mTouchTracker.setProgressThreshold(FAKE_THRESHOLD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generatesProgress_onStart() {
|
||||
mTouchTracker.setGestureStartLocation(INITIAL_X_LEFT_EDGE, 0, BackEvent.EDGE_LEFT);
|
||||
BackMotionEvent event = mTouchTracker.createStartEvent(null);
|
||||
assertEquals(event.getProgress(), 0f, 0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generatesProgress_leftEdge() {
|
||||
mTouchTracker.setGestureStartLocation(INITIAL_X_LEFT_EDGE, 0, BackEvent.EDGE_LEFT);
|
||||
float touchX = 10;
|
||||
float velocityX = 0;
|
||||
float velocityY = 0;
|
||||
|
||||
// Pre-commit
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), (touchX - INITIAL_X_LEFT_EDGE) / FAKE_THRESHOLD, 0f);
|
||||
|
||||
// Post-commit
|
||||
touchX += 100;
|
||||
mTouchTracker.setTriggerBack(true);
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), (touchX - INITIAL_X_LEFT_EDGE) / FAKE_THRESHOLD, 0f);
|
||||
|
||||
// Cancel
|
||||
touchX -= 10;
|
||||
mTouchTracker.setTriggerBack(false);
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), 0, 0f);
|
||||
|
||||
// Cancel more
|
||||
touchX -= 10;
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), 0, 0f);
|
||||
|
||||
// Restart
|
||||
touchX += 10;
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), 0, 0f);
|
||||
|
||||
// Restarted, but pre-commit
|
||||
float restartX = touchX;
|
||||
touchX += 10;
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), (touchX - restartX) / FAKE_THRESHOLD, 0f);
|
||||
|
||||
// Restarted, post-commit
|
||||
touchX += 10;
|
||||
mTouchTracker.setTriggerBack(true);
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), (touchX - INITIAL_X_LEFT_EDGE) / FAKE_THRESHOLD, 0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generatesProgress_rightEdge() {
|
||||
mTouchTracker.setGestureStartLocation(INITIAL_X_RIGHT_EDGE, 0, BackEvent.EDGE_RIGHT);
|
||||
float touchX = INITIAL_X_RIGHT_EDGE - 10; // Fake right edge
|
||||
float velocityX = 0f;
|
||||
float velocityY = 0f;
|
||||
|
||||
// Pre-commit
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), (INITIAL_X_RIGHT_EDGE - touchX) / FAKE_THRESHOLD, 0f);
|
||||
|
||||
// Post-commit
|
||||
touchX -= 100;
|
||||
mTouchTracker.setTriggerBack(true);
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), (INITIAL_X_RIGHT_EDGE - touchX) / FAKE_THRESHOLD, 0f);
|
||||
|
||||
// Cancel
|
||||
touchX += 10;
|
||||
mTouchTracker.setTriggerBack(false);
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), 0, 0f);
|
||||
|
||||
// Cancel more
|
||||
touchX += 10;
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), 0, 0f);
|
||||
|
||||
// Restart
|
||||
touchX -= 10;
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), 0, 0f);
|
||||
|
||||
// Restarted, but pre-commit
|
||||
float restartX = touchX;
|
||||
touchX -= 10;
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), (restartX - touchX) / FAKE_THRESHOLD, 0f);
|
||||
|
||||
// Restarted, post-commit
|
||||
touchX -= 10;
|
||||
mTouchTracker.setTriggerBack(true);
|
||||
mTouchTracker.update(touchX, 0, velocityX, velocityY);
|
||||
assertEquals(getProgress(), (INITIAL_X_RIGHT_EDGE - touchX) / FAKE_THRESHOLD, 0f);
|
||||
}
|
||||
|
||||
private float getProgress() {
|
||||
return mTouchTracker.createProgressEvent().getProgress();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.wm.shell.back
|
||||
|
||||
import android.util.MathUtils
|
||||
import android.window.BackEvent
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class TouchTrackerTest {
|
||||
private fun linearTouchTracker(): TouchTracker = TouchTracker().apply {
|
||||
setProgressThresholds(MAX_DISTANCE, MAX_DISTANCE, NON_LINEAR_FACTOR)
|
||||
}
|
||||
|
||||
private fun nonLinearTouchTracker(): TouchTracker = TouchTracker().apply {
|
||||
setProgressThresholds(LINEAR_DISTANCE, MAX_DISTANCE, NON_LINEAR_FACTOR)
|
||||
}
|
||||
|
||||
private fun TouchTracker.assertProgress(expected: Float) {
|
||||
val actualProgress = createProgressEvent().progress
|
||||
assertEquals(expected, actualProgress, /* delta = */ 0f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun generatesProgress_onStart() {
|
||||
val linearTracker = linearTouchTracker()
|
||||
linearTracker.setGestureStartLocation(INITIAL_X_LEFT_EDGE, 0f, BackEvent.EDGE_LEFT)
|
||||
val event = linearTracker.createStartEvent(null)
|
||||
assertEquals(0f, event.progress, 0f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun generatesProgress_leftEdge() {
|
||||
val linearTracker = linearTouchTracker()
|
||||
linearTracker.setGestureStartLocation(INITIAL_X_LEFT_EDGE, 0f, BackEvent.EDGE_LEFT)
|
||||
var touchX = 10f
|
||||
val velocityX = 0f
|
||||
val velocityY = 0f
|
||||
|
||||
// Pre-commit
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / MAX_DISTANCE)
|
||||
|
||||
// Post-commit
|
||||
touchX += 100f
|
||||
linearTracker.setTriggerBack(true)
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / MAX_DISTANCE)
|
||||
|
||||
// Cancel
|
||||
touchX -= 10f
|
||||
linearTracker.setTriggerBack(false)
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress(0f)
|
||||
|
||||
// Cancel more
|
||||
touchX -= 10f
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress(0f)
|
||||
|
||||
// Restart
|
||||
touchX += 10f
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress(0f)
|
||||
|
||||
// Restarted, but pre-commit
|
||||
val restartX = touchX
|
||||
touchX += 10f
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress((touchX - restartX) / MAX_DISTANCE)
|
||||
|
||||
// Restarted, post-commit
|
||||
touchX += 10f
|
||||
linearTracker.setTriggerBack(true)
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / MAX_DISTANCE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun generatesProgress_rightEdge() {
|
||||
val linearTracker = linearTouchTracker()
|
||||
linearTracker.setGestureStartLocation(INITIAL_X_RIGHT_EDGE, 0f, BackEvent.EDGE_RIGHT)
|
||||
var touchX = INITIAL_X_RIGHT_EDGE - 10 // Fake right edge
|
||||
val velocityX = 0f
|
||||
val velocityY = 0f
|
||||
val target = MAX_DISTANCE
|
||||
|
||||
// Pre-commit
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress((INITIAL_X_RIGHT_EDGE - touchX) / target)
|
||||
|
||||
// Post-commit
|
||||
touchX -= 100f
|
||||
linearTracker.setTriggerBack(true)
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress((INITIAL_X_RIGHT_EDGE - touchX) / target)
|
||||
|
||||
// Cancel
|
||||
touchX += 10f
|
||||
linearTracker.setTriggerBack(false)
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress(0f)
|
||||
|
||||
// Cancel more
|
||||
touchX += 10f
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress(0f)
|
||||
|
||||
// Restart
|
||||
touchX -= 10f
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress(0f)
|
||||
|
||||
// Restarted, but pre-commit
|
||||
val restartX = touchX
|
||||
touchX -= 10f
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress((restartX - touchX) / target)
|
||||
|
||||
// Restarted, post-commit
|
||||
touchX -= 10f
|
||||
linearTracker.setTriggerBack(true)
|
||||
linearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
linearTracker.assertProgress((INITIAL_X_RIGHT_EDGE - touchX) / target)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun generatesNonLinearProgress_leftEdge() {
|
||||
val nonLinearTracker = nonLinearTouchTracker()
|
||||
nonLinearTracker.setGestureStartLocation(INITIAL_X_LEFT_EDGE, 0f, BackEvent.EDGE_LEFT)
|
||||
var touchX = 10f
|
||||
val velocityX = 0f
|
||||
val velocityY = 0f
|
||||
val linearTarget = LINEAR_DISTANCE + (MAX_DISTANCE - LINEAR_DISTANCE) * NON_LINEAR_FACTOR
|
||||
|
||||
// Pre-commit: linear progress
|
||||
nonLinearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
nonLinearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / linearTarget)
|
||||
|
||||
// Post-commit: still linear progress
|
||||
touchX += 100f
|
||||
nonLinearTracker.setTriggerBack(true)
|
||||
nonLinearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
nonLinearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / linearTarget)
|
||||
|
||||
// still linear progress
|
||||
touchX = INITIAL_X_LEFT_EDGE + LINEAR_DISTANCE
|
||||
nonLinearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
nonLinearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / linearTarget)
|
||||
|
||||
// non linear progress
|
||||
touchX += 10
|
||||
nonLinearTracker.update(touchX, 0f, velocityX, velocityY)
|
||||
val nonLinearTouch = (touchX - INITIAL_X_LEFT_EDGE) - LINEAR_DISTANCE
|
||||
val nonLinearProgress = nonLinearTouch / NON_LINEAR_DISTANCE
|
||||
val nonLinearTarget = MathUtils.lerp(linearTarget, MAX_DISTANCE, nonLinearProgress)
|
||||
nonLinearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / nonLinearTarget)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MAX_DISTANCE = 500f
|
||||
private const val LINEAR_DISTANCE = 400f
|
||||
private const val NON_LINEAR_DISTANCE = MAX_DISTANCE - LINEAR_DISTANCE
|
||||
private const val NON_LINEAR_FACTOR = 0.2f
|
||||
private const val INITIAL_X_LEFT_EDGE = 5f
|
||||
private const val INITIAL_X_RIGHT_EDGE = MAX_DISTANCE - INITIAL_X_LEFT_EDGE
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,9 @@
|
||||
<dimen name="navigation_edge_action_drag_threshold">16dp</dimen>
|
||||
<!-- The threshold to progress back animation for edge swipe -->
|
||||
<dimen name="navigation_edge_action_progress_threshold">412dp</dimen>
|
||||
<!-- This value is used to calculate the target if the screen is wider than the
|
||||
navigation_edge_action_progress_threshold. See BackAnimation#setSwipeThresholds -->
|
||||
<item name="back_progress_non_linear_factor" format="float" type="dimen">0.2</item>
|
||||
<!-- The minimum display position of the arrow on the screen -->
|
||||
<dimen name="navigation_edge_arrow_min_y">64dp</dimen>
|
||||
<!-- The amount by which the arrow is shifted to avoid the finger-->
|
||||
|
||||
@@ -63,6 +63,8 @@ import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
import android.window.BackEvent;
|
||||
|
||||
import androidx.annotation.DimenRes;
|
||||
|
||||
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
|
||||
import com.android.internal.policy.GestureNavigationSettingsObserver;
|
||||
import com.android.systemui.R;
|
||||
@@ -225,7 +227,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
|
||||
// The slop to distinguish between horizontal and vertical motion
|
||||
private float mTouchSlop;
|
||||
// The threshold for back swipe full progress.
|
||||
private float mBackSwipeProgressThreshold;
|
||||
private float mBackSwipeLinearThreshold;
|
||||
private float mNonLinearFactor;
|
||||
// Duration after which we consider the event as longpress.
|
||||
private final int mLongPressTimeout;
|
||||
private int mStartingQuickstepRotation = -1;
|
||||
@@ -471,11 +474,19 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
|
||||
final float backGestureSlop = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.BACK_GESTURE_SLOP_MULTIPLIER, 0.75f);
|
||||
mTouchSlop = mViewConfiguration.getScaledTouchSlop() * backGestureSlop;
|
||||
mBackSwipeProgressThreshold = res.getDimension(
|
||||
mBackSwipeLinearThreshold = res.getDimension(
|
||||
R.dimen.navigation_edge_action_progress_threshold);
|
||||
mNonLinearFactor = getDimenFloat(res,
|
||||
R.dimen.back_progress_non_linear_factor);
|
||||
updateBackAnimationThresholds();
|
||||
}
|
||||
|
||||
private float getDimenFloat(Resources res, @DimenRes int resId) {
|
||||
TypedValue typedValue = new TypedValue();
|
||||
res.getValue(resId, typedValue, true);
|
||||
return typedValue.getFloat();
|
||||
}
|
||||
|
||||
public void updateNavigationBarOverlayExcludeRegion(Rect exclude) {
|
||||
mNavBarOverlayExcludedBounds.set(exclude);
|
||||
}
|
||||
@@ -1116,8 +1127,9 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
|
||||
if (mBackAnimation == null) {
|
||||
return;
|
||||
}
|
||||
mBackAnimation.setSwipeThresholds(
|
||||
Math.min(mDisplaySize.x, mBackSwipeProgressThreshold));
|
||||
int maxDistance = mDisplaySize.x;
|
||||
float linearDistance = Math.min(maxDistance, mBackSwipeLinearThreshold);
|
||||
mBackAnimation.setSwipeThresholds(linearDistance, maxDistance, mNonLinearFactor);
|
||||
}
|
||||
|
||||
private boolean sendEvent(int action, int code) {
|
||||
|
||||
Reference in New Issue
Block a user