Moved AccessHelper to an outer class

This commit is contained in:
merkost 2023-06-09 11:40:41 +10:00
parent 91852ed63e
commit e6a22e5920
3 changed files with 75 additions and 72 deletions

View File

@ -0,0 +1,68 @@
package com.simplemobiletools.keyboard.helpers
import android.graphics.Rect
import android.os.Bundle
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import androidx.customview.widget.ExploreByTouchHelper
import com.simplemobiletools.keyboard.views.MyKeyboardView
class AccessHelper(
private val keyboardView: MyKeyboardView,
private val keys: List<MyKeyboard.Key>
) : ExploreByTouchHelper(keyboardView) {
/**
* We need to populate the list with the IDs of all of the visible virtual views (the intervals in the chart).
* In our case, all keys are always visible, so well return a list of all IDs.
*/
override fun getVisibleVirtualViews(virtualViewIds: MutableList<Int>) {
val keysSize = keys.size
for (i in 0 until keysSize) {
virtualViewIds.add(i)
}
}
/**
* For this function, we need to return the ID of the virtual view thats under the x, y position,
* or ExploreByTouchHelper.HOST_ID if theres no item at those coordinates.
*/
override fun getVirtualViewAt(x: Float, y: Float): Int {
val rects = keys.map {
Rect(it.x, it.y, it.x + it.width, it.y + it.height)
}
rects.firstOrNull { it.contains(x.toInt(), y.toInt()) }?.let { exactRect ->
return rects.indexOf(exactRect)
} ?: return HOST_ID
}
/**
* This is where we provide all the metadata for our virtual view.
* We need to set the content description (or text, if its presented visually) and set the bounds in parent.
*/
override fun onPopulateNodeForVirtualView(virtualViewId: Int, node: AccessibilityNodeInfoCompat) {
node.className = keyboardView::class.simpleName
val key = keys.getOrNull(virtualViewId)
node.contentDescription = key?.getContentDescription(keyboardView.context) ?: ""
val bounds = updateBoundsForInterval(virtualViewId)
node.setBoundsInParent(bounds)
}
/**
* We need to set the content description (or text, if its presented visually) and set the bounds in parent.
* The bounds in the parent should match the logic in the onDraw() function.
*/
private fun updateBoundsForInterval(index: Int): Rect {
val keys = keys
val key = keys.getOrNull(index) ?: return Rect()
return Rect().apply {
left = key.x
top = key.y
right = key.x + key.width
bottom = key.y + key.height
}
}
override fun onPerformActionForVirtualView(virtualViewId: Int, action: Int, arguments: Bundle?): Boolean {
return false
}
}

View File

@ -43,7 +43,7 @@ class MyKeyboard {
var mMinWidth = 0 var mMinWidth = 0
/** List of keys in this keyboard */ /** List of keys in this keyboard */
var mKeys: MutableList<Key?>? = null var mKeys: MutableList<Key>? = null
/** Width of the screen available to fit the keyboard */ /** Width of the screen available to fit the keyboard */
private var mDisplayWidth = 0 private var mDisplayWidth = 0

View File

@ -10,7 +10,6 @@ import android.content.Intent
import android.graphics.* import android.graphics.*
import android.graphics.Paint.Align import android.graphics.Paint.Align
import android.graphics.drawable.* import android.graphics.drawable.*
import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.os.Message import android.os.Message
@ -24,8 +23,6 @@ import android.widget.TextView
import androidx.core.animation.doOnEnd import androidx.core.animation.doOnEnd
import androidx.core.animation.doOnStart import androidx.core.animation.doOnStart
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import androidx.customview.widget.ExploreByTouchHelper
import androidx.emoji2.text.EmojiCompat import androidx.emoji2.text.EmojiCompat
import androidx.emoji2.text.EmojiCompat.EMOJI_SUPPORTED import androidx.emoji2.text.EmojiCompat.EMOJI_SUPPORTED
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
@ -58,80 +55,14 @@ import java.util.*
class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int = 0) : View(context, attrs, defStyleRes) { class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int = 0) : View(context, attrs, defStyleRes) {
override fun dispatchHoverEvent(event: MotionEvent): Boolean { override fun dispatchHoverEvent(event: MotionEvent): Boolean {
return if (accessHelper.dispatchHoverEvent(event)) { return if (accessHelper?.dispatchHoverEvent(event) == true) {
true true
} else { } else {
super.dispatchHoverEvent(event) super.dispatchHoverEvent(event)
} }
} }
private val accessHelper = AccessHelper() private var accessHelper: AccessHelper? = null
inner class AccessHelper() : ExploreByTouchHelper(this) {
/**
* We need to populate the list with the IDs of all of the visible virtual views (the intervals in the chart).
* In our case, all keys are always visible, so well return a list of all IDs.
*/
override fun getVisibleVirtualViews(virtualViewIds: MutableList<Int>) {
val keysSize = mKeyboard?.mKeys?.size ?: 0
for (i in 0 until keysSize) {
virtualViewIds.add(i)
}
}
/**
* For this function, we need to return the ID of the virtual view thats under the x, y position,
* or ExploreByTouchHelper.HOST_ID if theres no item at those coordinates.
*/
override fun getVirtualViewAt(x: Float, y: Float): Int {
mKeyboard?.mKeys?.filterNotNull()?.let { keyList ->
val rects = keyList.map {
Rect(it.x, it.y, it.x + it.width, it.y + it.height)
}
rects.firstOrNull { it.contains(x.toInt(), y.toInt()) }?.let { exactRect ->
val exactIndexKey = rects.indexOf(exactRect)
return exactIndexKey
} ?: return HOST_ID
}
return HOST_ID
}
/**
* This is where we provide all the metadata for our virtual view.
* We need to set the content description (or text, if its presented visually) and set the bounds in parent.
*/
override fun onPopulateNodeForVirtualView(virtualViewId: Int, node: AccessibilityNodeInfoCompat) {
node.className = MyKeyboardView::class.simpleName
val key = mKeyboard?.mKeys?.get(virtualViewId)
node.contentDescription = key?.getContentDescription(context)
val bounds = updateBoundsForInterval(virtualViewId)
node.setBoundsInParent(bounds)
}
/**
* We need to set the content description (or text, if its presented visually) and set the bounds in parent.
* The bounds in the parent should match the logic in the onDraw() function.
*/
private fun updateBoundsForInterval(index: Int): Rect {
val keys = mKeyboard?.mKeys ?: return Rect()
val key = keys[index]!!
return Rect().apply {
left = key.x
top = key.y
right = key.x + key.width
bottom = key.y + key.height
}
}
override fun onPerformActionForVirtualView(virtualViewId: Int, action: Int, arguments: Bundle?): Boolean {
return false
}
}
init {
ViewCompat.setAccessibilityDelegate(this, accessHelper)
}
private var mKeyboard: MyKeyboard? = null private var mKeyboard: MyKeyboard? = null
private var mCurrentKeyIndex: Int = NOT_A_KEY private var mCurrentKeyIndex: Int = NOT_A_KEY
@ -335,6 +266,10 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
invalidateAllKeys() invalidateAllKeys()
computeProximityThreshold(keyboard) computeProximityThreshold(keyboard)
mMiniKeyboardCache.clear() mMiniKeyboardCache.clear()
accessHelper = AccessHelper(this, mKeyboard?.mKeys.orEmpty())
ViewCompat.setAccessibilityDelegate(this, accessHelper)
// Not really necessary to do every time, but will free up views // Not really necessary to do every time, but will free up views
// Switching to a different keyboard should abort any pending keys so that the key up // Switching to a different keyboard should abort any pending keys so that the key up
// doesn't get delivered to the old or new keyboard // doesn't get delivered to the old or new keyboard