do not complicate the code with nearest keys, we have no corrections
This commit is contained in:
parent
8a1b68f826
commit
aedc35ff02
|
@ -6,7 +6,6 @@ import android.content.res.Resources
|
|||
import android.content.res.TypedArray
|
||||
import android.content.res.XmlResourceParser
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.SparseArray
|
||||
import android.util.TypedValue
|
||||
import android.util.Xml
|
||||
import android.view.inputmethod.EditorInfo
|
||||
|
@ -45,14 +44,10 @@ class MyKeyboard {
|
|||
/** Width of the screen available to fit the keyboard */
|
||||
private var mDisplayWidth = 0
|
||||
|
||||
/** What icon should we show at Enter key */
|
||||
/** What icon should we show at Enter key */
|
||||
private var mEnterKeyType = IME_ACTION_NONE
|
||||
|
||||
/** Keyboard mode, or zero, if none. */
|
||||
private var mCellWidth = 0
|
||||
private var mCellHeight = 0
|
||||
private var mGridNeighbors: SparseArray<IntArray?>? = null
|
||||
private var mProximityThreshold = 0
|
||||
/** Keyboard rows */
|
||||
private val mRows = ArrayList<Row?>()
|
||||
|
||||
companion object {
|
||||
|
@ -61,22 +56,12 @@ class MyKeyboard {
|
|||
private const val TAG_KEY = "Key"
|
||||
private const val EDGE_LEFT = 0x01
|
||||
private const val EDGE_RIGHT = 0x02
|
||||
private const val EDGE_TOP = 0x04
|
||||
private const val EDGE_BOTTOM = 0x08
|
||||
const val KEYCODE_SHIFT = -1
|
||||
const val KEYCODE_MODE_CHANGE = -2
|
||||
const val KEYCODE_ENTER = -4
|
||||
const val KEYCODE_DELETE = -5
|
||||
const val KEYCODE_SPACE = 32
|
||||
|
||||
// Variables for pre-computing nearest keys.
|
||||
private const val GRID_WIDTH = 10
|
||||
private const val GRID_HEIGHT = 5
|
||||
private const val GRID_SIZE = GRID_WIDTH * GRID_HEIGHT
|
||||
|
||||
/** Number of key widths from current touch point to search for nearest keys. */
|
||||
private const val SEARCH_DISTANCE = 1.8f
|
||||
|
||||
fun getDimensionOrFraction(a: TypedArray, index: Int, base: Int, defValue: Int): Int {
|
||||
val value = a.peekValue(index) ?: return defValue
|
||||
return when (value.type) {
|
||||
|
@ -174,7 +159,7 @@ class MyKeyboard {
|
|||
|
||||
/**
|
||||
* Flags that specify the anchoring to edges of the keyboard for detecting touch events that are just out of the boundary of the key.
|
||||
* This is a bit mask of [MyKeyboard.EDGE_LEFT], [MyKeyboard.EDGE_RIGHT], [MyKeyboard.EDGE_TOP] and [MyKeyboard.EDGE_BOTTOM].
|
||||
* This is a bit mask of [MyKeyboard.EDGE_LEFT], [MyKeyboard.EDGE_RIGHT].
|
||||
*/
|
||||
private var edgeFlags = 0
|
||||
|
||||
|
@ -240,24 +225,10 @@ class MyKeyboard {
|
|||
fun isInside(x: Int, y: Int): Boolean {
|
||||
val leftEdge = edgeFlags and EDGE_LEFT > 0
|
||||
val rightEdge = edgeFlags and EDGE_RIGHT > 0
|
||||
val topEdge = edgeFlags and EDGE_TOP > 0
|
||||
val bottomEdge = edgeFlags and EDGE_BOTTOM > 0
|
||||
return ((x >= this.x || leftEdge && x <= this.x + width)
|
||||
&& (x < this.x + width || rightEdge && x >= this.x)
|
||||
&& (y >= this.y || topEdge && y <= this.y + height)
|
||||
&& (y < this.y + height || bottomEdge && y >= this.y))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square of the distance between the center of the key and the given point.
|
||||
* @param x the x-coordinate of the point
|
||||
* @param y the y-coordinate of the point
|
||||
* @return the square of the distance of the point from the center of the key
|
||||
*/
|
||||
fun squaredDistanceFrom(x: Int, y: Int): Int {
|
||||
val xDist = this.x + width / 2 - x
|
||||
val yDist = this.y + height / 2 - y
|
||||
return xDist * xDist + yDist * yDist
|
||||
&& (y >= this.y && y <= this.y + height)
|
||||
&& (y < this.y + height && y >= this.y))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,60 +303,6 @@ class MyKeyboard {
|
|||
return false
|
||||
}
|
||||
|
||||
private fun computeNearestNeighbors() {
|
||||
// Round-up so we don't have any pixels outside the grid
|
||||
mCellWidth = (mMinWidth + GRID_WIDTH - 1) / GRID_WIDTH
|
||||
mCellHeight = (mHeight + GRID_HEIGHT - 1) / GRID_HEIGHT
|
||||
mGridNeighbors = SparseArray<IntArray?>(GRID_SIZE)
|
||||
val indices = IntArray(mKeys!!.size)
|
||||
val gridWidth: Int = GRID_WIDTH * mCellWidth
|
||||
val gridHeight: Int = GRID_HEIGHT * mCellHeight
|
||||
var x = 0
|
||||
while (x < gridWidth) {
|
||||
var y = 0
|
||||
while (y < gridHeight) {
|
||||
var count = 0
|
||||
for (i in mKeys!!.indices) {
|
||||
val key = mKeys!![i]
|
||||
if (key!!.squaredDistanceFrom(x, y) < mProximityThreshold || key.squaredDistanceFrom(
|
||||
x + mCellWidth - 1, y
|
||||
) < mProximityThreshold || (key.squaredDistanceFrom(x + mCellWidth - 1, y + mCellHeight - 1)
|
||||
< mProximityThreshold) || key.squaredDistanceFrom(x, y + mCellHeight - 1) < mProximityThreshold
|
||||
) {
|
||||
indices[count++] = i
|
||||
}
|
||||
}
|
||||
|
||||
val cell = IntArray(count)
|
||||
System.arraycopy(indices, 0, cell, 0, count)
|
||||
mGridNeighbors!!.put(y / mCellHeight * GRID_WIDTH + x / mCellWidth, cell)
|
||||
y += mCellHeight
|
||||
}
|
||||
x += mCellWidth
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the indices of the keys that are closest to the given point.
|
||||
* @param x the x-coordinate of the point
|
||||
* @param y the y-coordinate of the point
|
||||
* @return the array of integer indices for the nearest keys to the given point. If the given point is out of range, then an array of size zero is returned.
|
||||
*/
|
||||
fun getNearestKeys(x: Int, y: Int): IntArray {
|
||||
if (mGridNeighbors == null) {
|
||||
computeNearestNeighbors()
|
||||
}
|
||||
|
||||
if (x in 0 until mMinWidth && y >= 0 && y < mHeight) {
|
||||
val index = y / mCellHeight * GRID_WIDTH + x / mCellWidth
|
||||
if (index < GRID_SIZE) {
|
||||
return mGridNeighbors!![index]!!
|
||||
}
|
||||
}
|
||||
|
||||
return IntArray(0)
|
||||
}
|
||||
|
||||
private fun createRowFromXml(res: Resources, parser: XmlResourceParser?): Row {
|
||||
return Row(res, this, parser)
|
||||
}
|
||||
|
@ -458,8 +375,6 @@ class MyKeyboard {
|
|||
mDefaultWidth = getDimensionOrFraction(a, R.styleable.MyKeyboard_keyWidth, mDisplayWidth, mDisplayWidth / 10)
|
||||
mDefaultHeight = res.getDimension(R.dimen.key_height).toInt()
|
||||
mDefaultHorizontalGap = getDimensionOrFraction(a, R.styleable.MyKeyboard_horizontalGap, mDisplayWidth, 0)
|
||||
mProximityThreshold = (mDefaultWidth * SEARCH_DISTANCE).toInt()
|
||||
mProximityThreshold *= mProximityThreshold // Square it for comparison
|
||||
a.recycle()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -678,41 +678,16 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||
}
|
||||
}
|
||||
|
||||
private fun getKeyIndices(x: Int, y: Int): Int {
|
||||
val keys = mKeys
|
||||
var primaryIndex = NOT_A_KEY
|
||||
var closestKey = NOT_A_KEY
|
||||
var closestKeyDist = mProximityThreshold + 1
|
||||
val nearestKeyIndices = mKeyboard!!.getNearestKeys(x, y)
|
||||
val keyCount = nearestKeyIndices.size
|
||||
|
||||
for (i in 0 until keyCount) {
|
||||
val key = keys[nearestKeyIndices[i]]
|
||||
val dist = 0
|
||||
val isInside = key.isInside(x, y)
|
||||
if (isInside) {
|
||||
primaryIndex = nearestKeyIndices[i]
|
||||
}
|
||||
|
||||
if (isInside && key.code > KEYCODE_SPACE) {
|
||||
if (dist < closestKeyDist) {
|
||||
closestKeyDist = dist
|
||||
closestKey = nearestKeyIndices[i]
|
||||
}
|
||||
}
|
||||
private fun getPressedKeyIndex(x: Int, y: Int): Int {
|
||||
return mKeys.indexOfFirst {
|
||||
it.isInside(x, y)
|
||||
}
|
||||
|
||||
if (primaryIndex == NOT_A_KEY) {
|
||||
primaryIndex = closestKey
|
||||
}
|
||||
|
||||
return primaryIndex
|
||||
}
|
||||
|
||||
private fun detectAndSendKey(index: Int, x: Int, y: Int, eventTime: Long) {
|
||||
if (index != NOT_A_KEY && index < mKeys.size) {
|
||||
val key = mKeys[index]
|
||||
getKeyIndices(x, y)
|
||||
getPressedKeyIndex(x, y)
|
||||
mOnKeyboardActionListener!!.onKey(key.code)
|
||||
mLastTapTime = eventTime
|
||||
}
|
||||
|
@ -1095,7 +1070,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||
|
||||
val action = me.actionMasked
|
||||
val eventTime = me.eventTime
|
||||
val keyIndex = getKeyIndices(touchX, touchY)
|
||||
val keyIndex = getPressedKeyIndex(touchX, touchY)
|
||||
|
||||
// Ignore all motion events until a DOWN.
|
||||
if (mAbortKey && action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_CANCEL) {
|
||||
|
@ -1118,7 +1093,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||
|
||||
val newPointerX = me.getX(1).toInt()
|
||||
val newPointerY = me.getY(1).toInt()
|
||||
val secondKeyIndex = getKeyIndices(newPointerX, newPointerY)
|
||||
val secondKeyIndex = getPressedKeyIndex(newPointerX, newPointerY)
|
||||
showPreview(secondKeyIndex)
|
||||
detectAndSendKey(secondKeyIndex, newPointerX, newPointerY, eventTime)
|
||||
|
||||
|
|
|
@ -118,9 +118,7 @@
|
|||
app:keyEdgeFlags="left"
|
||||
app:keyLabel="123"
|
||||
app:keyWidth="15%p" />
|
||||
<Key
|
||||
app:keyLabel=","
|
||||
app:keyWidth="10%p" />
|
||||
<Key app:keyLabel="," />
|
||||
<Key
|
||||
app:code="32"
|
||||
app:isRepeatable="true"
|
||||
|
|
Loading…
Reference in New Issue