Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose a MoveGestureDetector#moveThresholdRect #96

Merged
merged 3 commits into from
Apr 30, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ object GesturesUiTestUtils {
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
injectMotionEventToUiController(uiController, event)
} catch (ex: InjectEventSecurityException) {
throw RuntimeException("Could not perform quick scale", ex)
throw RuntimeException("Could not perform move", ex)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package com.mapbox.android.gestures

import GesturesUiTestUtils.DEFAULT_GESTURE_DURATION
import GesturesUiTestUtils.move
import android.graphics.PointF
import android.graphics.RectF
import androidx.test.espresso.Espresso
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import com.mapbox.android.gestures.testapp.R
import com.mapbox.android.gestures.testapp.TestActivity
import org.junit.Assert
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

@RunWith(AndroidJUnit4::class)
class MoveGestureDetectorTest {

@Rule
@JvmField
val activityTestRule = ActivityTestRule(TestActivity::class.java)

private lateinit var gesturesManager: AndroidGesturesManager

@Before
fun setup() {
gesturesManager = activityTestRule.activity.gesturesManager
}

@Test
fun move_ignoredWithRectThreshold() {
val rect = RectF(400f, 400f, 600f, 600f)
gesturesManager.setMoveGestureListener(object : MoveGestureDetector.OnMoveGestureListener {
override fun onMoveBegin(detector: MoveGestureDetector) = true

override fun onMove(
detector: MoveGestureDetector,
distanceX: Float,
distanceY: Float
): Boolean = throw AssertionError("onMove shouldn't be called if threshold was not met")

override fun onMoveEnd(detector: MoveGestureDetector, velocityX: Float, velocityY: Float) = Unit

})
gesturesManager.moveGestureDetector.moveThresholdRect = rect
Espresso.onView(ViewMatchers.withId(R.id.content)).perform(
move(
deltaX = 50f,
deltaY = 50f,
startPoint = PointF(rect.right - 100f, rect.bottom - 100f)
)
)
}

@Test
fun move_executedWhenOutsideOfRect() {
val latch = CountDownLatch(1)
val rect = RectF(400f, 400f, 600f, 600f)
gesturesManager.setMoveGestureListener(object : MoveGestureDetector.OnMoveGestureListener {
override fun onMoveBegin(detector: MoveGestureDetector) = true

override fun onMove(
detector: MoveGestureDetector,
distanceX: Float,
distanceY: Float
): Boolean {
Assert.assertFalse(rect.contains(detector.focalPoint.x, detector.focalPoint.y))
latch.countDown()
return true
}

override fun onMoveEnd(detector: MoveGestureDetector, velocityX: Float, velocityY: Float) = Unit

})
gesturesManager.moveGestureDetector.moveThresholdRect = rect
Espresso.onView(ViewMatchers.withId(R.id.content)).perform(
move(
deltaX = 100f,
deltaY = 100f,
startPoint = PointF(rect.right + 50f, rect.bottom + 50f)
)
)
if (!latch.await(DEFAULT_GESTURE_DURATION, TimeUnit.MILLISECONDS)) {
Assert.fail("move was not called")
}
}

@Test
fun move_executedWhenRectThresholdMet() {
val latch = CountDownLatch(1)
val rect = RectF(400f, 400f, 600f, 600f)
gesturesManager.setMoveGestureListener(object : MoveGestureDetector.OnMoveGestureListener {
override fun onMoveBegin(detector: MoveGestureDetector) = true

override fun onMove(
detector: MoveGestureDetector,
distanceX: Float,
distanceY: Float
): Boolean {
Assert.assertFalse(rect.contains(detector.focalPoint.x, detector.focalPoint.y))
latch.countDown()
return true
}

override fun onMoveEnd(detector: MoveGestureDetector, velocityX: Float, velocityY: Float) = Unit

})
gesturesManager.moveGestureDetector.moveThresholdRect = rect
Espresso.onView(ViewMatchers.withId(R.id.content)).perform(
move(
deltaX = -150f,
deltaY = -150f,
startPoint = PointF(500f, 500f)
)
)
if (!latch.await(DEFAULT_GESTURE_DURATION, TimeUnit.MILLISECONDS)) {
Assert.fail("move was not called")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import android.os.Build
import android.os.Handler
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.rule.ActivityTestRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import com.mapbox.android.gestures.testapp.R
import com.mapbox.android.gestures.testapp.TestActivity
import org.junit.Assert
Expand Down Expand Up @@ -449,11 +449,9 @@ class ScaleGestureDetectorTest {
override fun onScaleEnd(detector: StandardScaleGestureDetector, velocityX: Float, velocityY: Float) {
endInvocations[0]++
gesturesManager.setMoveGestureListener(object : MoveGestureDetector.OnMoveGestureListener {
override fun onMoveBegin(detector: MoveGestureDetector?): Boolean {
return true
}
override fun onMoveBegin(detector: MoveGestureDetector) = true

override fun onMove(detector: MoveGestureDetector?, distanceX: Float, distanceY: Float): Boolean {
override fun onMove(detector: MoveGestureDetector, distanceX: Float, distanceY: Float): Boolean {
if (endInvocations[0] == 1) {
moveAfterInterruption = true
} else {
Expand All @@ -462,8 +460,7 @@ class ScaleGestureDetectorTest {
return true
}

override fun onMoveEnd(detector: MoveGestureDetector?, velocityX: Float, velocityY: Float) {
}
override fun onMoveEnd(detector: MoveGestureDetector, velocityX: Float, velocityY: Float) {}
})
}
})
Expand Down Expand Up @@ -615,7 +612,6 @@ class ScaleGestureDetectorTest {
}
})

onView(withId(R.id.content)).perform(quickScale(gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold / 2, withVelocity = false, duration = 50L))
onView(withId(R.id.content)).perform(move(300f, 300f, withVelocity = false))
}
}
20 changes: 4 additions & 16 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,20 @@ jobs:
build:
working_directory: ~/code
docker:
- image: mbgl/android-ndk-r19:8e91a7ebab
- image: mbgl/android-ndk-r20:7b7c4b42cf
environment:
JVM_OPTS: -Xmx3200m
BUILDTYPE: Debug
IS_LOCAL_DEVELOPMENT: false
steps:
- checkout
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}-{{ checksum "library/build.gradle" }}-{{ checksum "gradle/dependencies.gradle" }}
- run:
name: Download Dependencies
command: ./gradlew androidDependencies
- save_cache:
paths:
- ~/.gradle
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}-{{ checksum "library/build.gradle" }}-{{ checksum "gradle/dependencies.gradle" }}
- run:
name: Check code style
command: make checkstyle
Expand All @@ -38,13 +36,6 @@ jobs:
- run:
name: Run unit-test in Android libraries
command: make test
- run:
name: Log in to Google Cloud Platform
shell: /bin/bash -euo pipefail
command: |
echo "${GCLOUD_SERVICE_ACCOUNT_JSON}" > secret.json
gcloud auth activate-service-account --key-file secret.json --project mapbox-events-android
rm secret.json
- store_artifacts:
path: app/build/reports
destination: reports
Expand All @@ -57,11 +48,8 @@ jobs:
only:
- master
docker:
- image: mbgl/android-ndk-r19:8e91a7ebab
- image: mbgl/android-ndk-r20:7b7c4b42cf
working_directory: ~/code
environment:
BUILDTYPE: Release
IS_LOCAL_DEVELOPMENT: false
steps:
- checkout
- run:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import android.content.Context;
import android.graphics.PointF;
import android.graphics.RectF;
import android.view.MotionEvent;

import androidx.annotation.DimenRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import android.view.MotionEvent;

import java.util.HashMap;
import java.util.HashSet;
Expand Down Expand Up @@ -38,7 +41,10 @@ public class MoveGestureDetector extends ProgressiveGesture<MoveGestureDetector.
handledTypes.add(GESTURE_TYPE_MOVE);
}

@Nullable
private RectF moveThresholdRect;
private float moveThreshold;

private final Map<Integer, MoveDistancesObject> moveDistancesObjectMap = new HashMap<>();

public MoveGestureDetector(Context context, AndroidGesturesManager gesturesManager) {
Expand Down Expand Up @@ -172,10 +178,11 @@ private void updateMoveDistancesObjects() {

boolean checkAnyMoveAboveThreshold() {
for (MoveDistancesObject moveDistancesObject : moveDistancesObjectMap.values()) {
if (Math.abs(moveDistancesObject.getDistanceXSinceStart()) >= moveThreshold
|| Math.abs(moveDistancesObject.getDistanceYSinceStart()) >= moveThreshold) {
return true;
}
boolean thresholdExceeded = Math.abs(moveDistancesObject.getDistanceXSinceStart()) >= moveThreshold
|| Math.abs(moveDistancesObject.getDistanceYSinceStart()) >= moveThreshold;

boolean isInRect = moveThresholdRect != null && moveThresholdRect.contains(getFocalPoint().x, getFocalPoint().y);
return !isInRect && thresholdExceeded;
pengdev marked this conversation as resolved.
Show resolved Hide resolved
}
return false;
}
Expand Down Expand Up @@ -205,6 +212,7 @@ protected int getRequiredPointersCount() {
* Get the delta pixel threshold required to qualify it as a move gesture.
*
* @return delta pixel threshold
* @see #getMoveThresholdRect()
*/
public float getMoveThreshold() {
return moveThreshold;
Expand All @@ -216,11 +224,35 @@ public float getMoveThreshold() {
* We encourage to set those values from dimens to accommodate for various screen sizes.
*
* @param moveThreshold delta threshold
* @see #setMoveThresholdRect(RectF)
*/
public void setMoveThreshold(float moveThreshold) {
this.moveThreshold = moveThreshold;
}

/**
* Get the screen area in which the move gesture cannot be started.
* If the gesture is already in progress, this value is ignored.
* This condition is evaluated before {@link #setMoveThreshold(float)}.
*
* @return the screen area in which the gesture cannot be started
*/
@Nullable
public RectF getMoveThresholdRect() {
return moveThresholdRect;
}

/**
* Set the screen area in which the move gesture cannot be started.
* If the gesture is already in progress, this value is ignored.
* This condition is evaluated before {@link #setMoveThreshold(float)}.
*
* @param moveThresholdRect the screen area in which the gesture cannot be started
*/
public void setMoveThresholdRect(@Nullable RectF moveThresholdRect) {
this.moveThresholdRect = moveThresholdRect;
}

/**
* Set the delta dp threshold required to qualify it as a move gesture.
*
Expand Down