使用JavaScript捕获在Android虚拟键盘上键入的键

wb1gzix0  于 2023-05-05  发布在  Android
关注(0)|答案(8)|浏览(224)

我有一个带有textarea的网页,我需要捕获用户键入的键(这样我就可以用不同的unicode字符替换键入的键)。代码如下:

$("#myTextArea").bind('keypress', function(event) {

    var keyInput = event.which;
   // call other functions

});

上面的代码适用于PC和iPhone/Safari。然而,在Android**(三星)平板电脑上使用Chrome时,它失败。由于某些原因,当我在android虚拟(软)键盘上键入时,“keypress”事件没有触发**。Android版本是5.0.2。
如果我尝试使用**“keyUp”或“keyDown”,它总是返回229的所有字符**(除了回车键,空格,退格键等)。
即使keyCode始终为229,文本区域也会显示用户键入的正确字符。这意味着设备知道输入的是哪个键,但不知何故,我无法使用javascript处理此事件(和键代码)。
以下是我迄今为止尝试过的替代方案及其结果:

$("#mainTextArea").on("keydown keyup", function(event) { 
    // event.which and event.keyCode both return 229

$(document).on('keypress', function(event) { 
    // function is not triggered

$('#myTextArea').bind('input keypress', function(event) { 
   // comes inside function, but keyCode and which are undefined

关于这个问题的任何帮助都是感激的。

wz8daaqr

wz8daaqr1#

不幸的是,你似乎不能在这里做很多事情。Keypress事件已弃用,因此未激发。229在keyup和keydown上表示键盘缓冲区忙碌。原因-当你按下一个键-输入仍然不能保证是什么用户按下,因为自动建议和其他事件,可能会立即跟进,并无效的事件。虽然在我看来,最好先发送密钥,然后在自动建议上触发另一个事件,这样你就可以单独对它采取行动...
我目前所知道的唯一一件事是同时附加到- keydown和keyup上,存储keydown上的值,获取keyup上的值并找到delta,这就是用户按下的值。不幸的是,这将不适用于非输入控件(例如- 身体或类似的东西)。也许不是你想听到的答案,但仍然。

o7jaxewo

o7jaxewo2#

我在为我正在做的一个项目做研究时遇到了这个讨论。我必须为一个移动的应用程序创建输入掩码,Pavel Donchev的回答让我思考在Android中如何捕获键。在我的具体项目中,keydown和keyup是不够的,因为keyup事件只在键被释放后触发,所以它意味着后期验证,所以我对输入事件做了更多的研究(和大量的试验和错误),并使其工作。

var input = document.getElementById('credit-card-mask'),
    oldValue,
    newValue,
    difference = function(value1, value2) {
      var output = [];
      for(i = 0; i < value2.length; i++) {
        if(value1[i] !== value2[i]) {
          output.push(value2[i]);
        }
      }
      return output.join("");
    },
    keyDownHandler = function(e) {
      oldValue = input.value;
      document.getElementById("onkeydown-result").innerHTML = input.value;
    },
    inputHandler = function(e) {
      newValue = input.value;
      document.getElementById("oninput-result").innerHTML = input.value;
      document.getElementById("typedvalue-result").innerHTML = difference(oldValue, newValue);
    }
;

input.addEventListener('keydown', keyDownHandler);
input.addEventListener('input', inputHandler);
<input type="text" id="credit-card-mask" />
<div id="result">
  <h4>on keydown value</h4>
  <div id="onkeydown-result"></div>
  <h4>on input value</h4>
  <div id="oninput-result"></div>
  <h4>typed value</h4>
  <div id="typedvalue-result"></div>
</div>

oninput事件是在keydown事件之后触发的,这是我的验证的最佳时机。
我把整件事都写在一篇文章里了。如果你好奇,你可以阅读here

kmynzznz

kmynzznz3#

我也遇到了同样的问题。有几种解释,但无论如何,似乎奇怪的是,没有提供解决方案。目前我通过捕获oninput事件来解决这个问题。
“此事件类似于onchange事件。不同之处在于oninput事件在元素的值更改后立即发生,而onchange事件发生在元素失去焦点时,在内容更改后“
这个事件也支持插入文本,从粘贴文本或从更正和建议。
它没有给予我完美的解决方案,因为我只能在输入文本后操作它,但目前它是我最好的解决方案。
如果有人有更好的解决方案,我会很高兴听到它。

dba5bblo

dba5bblo4#

只要检查你输入的字符keyCode,如果是0或者229,那么这里是函数getKeyCode(),它使用JS的charCodeAt返回KeyCode,它将输入字符串作为参数,返回最后一个字符的keycode。

var getKeyCode = function (str) {
    return str.charCodeAt(str.length);
}

$('#myTextfield').on('keyup',function(e) {
    // For android chrome keycode fix
    if (navigator.userAgent.match(/Android/i)) {
        var inputValue = this.value;
        var charKeyCode = e.keyCode || e.which;
        if (charKeyCode == 0 || charKeyCode == 229) {
            charKeyCode = getKeyCode(inputValue);
            alert(charKeyCode+' key Pressed');
        } else {
           alert(charKeyCode+' key Pressed');
        }
    }
});
jgzswidk

jgzswidk5#

有一个textInput事件,它给出了输入的字符

const inputField = document.getElementById('wanted-input-field');

inputField.addEventListener('textInput', function(e) {
    // e.data will be the 1:1 input you done
    const char = e.data; // In our example = "a"

    // If you want the keyCode..
    const keyCode = char.charCodeAt(0); // a = 97

    // Stop processing if "a" is pressed
    if (keyCode === 97) {
        e.preventDefault();
        return false;
    }
    return true;
});
scyqe7ek

scyqe7ek6#

我最近在我们的Astro AI辅助电子邮件应用程序的最新版本中实现了“提及”功能。基本上,你在我们的合成web视图中输入“@”,你会得到一个自动完成建议的列表。我们,像大多数其他人一样,试图在JavaScript中解决这个问题。最终成功的是一个原生的解决方案。如果您@Override WebView的onCreateInputConnection()方法,则可以使用自定义类 Package super.onCreateInputConnection()结果(它只是一个InputConnection接口)。然后在你的 Package 器实现中,你可以通过commitText()或setComposingText()或者其他一些特定于你所寻找的方法来捕获输入......比如删除。我不知道你是否会得到任何回调控制字符,如向上和向下箭头,但也许这可以是一个地方开始解决您的具体问题。

uklbhaso

uklbhaso7#

您可以通过使用selectionstart属性从不同的Angular 来处理它:
返回/设置所选文本的起始索引。如果没有选择任何内容,则返回文本输入光标(插入符号)在<input>元素中的位置[也适用于<textarea>]。
资料来源:MDN
我在自己的应用程序中做了这样的事情,它一直可靠地工作...

document.querySelector('textarea').addEventListener('input', (e) => {
  const elInput = e.target;
  // Get start of selection (caret offset when typing)
  const nSelStart = elInput.selectionStart;
  // Get last typed character (modify for your own needs)
  const sLastTyped = elInput.value.substr(nSelStart-1, 1);
  console.log('Last typed character:', sLastTyped);
});
textarea {
  width: 99%;
  height: 4rem;
}
<textarea placeholder="Enter something using Android soft keyboard"></textarea>

Codepen:https://codepen.io/thdoan/full/dymPwVY

k4aesqcs

k4aesqcs8#

我发现了!
这是一个100%有效的解决方案,可以在任何地方使用每个功能,甚至包括iOS上的表情符号建议和任何粘贴的内容。我使用子字符串比较来查找从onInput到onInput发生变化的实际内容。
指出从中删除文本和从中插入文本的点。
评分和选择作为答案是赞赏。

var x = document.getElementById("area"),
    text = x.value,
    event_count = 0



function find_Entered_And_Removed_Substrings(
    previous_string, current_string, pos
) {
    let
        right_pos = pos,
        right_boundary_of_removed =
            previous_string.length -
            (
                current_string.length -
                pos
            ),
        left_max_pos = Math.min(
            pos,
            right_boundary_of_removed
        ),
        left_pos = left_max_pos

    for (
        let x = 0; x < left_max_pos; x++
    ) {
        if (
            previous_string[x] !==
            current_string[x]
        ) {
            left_pos = x
            break
        }
    }


    return {
        left: left_pos,
        right: pos,
        removed_left: left_pos,
        removed_right: right_boundary_of_removed
    }
}

x.oninput =
    (e) => {
        // debugger;
        let
            cur_text = x.value,
            positions =
                find_Entered_And_Removed_Substrings(
                    text, cur_text, Math.max(
                        x.selectionStart, x.selectionEnd
                    )
                )
        console.log(positions)
        let
            entered =
                cur_text.substring(
                    positions.left, positions.right
                ),
            removed =
                text.substring(
                    positions.removed_left, positions.removed_right
                )


        if (
            entered.length >
            0 ||
            removed.length >
            0
        ) {
            document.getElementById("entered")
                .innerHTML +=
                entered

            document.getElementById("removed")
                .innerHTML +=
                removed

            document.getElementById("events")
                .innerHTML =
                event_count++
        }


        text = cur_text
    }
<textarea id="area"></textarea>
<br/>
<pre id="entered"></pre>
<br/>
<div id="events"></div>
<pre id="removed"></pre>

相关问题