mirror of
https://github.com/florisboard/florisboard.git
synced 2024-09-20 03:52:18 +02:00
Merge pull request #218 from florisboard/fix-key-precise-swipe
Fix precise character deletion behaviour
This commit is contained in:
commit
ef075151fb
@ -26,6 +26,36 @@ import kotlin.math.*
|
||||
* Wrapper class which holds all enums, interfaces and classes for detecting a swipe gesture.
|
||||
*/
|
||||
abstract class SwipeGesture {
|
||||
companion object {
|
||||
/**
|
||||
* Returns a numeric value for a given [DistanceThreshold], based on the values defined in
|
||||
* the resources dimens.xml file.
|
||||
*/
|
||||
fun numericValue(context: Context, of: DistanceThreshold): Double {
|
||||
return when (of) {
|
||||
DistanceThreshold.VERY_SHORT -> context.resources.getDimension(R.dimen.gesture_distance_threshold_very_short)
|
||||
DistanceThreshold.SHORT -> context.resources.getDimension(R.dimen.gesture_distance_threshold_short)
|
||||
DistanceThreshold.NORMAL -> context.resources.getDimension(R.dimen.gesture_distance_threshold_normal)
|
||||
DistanceThreshold.LONG -> context.resources.getDimension(R.dimen.gesture_distance_threshold_long)
|
||||
DistanceThreshold.VERY_LONG -> context.resources.getDimension(R.dimen.gesture_distance_threshold_very_long)
|
||||
}.toDouble()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a numeric value for a given [VelocityThreshold], based on the values defined in
|
||||
* the resources dimens.xml file.
|
||||
*/
|
||||
fun numericValue(context: Context, of: VelocityThreshold): Double {
|
||||
return when (of) {
|
||||
VelocityThreshold.VERY_SLOW -> context.resources.getInteger(R.integer.gesture_velocity_threshold_very_slow)
|
||||
VelocityThreshold.SLOW -> context.resources.getInteger(R.integer.gesture_velocity_threshold_slow)
|
||||
VelocityThreshold.NORMAL -> context.resources.getInteger(R.integer.gesture_velocity_threshold_normal)
|
||||
VelocityThreshold.FAST -> context.resources.getInteger(R.integer.gesture_velocity_threshold_fast)
|
||||
VelocityThreshold.VERY_FAST -> context.resources.getInteger(R.integer.gesture_velocity_threshold_very_fast)
|
||||
}.toDouble()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class which detects swipes based on given [MotionEvent]s. Only supports single-finger swipes
|
||||
* and ignores additional pointers provided, if any.
|
||||
@ -50,14 +80,20 @@ abstract class SwipeGesture {
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
eventList.add(MotionEvent.obtainNoHistory(event))
|
||||
val firstEvent = eventList[indexFirst]
|
||||
val lastEvent = eventList[indexLastMoveRecognized]
|
||||
val diffX = event.x - lastEvent.x
|
||||
val diffY = event.y - lastEvent.y
|
||||
val distanceThresholdNV = numericValue(distanceThreshold) / 4.0f
|
||||
val distanceThresholdNV = numericValue(context, distanceThreshold) / 4.0f
|
||||
return if (abs(diffX) > distanceThresholdNV || abs(diffY) > distanceThresholdNV) {
|
||||
indexLastMoveRecognized = eventList.size - 1
|
||||
val direction = detectDirection(diffX.toDouble(), diffY.toDouble())
|
||||
listener.onSwipe(direction, Type.TOUCH_MOVE)
|
||||
listener.onSwipe(Event(
|
||||
direction = direction,
|
||||
type = Type.TOUCH_MOVE,
|
||||
diffX = event.x - firstEvent.x,
|
||||
diffY = event.y - firstEvent.y
|
||||
))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -67,7 +103,7 @@ abstract class SwipeGesture {
|
||||
val firstEvent = eventList[indexFirst]
|
||||
val diffX = event.x - firstEvent.x
|
||||
val diffY = event.y - firstEvent.y
|
||||
val distanceThresholdNV = numericValue(distanceThreshold)
|
||||
val distanceThresholdNV = numericValue(context, distanceThreshold)
|
||||
/*val velocityThresholdNV = numericValue(velocityThreshold)
|
||||
val velocity =
|
||||
((convertPixelsToDp(
|
||||
@ -78,7 +114,12 @@ abstract class SwipeGesture {
|
||||
// return if ((abs(diffX) > distanceThresholdNV || abs(diffY) > distanceThresholdNV) && velocity >= velocityThresholdNV) {
|
||||
return if ((abs(diffX) > distanceThresholdNV || abs(diffY) > distanceThresholdNV)) {
|
||||
val direction = detectDirection(diffX.toDouble(), diffY.toDouble())
|
||||
listener.onSwipe(direction, Type.TOUCH_UP)
|
||||
listener.onSwipe(Event(
|
||||
direction = direction,
|
||||
type = Type.TOUCH_UP,
|
||||
diffX = diffX,
|
||||
diffY = diffY
|
||||
))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -144,38 +185,10 @@ abstract class SwipeGesture {
|
||||
indexFirst = 0
|
||||
indexLastMoveRecognized = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a numeric value for a given [DistanceThreshold], based on the values defined in
|
||||
* the resources dimens.xml file.
|
||||
*/
|
||||
private fun numericValue(of: DistanceThreshold): Double {
|
||||
return when (of) {
|
||||
DistanceThreshold.VERY_SHORT -> context.resources.getDimension(R.dimen.gesture_distance_threshold_very_short)
|
||||
DistanceThreshold.SHORT -> context.resources.getDimension(R.dimen.gesture_distance_threshold_short)
|
||||
DistanceThreshold.NORMAL -> context.resources.getDimension(R.dimen.gesture_distance_threshold_normal)
|
||||
DistanceThreshold.LONG -> context.resources.getDimension(R.dimen.gesture_distance_threshold_long)
|
||||
DistanceThreshold.VERY_LONG -> context.resources.getDimension(R.dimen.gesture_distance_threshold_very_long)
|
||||
}.toDouble()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a numeric value for a given [VelocityThreshold], based on the values defined in
|
||||
* the resources dimens.xml file.
|
||||
*/
|
||||
private fun numericValue(of: VelocityThreshold): Double {
|
||||
return when (of) {
|
||||
VelocityThreshold.VERY_SLOW -> context.resources.getInteger(R.integer.gesture_velocity_threshold_very_slow)
|
||||
VelocityThreshold.SLOW -> context.resources.getInteger(R.integer.gesture_velocity_threshold_slow)
|
||||
VelocityThreshold.NORMAL -> context.resources.getInteger(R.integer.gesture_velocity_threshold_normal)
|
||||
VelocityThreshold.FAST -> context.resources.getInteger(R.integer.gesture_velocity_threshold_fast)
|
||||
VelocityThreshold.VERY_FAST -> context.resources.getInteger(R.integer.gesture_velocity_threshold_very_fast)
|
||||
}.toDouble()
|
||||
}
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun onSwipe(direction: Direction, type: Type): Boolean
|
||||
fun onSwipe(event: Event): Boolean
|
||||
}
|
||||
|
||||
enum class Direction {
|
||||
@ -189,6 +202,13 @@ abstract class SwipeGesture {
|
||||
LEFT,
|
||||
}
|
||||
|
||||
data class Event(
|
||||
val direction: Direction,
|
||||
val type: Type,
|
||||
val diffX: Float,
|
||||
val diffY: Float
|
||||
)
|
||||
|
||||
enum class Type {
|
||||
TOUCH_UP,
|
||||
TOUCH_MOVE;
|
||||
|
@ -101,7 +101,7 @@ class KeyView(
|
||||
private var themeValueCache: ThemeValueCache = ThemeValueCache()
|
||||
|
||||
var florisboard: FlorisBoard? = null
|
||||
private val swipeGestureDetector = SwipeGesture.Detector(context, this)
|
||||
val swipeGestureDetector = SwipeGesture.Detector(context, this)
|
||||
var touchHitBox: Rect = Rect(-1, -1, -1, -1)
|
||||
|
||||
init {
|
||||
@ -308,46 +308,32 @@ class KeyView(
|
||||
* Swipe event handler. Listens to touch_move left/right swipes and triggers the swipe action
|
||||
* defined in the prefs.
|
||||
*/
|
||||
override fun onSwipe(direction: SwipeGesture.Direction, type: SwipeGesture.Type): Boolean {
|
||||
override fun onSwipe(event: SwipeGesture.Event): Boolean {
|
||||
return when (data.code) {
|
||||
KeyCode.DELETE -> when (type) {
|
||||
SwipeGesture.Type.TOUCH_MOVE -> when (direction) {
|
||||
SwipeGesture.Direction.LEFT -> when (prefs.gestures.deleteKeySwipeLeft) {
|
||||
SwipeAction.DELETE_CHARACTERS_PRECISELY -> {
|
||||
florisboard?.activeEditorInstance?.apply {
|
||||
setSelection(
|
||||
if (selection.start > 0) { selection.start - 1 } else { selection.start },
|
||||
selection.end
|
||||
)
|
||||
}
|
||||
hasTriggeredGestureMove = true
|
||||
shouldBlockNextKeyCode = true
|
||||
true
|
||||
KeyCode.DELETE -> when (event.type) {
|
||||
SwipeGesture.Type.TOUCH_MOVE -> when (prefs.gestures.deleteKeySwipeLeft) {
|
||||
SwipeAction.DELETE_CHARACTERS_PRECISELY -> {
|
||||
val charWidth = SwipeGesture.numericValue(context, swipeGestureDetector.distanceThreshold) / 4.0f
|
||||
florisboard?.activeEditorInstance?.apply {
|
||||
setSelection(
|
||||
(selection.end - (event.diffX.times(-1) / charWidth).toInt()).coerceIn(0, selection.end),
|
||||
selection.end
|
||||
)
|
||||
}
|
||||
SwipeAction.DELETE_WORDS_PRECISELY -> {
|
||||
hasTriggeredGestureMove = true
|
||||
shouldBlockNextKeyCode = true
|
||||
true
|
||||
}
|
||||
SwipeAction.DELETE_WORDS_PRECISELY -> when (event.direction) {
|
||||
SwipeGesture.Direction.LEFT -> {
|
||||
florisboard?.activeEditorInstance?.apply {
|
||||
leftAppendWordToSelection()
|
||||
}
|
||||
|
||||
hasTriggeredGestureMove = true
|
||||
shouldBlockNextKeyCode = true
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
SwipeGesture.Direction.RIGHT -> when (prefs.gestures.deleteKeySwipeLeft) {
|
||||
SwipeAction.DELETE_CHARACTERS_PRECISELY -> {
|
||||
florisboard?.activeEditorInstance?.apply {
|
||||
setSelection(
|
||||
if (selection.start < selection.end) { selection.start + 1 } else { selection.start },
|
||||
selection.end
|
||||
)
|
||||
}
|
||||
shouldBlockNextKeyCode = true
|
||||
true
|
||||
}
|
||||
|
||||
SwipeAction.DELETE_WORDS_PRECISELY -> {
|
||||
SwipeGesture.Direction.RIGHT -> {
|
||||
florisboard?.activeEditorInstance?.apply {
|
||||
leftPopWordFromSelection()
|
||||
}
|
||||
@ -360,8 +346,8 @@ class KeyView(
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
KeyCode.SPACE -> when (type) {
|
||||
SwipeGesture.Type.TOUCH_MOVE -> when (direction) {
|
||||
KeyCode.SPACE -> when (event.type) {
|
||||
SwipeGesture.Type.TOUCH_MOVE -> when (event.direction) {
|
||||
SwipeGesture.Direction.UP -> {
|
||||
florisboard?.executeSwipeAction(prefs.gestures.spaceBarSwipeUp)
|
||||
shouldBlockNextKeyCode = true
|
||||
|
@ -103,6 +103,7 @@ class KeyboardView : LinearLayout, FlorisBoard.EventListener, SwipeGesture.Liste
|
||||
}
|
||||
if (!isPreviewMode) {
|
||||
themeManager.requestThemeUpdate(this)
|
||||
onWindowShown()
|
||||
} else {
|
||||
updateVisibility()
|
||||
}
|
||||
@ -138,6 +139,18 @@ class KeyboardView : LinearLayout, FlorisBoard.EventListener, SwipeGesture.Liste
|
||||
distanceThreshold = prefs.gestures.swipeDistanceThreshold
|
||||
velocityThreshold = prefs.gestures.swipeVelocityThreshold
|
||||
}
|
||||
for (row in children) {
|
||||
if (row is ViewGroup) {
|
||||
for (keyView in row.children) {
|
||||
if (keyView is KeyView) {
|
||||
keyView.swipeGestureDetector.apply {
|
||||
distanceThreshold = prefs.gestures.swipeDistanceThreshold
|
||||
velocityThreshold = prefs.gestures.swipeVelocityThreshold
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -244,10 +257,10 @@ class KeyboardView : LinearLayout, FlorisBoard.EventListener, SwipeGesture.Liste
|
||||
* Swipe event handler. Listens to touch_up swipes and executes the swipe action defined for it
|
||||
* in the prefs.
|
||||
*/
|
||||
override fun onSwipe(direction: SwipeGesture.Direction, type: SwipeGesture.Type): Boolean {
|
||||
override fun onSwipe(event: SwipeGesture.Event): Boolean {
|
||||
return when {
|
||||
initialKeyCode == KeyCode.DELETE -> {
|
||||
if (type == SwipeGesture.Type.TOUCH_UP && direction == SwipeGesture.Direction.LEFT &&
|
||||
if (event.type == SwipeGesture.Type.TOUCH_UP && event.direction == SwipeGesture.Direction.LEFT &&
|
||||
prefs.gestures.deleteKeySwipeLeft == SwipeAction.DELETE_WORD) {
|
||||
florisboard?.executeSwipeAction(prefs.gestures.deleteKeySwipeLeft)
|
||||
true
|
||||
@ -256,9 +269,9 @@ class KeyboardView : LinearLayout, FlorisBoard.EventListener, SwipeGesture.Liste
|
||||
}
|
||||
}
|
||||
initialKeyCode > KeyCode.SPACE && !popupManager.isShowingExtendedPopup -> when {
|
||||
!prefs.glide.enabled -> when (type) {
|
||||
!prefs.glide.enabled -> when (event.type) {
|
||||
SwipeGesture.Type.TOUCH_UP -> {
|
||||
val swipeAction = when (direction) {
|
||||
val swipeAction = when (event.direction) {
|
||||
SwipeGesture.Direction.UP -> prefs.gestures.swipeUp
|
||||
SwipeGesture.Direction.DOWN -> prefs.gestures.swipeDown
|
||||
SwipeGesture.Direction.LEFT -> prefs.gestures.swipeLeft
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
<PreferenceCategory
|
||||
app:iconSpaceReserved="false"
|
||||
app:key="gestures"
|
||||
app:key="general_gestures"
|
||||
app:title="@string/pref__gestures__general_title">
|
||||
|
||||
<ListPreference
|
||||
@ -73,7 +73,7 @@
|
||||
|
||||
<PreferenceCategory
|
||||
app:iconSpaceReserved="false"
|
||||
app:key="gestures"
|
||||
app:key="space_bar_gestures"
|
||||
app:title="@string/pref__gestures__space_bar_title">
|
||||
|
||||
<ListPreference
|
||||
@ -116,7 +116,7 @@
|
||||
|
||||
<PreferenceCategory
|
||||
app:iconSpaceReserved="false"
|
||||
app:key="gestures"
|
||||
app:key="other_gestures"
|
||||
app:title="@string/pref__gestures__other_title">
|
||||
|
||||
<ListPreference
|
||||
|
Loading…
Reference in New Issue
Block a user