Android SoftKeyboard onKeyDown / Up没有检测到“替代”键

时间:2013-01-08 14:48:52

标签: android android-softkeyboard

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

@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无法检测到这些替代字母。我只能检测正常的字母,软键盘的标签。 现在我的应用程序必须处理外国输入和字母,我已将键盘更改为土耳其语,我可以在键盘上找到类似í“ú”的字母,但如果我按下它们,我就不会得到任何回复。不是与event.getDisplayLabel或event.getUnicodeChar(); 我该如何检测这些字母?

3 个答案:

答案 0 :(得分:3)

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

实现目标的最简单方法是在视图上覆盖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上测试的。

答案 1 :(得分:1)

编辑:

我不确定是什么导致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()只会为您提供键盘上显示的键,正如您所指出的那样,键不一定是用户选择的字符。

答案 2 :(得分: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在移动设备上运行。但是在平板电脑上,我仍然没有收到删除密钥的回调。看起来像一个坏的错误,因为今天早上它甚至在平板电脑上工作正常。