当前位置: 首页 > 知识库问答 >
问题:

Android SoftKeyboard onKeyDown/Up无法检测“替代”键

苏畅
2023-03-14

我有一个视图为我处理输入,我弹出一个键盘并设置视图可聚焦。现在我可以得到某些按键...

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_DEL) {
    } else if (keyCode == KeyEvent.KEYCODE_BACK) {
    } else if (keyCode == KeyEvent.KEYCODE_ENTER) {
    } else {
    }
}

等等……我使用的字符被按下。

event.getDisplayLabel()

只要我只想要普通的字母A-Z,这就行了。在其他语言中,长按软键盘上的普通字母可以访问更多字母…但是,onKeyDown/Up无法检测到这些替代字母。我只能检测到正常的字母,软键盘的标签。现在我的应用程序必须处理外国输入和字母,我已经将键盘改为土耳其语,并且我可以在键盘上找到类似于“íüöó”的字母,但如果我按下它们,我不会得到任何响应。与事件无关。getDisplayLabel或事件。获取Unicode字符();如何检测这些字母?

共有3个答案

松阳泽
2023-03-14

明白了:)

public boolean onKey(View v, int keyCode, KeyEvent event) {
    if(event.getAction()==KeyEvent.ACTION_DOWN) return true;
    if(keyCode==KeyEvent.KEYCODE_ALT_LEFT || keyCode==KeyEvent.KEYCODE_ALT_RIGHT || keyCode==KeyEvent.KEYCODE_SHIFT_LEFT || keyCode==KeyEvent.KEYCODE_SHIFT_RIGHT) return true;

    if (keyCode == KeyEvent.KEYCODE_DEL) {
        doBackspace();
        return true;
    } else if (keyCode == KeyEvent.KEYCODE_BACK) {
        if(this.avl!=null) this.avl.onInputCancelled(this);
        return false;
    } else if (keyCode == KeyEvent.KEYCODE_ENTER) {
        inputstarted=false;
        if(this.avl!=null) this.avl.onInputFinished(this,this.text,celldata);
        return true;
    }   

    String key = "";
    if (event.getAction()==KeyEvent.ACTION_UP) key = String.valueOf((char)event.getUnicodeChar()).toUpperCase();
    else if (event.getAction()==KeyEvent.ACTION_MULTIPLE) key = String.valueOf(event.getCharacters()).toUpperCase();
    return process(key);
}

重要的部分是阻止ALT_LEFT/SHIFT_LEFT/etc键码,区分ACTION_UP/ACTION_MULTIPLE,使用event.getUnicodeChar()或event.getCharacters()。

它现在工作,我可以在手机上获得所有的字符,甚至KEYCODE_DEL工作。但是在平板电脑上,我仍然没有收到删除键的回调。似乎是一个坏错误,因为今天早上它甚至在平板电脑上也工作得很好。

白宏大
2023-03-14

编辑:

我不确定是什么原因导致onKeyDown根本没有被调用。也许是你的观点有问题?因为这个可能会有比我的解决方案更好的答案。无论哪种方式,这都可能奏效:

在活动级别覆盖dispatchKeyEvent,而不是使用视图中的onKeyDown。这将在到达窗口管理器之前处理您的键事件,因此请确保对任何未显式处理的键事件调用super。

使用ACTION_DOWN的示例(因为每个事件都有ACTION_UP和ACTION_DOWN),因为您的示例使用了onKeyDown:

@Override
public boolean dispatchKeyEvent(KeyEvent event){
    if(event.getAction() == KeyEvent.ACTION_UP) {
        return super.dispatchKeyEvent(event);
    }

    if (keyCode == KeyEvent.KEYCODE_DEL) {
    } else if (keyCode == KeyEvent.KEYCODE_BACK) {
    } else if (keyCode == KeyEvent.KEYCODE_ENTER) {
    } else {
        return super.dispatchKeyEvent(event);
    }
}

现在(很抱歉)

你可以试试:

char key = (char)event.getUnicodeChar();

而不是

char key = event.getDisplayLabel();

getDisplayLabel()将只提供键盘上显示的键,正如您所指出的,该键不一定是用户选择的字符。

谷翰飞
2023-03-14

当键盘打开时,onKeyDown()onKeyUp() 方法无法正常工作,因为 Android 将屏幕键盘视为单独的活动。

实现所需内容的最简单方法是在视图上重写 onKeyPreIme() 方法。例如,如果您尝试从编辑文本中捕获 onKeyDown,请创建一个扩展编辑文本的新类,并重写 onKeyPreIme() 方法:

public class LoseFocusEditText extends EditText {

    private Context mContext;

    protected final String TAG = getClass().getName();

    public LoseFocusEditText(Context context) {
        super(context);
        mContext = context;
    }

    public LoseFocusEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    public LoseFocusEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
    }

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {

            //hide keyboard
            InputMethodManager mgr = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
            mgr.hideSoftInputFromWindow(this.getWindowToken(), 0);

            //lose focus
            this.clearFocus();

            return true;
        }
        return false;
    }
}

这是在kitkat / htc one上测试的。

 类似资料:
  • 我在使用JProfiler时面临一个问题:问题是它无法检测正在运行的WebSphere的JVM。 我看到WebSphere作为本地系统帐户作为Windows服务运行。因此,我尝试了“show Services”选项,但它仍然无法检测到JVM。 解决这个问题真的花了我很多时间,有人能帮我吗?

  • 当我尝试切换到git视图时,VisualStudio代码报告“您的系统上似乎没有安装git”。我知道我已经安装了git,并被其他git客户端使用。我想如果我按照VisualStudio代码的指示重新安装git(“用巧克力安装或从git scm.com下载”),它可能会解决问题,但我不想搞乱我系统上现有的git客户端。是否有可靠的方法来配置VisualStudio代码,以便它可以找到现有的git安装

  • 我正在Ubuntu 18.04服务器上用OpenJDK 11运行Tomcat 9(作为用户)。我希望能够将JProfiler 11连接到Tomcat进程。 在过去,我只是使用这个选项通过ssh连接到远程JVM,而JProfiler可以定位进程。在这台机器上,JProfiler从未找到Tomcat进程。 我尝试使用su和sudo选项切换到tomcat用户。我甚至启用了直接作为tomcat登录。无论如

  • Android Studio项目检测到android_home=C:\users\user\appdata\local\Android\sdk java_home=C:\program files\java\jdk1.8.0_181\bin(节点:3276)unhandledpromiseerejectionwarning:Cordovaerror:Requirements check for J

  • 我想用toolchain版本4.4.3(用于工作armeabi libs) 我下载了最新的Android SDK、NDK和其他所需的工具 我还下载了ndk-legacy-toolschains并复制了“path_to_ndk/toolchains”下的内容 我试图用下面的脚本配置qt5 但是它失败了:无法检测Android NDK工具链。请使用-android-toolchain-version指

  • 我有一个页面,需要使用Selenium网络驱动程序自动化。 我的页面HTML(由火虫检查): 在这里,我尝试了然后。尝试逐个索引,帧名称,Xpath,类名,名称找到帧,但都是徒劳的。 我的驱动程序无法找到父框架,因此无法找到其中的任何元素。请帮我解决这个问题。