Merge "Don't pull magnetized objects into the target unless they're dragged." into rvc-dev
This commit is contained in:
@@ -266,6 +266,10 @@ public class PipTouchHandler {
|
|||||||
|
|
||||||
mMagnetizedPip = mMotionHelper.getMagnetizedPip();
|
mMagnetizedPip = mMotionHelper.getMagnetizedPip();
|
||||||
mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0);
|
mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0);
|
||||||
|
|
||||||
|
// Set the magnetic field radius equal to twice the size of the target.
|
||||||
|
mMagneticTarget.setMagneticFieldRadiusPx(targetSize * 2);
|
||||||
|
|
||||||
mMagnetizedPip.setPhysicsAnimatorUpdateListener(mMotionHelper.mResizePipUpdateListener);
|
mMagnetizedPip.setPhysicsAnimatorUpdateListener(mMotionHelper.mResizePipUpdateListener);
|
||||||
mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() {
|
mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -504,9 +508,6 @@ public class PipTouchHandler {
|
|||||||
mTargetView.setTranslationY(mTargetViewContainer.getHeight());
|
mTargetView.setTranslationY(mTargetViewContainer.getHeight());
|
||||||
mTargetViewContainer.setVisibility(View.VISIBLE);
|
mTargetViewContainer.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
// Set the magnetic field radius to half of PIP's width.
|
|
||||||
mMagneticTarget.setMagneticFieldRadiusPx(mMotionHelper.getBounds().width());
|
|
||||||
|
|
||||||
// Cancel in case we were in the middle of animating it out.
|
// Cancel in case we were in the middle of animating it out.
|
||||||
mMagneticTargetAnimator.cancel();
|
mMagneticTargetAnimator.cancel();
|
||||||
mMagneticTargetAnimator
|
mMagneticTargetAnimator
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import android.provider.Settings
|
|||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.VelocityTracker
|
import android.view.VelocityTracker
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.ViewConfiguration
|
||||||
import androidx.dynamicanimation.animation.DynamicAnimation
|
import androidx.dynamicanimation.animation.DynamicAnimation
|
||||||
import androidx.dynamicanimation.animation.FloatPropertyCompat
|
import androidx.dynamicanimation.animation.FloatPropertyCompat
|
||||||
import androidx.dynamicanimation.animation.SpringForce
|
import androidx.dynamicanimation.animation.SpringForce
|
||||||
@@ -146,6 +147,10 @@ abstract class MagnetizedObject<T : Any>(
|
|||||||
private val velocityTracker: VelocityTracker = VelocityTracker.obtain()
|
private val velocityTracker: VelocityTracker = VelocityTracker.obtain()
|
||||||
private val vibrator: Vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
private val vibrator: Vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||||
|
|
||||||
|
private var touchDown = PointF()
|
||||||
|
private var touchSlop = 0
|
||||||
|
private var movedBeyondSlop = false
|
||||||
|
|
||||||
/** Whether touch events are presently occurring within the magnetic field area of a target. */
|
/** Whether touch events are presently occurring within the magnetic field area of a target. */
|
||||||
val objectStuckToTarget: Boolean
|
val objectStuckToTarget: Boolean
|
||||||
get() = targetObjectIsStuckTo != null
|
get() = targetObjectIsStuckTo != null
|
||||||
@@ -324,15 +329,32 @@ abstract class MagnetizedObject<T : Any>(
|
|||||||
// When a gesture begins, recalculate target views' positions on the screen in case they
|
// When a gesture begins, recalculate target views' positions on the screen in case they
|
||||||
// have changed. Also, clear state.
|
// have changed. Also, clear state.
|
||||||
if (ev.action == MotionEvent.ACTION_DOWN) {
|
if (ev.action == MotionEvent.ACTION_DOWN) {
|
||||||
updateTargetViewLocations()
|
updateTargetViews()
|
||||||
|
|
||||||
// Clear the velocity tracker and assume we're not stuck to a target yet.
|
// Clear the velocity tracker and stuck target.
|
||||||
velocityTracker.clear()
|
velocityTracker.clear()
|
||||||
targetObjectIsStuckTo = null
|
targetObjectIsStuckTo = null
|
||||||
|
|
||||||
|
// Set the touch down coordinates and reset movedBeyondSlop.
|
||||||
|
touchDown.set(ev.rawX, ev.rawY)
|
||||||
|
movedBeyondSlop = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always pass events to the VelocityTracker.
|
||||||
addMovement(ev)
|
addMovement(ev)
|
||||||
|
|
||||||
|
// If we haven't yet moved beyond the slop distance, check if we have.
|
||||||
|
if (!movedBeyondSlop) {
|
||||||
|
val dragDistance = hypot(ev.rawX - touchDown.x, ev.rawY - touchDown.y)
|
||||||
|
if (dragDistance > touchSlop) {
|
||||||
|
// If we're beyond the slop distance, save that and continue.
|
||||||
|
movedBeyondSlop = true
|
||||||
|
} else {
|
||||||
|
// Otherwise, don't do anything yet.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val targetObjectIsInMagneticFieldOf = associatedTargets.firstOrNull { target ->
|
val targetObjectIsInMagneticFieldOf = associatedTargets.firstOrNull { target ->
|
||||||
val distanceFromTargetCenter = hypot(
|
val distanceFromTargetCenter = hypot(
|
||||||
ev.rawX - target.centerOnScreen.x,
|
ev.rawX - target.centerOnScreen.x,
|
||||||
@@ -559,8 +581,14 @@ abstract class MagnetizedObject<T : Any>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Updates the locations on screen of all of the [associatedTargets]. */
|
/** Updates the locations on screen of all of the [associatedTargets]. */
|
||||||
internal fun updateTargetViewLocations() {
|
internal fun updateTargetViews() {
|
||||||
associatedTargets.forEach { it.updateLocationOnScreen() }
|
associatedTargets.forEach { it.updateLocationOnScreen() }
|
||||||
|
|
||||||
|
// Update the touch slop, since the configuration may have changed.
|
||||||
|
if (associatedTargets.size > 0) {
|
||||||
|
touchSlop =
|
||||||
|
ViewConfiguration.get(associatedTargets[0].targetView.context).scaledTouchSlop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -186,8 +186,8 @@ class MagnetizedObjectTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMotionEventConsumption_downInMagneticField() {
|
fun testMotionEventConsumption_downInMagneticField() {
|
||||||
// We should consume DOWN events if they occur in the field.
|
// We should not consume DOWN events even if they occur in the field.
|
||||||
assertTrue(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
|
assertFalse(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
|
||||||
x = targetCenterX, y = targetCenterY, action = MotionEvent.ACTION_DOWN)))
|
x = targetCenterX, y = targetCenterY, action = MotionEvent.ACTION_DOWN)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,10 +342,14 @@ class MagnetizedObjectTest : SysuiTestCase() {
|
|||||||
// Trigger the magnet animation, and block the test until it ends.
|
// Trigger the magnet animation, and block the test until it ends.
|
||||||
PhysicsAnimatorTestUtils.setAllAnimationsBlock(true)
|
PhysicsAnimatorTestUtils.setAllAnimationsBlock(true)
|
||||||
magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
|
magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
|
||||||
x = targetCenterX,
|
x = targetCenterX - 250,
|
||||||
y = targetCenterY,
|
y = targetCenterY - 250,
|
||||||
action = MotionEvent.ACTION_DOWN))
|
action = MotionEvent.ACTION_DOWN))
|
||||||
|
|
||||||
|
magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
|
||||||
|
x = targetCenterX,
|
||||||
|
y = targetCenterY))
|
||||||
|
|
||||||
// The object's (top-left) position should now position it centered over the target.
|
// The object's (top-left) position should now position it centered over the target.
|
||||||
assertEquals(targetCenterX - objectSize / 2, objectX)
|
assertEquals(targetCenterX - objectSize / 2, objectX)
|
||||||
assertEquals(targetCenterY - objectSize / 2, objectY)
|
assertEquals(targetCenterY - objectSize / 2, objectY)
|
||||||
|
|||||||
Reference in New Issue
Block a user