提问人:hldev 提问时间:1/21/2023 最后编辑:hldev 更新时间:1/23/2023 访问量:113
如何使用 InputConnection 模拟具有逐个字符延迟的键入?
How to simulate typing with char-by-char delay using InputConnection?
问:
我需要在 WebView 上使用软输入键盘模拟具有逐个字符延迟的文本输入。我不能使用 WebView#dispatchKeyEvent,因为它不适合键入 Unicode 文本,并且不能模拟软输入键盘。
我正在重写 WebView#onCreateInputConnection 以获取对 webview 正在使用的实际输入连接的引用,以便我可以像软输入键盘一样向它发送输入:
class CustomWebView(context: Context, attrs: AttributeSet): WebView(context, attrs) {
private var inputConnection: InputConnection? = null
override fun onCreateInputConnection(outAttrs: EditorInfo?): InputConnection? {
val newInputConnection = super.onCreateInputConnection(outAttrs) ?: return inputConnection
inputConnection = newInputConnection
return newInputConnection
}
suspend fun sendTextInput(text: String, keyDelayStart: Long, keyDelayEnd: Long) {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager ?:
throw Exception("could not get system's InputMethodManager")
requestFocus()
val defer = CompletableDeferred<Int>()
// AsyncResultReceiver is a custom ResultReceiver which resolves a deferred on the callback
imm.showSoftInput(this, 0, AsyncResultReceiver(WeakReference(defer)))
val result = defer.await()
if (result == InputMethodManager.RESULT_HIDDEN || result == InputMethodManager.RESULT_UNCHANGED_HIDDEN)
throw Exception("could not show IME keyboard")
val ic = onCreateInputConnection(EditorInfo()) ?:
throw Exception("could not create InputConnection")
for (char in text) {
ic.commitText(char.toString(), 1)
delay(Random.nextLong(keyDelayStart, keyDelayEnd))
}
imm.hideSoftInputFromWindow(windowToken, 0)
}
}
我通过在输入字段上键入来测试,但是在键入下一个字符时,它会清除以前的字符:Hello, world!
向后键入时,请完全键入:ic.commitText(char.toString(), 0)
该测试在 Android 12 上运行。
答:
1赞
hldev
1/23/2023
#1
InputConnection#commitText()
替换实际合成区域的内容。要添加新字符,您需要将合成区域(“光标”)向前移动。尝试:InputConnection#setComposingRegion()
for (i in text.indices) {
ic.setComposingRegion(i, i + 1)
ic.commitText(text[i].toString(), 1)
delay(Random.nextLong(keyDelayStart, keyDelayEnd))
}
评论