5

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

@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()

只要我只想要普通字母 AZ 就可以了。在其他语言中,长按软键盘上的普通字母可以找到更多字母……但是,onKeyDown/Up 无法检测到这些替代字母。我只能检测到正常的字母,软键盘的标签。现在我的应用程序必须处理外国输入和字母,我已将键盘更改为土耳其语,我可以在键盘上找到 í ì ú ù 之类的字母,但如果我按下它们,我没有得到任何回应。不是 event.getDisplayLabel 也不是 event.getUnicodeChar(); 如何检测这些字母?

4

3 回答 3

3

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

实现您想要的最简单的方法是覆盖onKeyPreIme()视图上的方法。例如,如果您尝试从 EditText 捕获 onKeyDown,请创建一个新的扩展类EditText,并覆盖该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 上测试的。

于 2014-05-02T00:08:33.927 回答
2

编辑:

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

不要使用视图中的 onKeyDown,而是在活动级别覆盖 dispatchKeyEvent。这将在您的关键事件到达窗口管理器之前处理它,因此请确保在您未明确处理的任何关键事件上调用 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() 只会为您提供键盘上显示的键,正如您所指出的,它不一定是用户选择的字符。

于 2013-01-08T15:37:13.077 回答
1

知道了 :)

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 也可以在手机上工作。但是在平板电脑上我仍然没有得到删除键的回调。似乎是一个糟糕的错误,因为今天早上它即使在平板电脑上也能正常工作。

于 2013-01-09T15:29:27.840 回答