Skip to content

Commit 8c5de94

Browse files
committed
make movment and touch detection better
1 parent bffb9a2 commit 8c5de94

File tree

4 files changed

+67
-33
lines changed

4 files changed

+67
-33
lines changed

new-player/src/main/java/net/newpipe/newplayer/ui/common/utils.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import androidx.compose.ui.layout.Layout
4747
import androidx.compose.ui.layout.Placeable
4848
import androidx.compose.ui.platform.LocalConfiguration
4949
import androidx.compose.ui.platform.LocalContext
50+
import androidx.compose.ui.platform.LocalResources
5051
import androidx.compose.ui.platform.LocalView
5152
import androidx.compose.ui.res.painterResource
5253
import androidx.compose.ui.unit.Constraints
@@ -61,6 +62,8 @@ import net.newpipe.newplayer.data.NewPlayerException
6162
import net.newpipe.newplayer.uiModel.EmbeddedUiConfig
6263
import java.util.Locale
6364

65+
private const val INCHES_PER_CENTIMETER = 0.3937F
66+
6467
/** Get the [Activity] from local context. Assumes the activity exists!
6568
* @return the activity
6669
* @throws NullPointerException if there is no Activity
@@ -281,4 +284,9 @@ internal fun HiddenMeasure(
281284
// Draw nothing
282285
}
283286
}
284-
}
287+
}
288+
289+
/** @hide */
290+
@Composable
291+
internal fun getPixelsPerCentimeter() =
292+
LocalResources.current.displayMetrics.xdpi * INCHES_PER_CENTIMETER

new-player/src/main/java/net/newpipe/newplayer/ui/videoplayer/VideoPlayerControllerUI.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ fun AnimateVideoControlVisibility(visible: Boolean, content: @Composable () -> U
156156
enter = fadeIn(animationSpec = tween(durationMillis = 100, easing = LinearEasing)),
157157
exit = fadeOut(animationSpec = tween(durationMillis = 100, easing = LinearEasing))
158158
) {
159-
Log.d("GestureSurface", "=========");
160159
content()
161160
}
162161
}

new-player/src/main/java/net/newpipe/newplayer/ui/videoplayer/gesture_ui/GestureSurface.kt

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import androidx.compose.foundation.layout.fillMaxSize
2727
import androidx.compose.material3.Surface
2828
import androidx.compose.runtime.Composable
2929
import androidx.compose.runtime.getValue
30-
import androidx.compose.runtime.mutableFloatStateOf
3130
import androidx.compose.runtime.mutableIntStateOf
3231
import androidx.compose.runtime.mutableStateOf
3332
import androidx.compose.runtime.remember
@@ -37,11 +36,10 @@ import androidx.compose.ui.ExperimentalComposeUiApi
3736
import androidx.compose.ui.Modifier
3837
import androidx.compose.ui.graphics.Color
3938
import androidx.compose.ui.input.pointer.pointerInteropFilter
40-
import androidx.compose.ui.platform.LocalDensity
41-
import androidx.compose.ui.unit.dp
4239
import kotlinx.coroutines.Job
4340
import kotlinx.coroutines.delay
4441
import kotlinx.coroutines.launch
42+
import net.newpipe.newplayer.ui.common.getPixelsPerCentimeter
4543
import kotlin.math.abs
4644

4745
private const val TAG = "GestureSurface"
@@ -63,12 +61,20 @@ internal fun GestureSurface(
6361
content: @Composable () -> Unit = {}
6462
) {
6563

66-
var lastTouchedPosition by remember {
64+
var movementEventsUnlocked by remember {
65+
mutableStateOf(false)
66+
}
67+
68+
var ignoreMovementWhileFingerDown by remember {
69+
mutableStateOf(false)
70+
}
71+
72+
var fingerDownPosition by remember {
6773
mutableStateOf(TouchedPosition(0f, 0f))
6874
}
6975

70-
var yMovementSum by remember {
71-
mutableFloatStateOf(0f)
76+
var lastTouchPosition by remember {
77+
mutableStateOf(TouchedPosition(0f, 0f))
7278
}
7379

7480
var lastFingerDownTime by remember {
@@ -125,7 +131,7 @@ internal fun GestureSurface(
125131
regularTabJob = composableScope.launch {
126132
delay(ENTER_MULTITAB_MODE_DELAY)
127133

128-
val isMultitab = isAMultitapEvent();
134+
val isMultitab = isAMultitapEvent();
129135
val fingerDownUpOk = fingerDownAndUpHappenedInShortEnoughTimeForARegularTab()
130136
if (multitapAmount <= 0 && fingerDownUpOk) {
131137
onRegularTap()
@@ -136,11 +142,13 @@ internal fun GestureSurface(
136142
}
137143
}
138144

139-
140145
val handleActionDown = { event: MotionEvent ->
141146
Log.d(TAG, "finger down")
142-
lastTouchedPosition = TouchedPosition(event.x, event.y)
143-
yMovementSum = 0f
147+
fingerDownPosition = TouchedPosition(event.x, event.y)
148+
lastTouchPosition = fingerDownPosition
149+
movementEventsUnlocked = false
150+
ignoreMovementWhileFingerDown = false
151+
144152
if (isAMultitapEvent()) {
145153
onMultitap();
146154
} else {
@@ -151,36 +159,48 @@ internal fun GestureSurface(
151159
}
152160

153161
val handleActionUp = { onMultiTap: (Int) -> Unit, onRegularTap: () -> Unit ->
154-
Log.d(TAG, "finger up");
162+
Log.d(TAG, "finger up")
155163
onUp()
156-
yMovementSum = 0f
157-
lastFingerUpTime = System.currentTimeMillis();
164+
lastFingerUpTime = System.currentTimeMillis()
165+
movementEventsUnlocked = false
166+
ignoreMovementWhileFingerDown = false
158167
true
159168
}
160169

161-
val rangeAtWhichItsIntendedMovement = with(LocalDensity.current) {
162-
15.dp.toPx()
163-
}
170+
// prevents detecting movement when actually a tap was intended
171+
val deadZoneRange = 0.1 * getPixelsPerCentimeter()
164172

165-
val handleMove = { event: MotionEvent, lambda: (movement: TouchedPosition) -> Unit ->
166-
val currentTouchedPosition = TouchedPosition(event.x, event.y)
167-
val movement = currentTouchedPosition - lastTouchedPosition
168173

169-
lastTouchedPosition = currentTouchedPosition
174+
val handleMove =
175+
{ event: MotionEvent, onFilteredMovementEvent: (movement: TouchedPosition) -> Unit ->
176+
val currentTouchedPosition = TouchedPosition(event.x, event.y)
177+
val movement = currentTouchedPosition - lastTouchPosition
178+
val vectorFromFingerDownEvent = currentTouchedPosition - fingerDownPosition
170179

171-
yMovementSum += abs(movement.y)
180+
lastTouchPosition = currentTouchedPosition
172181

173-
if (yMovementSum < rangeAtWhichItsIntendedMovement) {
174-
Log.d(TAG, " cancel regular tab")
175-
regularTabJob?.cancel()
176-
}
182+
if (!movementEventsUnlocked && deadZoneRange < vectorFromFingerDownEvent.distance()) {
183+
movementEventsUnlocked = true
184+
if (regularTabJob?.isActive ?: false) {
185+
Log.d(TAG, " cancel regular tab")
186+
regularTabJob?.cancel()
187+
}
188+
// if user starts to swipe sideways the movements should be totally ignore
189+
// for as long as the user keeps the finger on the screen.
190+
if (abs(vectorFromFingerDownEvent.y) <= abs(vectorFromFingerDownEvent.x)) {
191+
ignoreMovementWhileFingerDown = true
192+
}
193+
}
177194

178-
// filter out left and right movements as these are not important for the app
179-
if (abs(movement.x) <= abs(movement.y)) {
180-
lambda(movement)
195+
if (movementEventsUnlocked && !ignoreMovementWhileFingerDown) {
196+
Log.d(TAG, "movement event: distance")
197+
// filter out left and right movements as these are not important for the app
198+
if (abs(movement.x) <= abs(movement.y)) {
199+
onFilteredMovementEvent(movement)
200+
}
201+
}
202+
true
181203
}
182-
true
183-
}
184204

185205
Box(modifier = modifier.pointerInteropFilter {
186206
when (it.action) {
@@ -194,4 +214,5 @@ internal fun GestureSurface(
194214
content()
195215
Surface(color = color, modifier = Modifier.fillMaxSize()) {}
196216
}
197-
}
217+
}
218+

new-player/src/main/java/net/newpipe/newplayer/ui/videoplayer/gesture_ui/TouchedPosition.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,14 @@
2020

2121
package net.newpipe.newplayer.ui.videoplayer.gesture_ui
2222

23+
import kotlin.math.pow
24+
import kotlin.math.sqrt
25+
2326

2427
/** @hide */
2528
internal data class TouchedPosition(val x: Float, val y: Float) {
2629
operator fun minus(other: TouchedPosition) = TouchedPosition(this.x - other.x, this.y - other.y)
30+
31+
fun distance() =
32+
sqrt(x.pow(1) + y.pow(2))
2733
}

0 commit comments

Comments
 (0)