【问题标题】:Why createKeyFromXml() doesn't create language switch key?为什么 createKeyFromXml() 不创建语言切换键?
【发布时间】:2018-06-05 14:08:04
【问题描述】:

我正在使用 Android 自定义键盘,它在我启动时崩溃。我发现createKeyFromXml() 方法有一行创建键,而这些键不会创建导致应用程序崩溃的语言切换键。

开发者指南对此并没有多说: https://developer.android.com/reference/android/inputmethodservice/Keyboard.html

LatinKeyboard.Java:

class LatinKeyboard extends Keyboard {
    private Key mEnterKey;
    private Key mSpaceKey;
    private Key mModeChangeKey;
    private Key mLanguageSwitchKey;
    private Key mSavedModeChangeKey;
    private Key mSavedLanguageSwitchKey;

    LatinKeyboard(Context context, int xmlLayoutResId) {
        super(context, xmlLayoutResId);
    }
    public LatinKeyboard(Context context, int layoutTemplateResId,
                         CharSequence characters, int columns, int horizontalPadding) {
        super(context, layoutTemplateResId, characters, columns, horizontalPadding);
    }
    @Override
    protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
                                   XmlResourceParser parser) {
        Key key = new LatinKey(res, parent, x, y, parser);
        Log.d("Keys", String.valueOf(key));
        if (key.codes[0] == 10) {
            mEnterKey = key;
        } else if (key.codes[0] == ' ') {
            mSpaceKey = key;
        } else if (key.codes[0] == Keyboard.KEYCODE_MODE_CHANGE) {
            mModeChangeKey = key;
            mSavedModeChangeKey = new LatinKey(res, parent, x, y, parser);
        } else if (key.codes[0] == LatinKeyboardView.KEYCODE_LANGUAGE_SWITCH) {
            mLanguageSwitchKey = key;
            mSavedLanguageSwitchKey = new LatinKey(res, parent, x, y, parser);
        }
        return key;
    }

    void setLanguageSwitchKeyVisibility(boolean visible) {
        if (visible) {
            mModeChangeKey.width = mSavedModeChangeKey.width;
            mModeChangeKey.x = mSavedModeChangeKey.x;
            mLanguageSwitchKey.width = mSavedLanguageSwitchKey.width;
            mLanguageSwitchKey.icon = mSavedLanguageSwitchKey.icon;
            mLanguageSwitchKey.iconPreview = mSavedLanguageSwitchKey.iconPreview;
        } else {
            mModeChangeKey.width = mSavedModeChangeKey.width + mSavedLanguageSwitchKey.width;
            mLanguageSwitchKey.width = 0;
            mLanguageSwitchKey.icon = null;
            mLanguageSwitchKey.iconPreview = null;
        }
    }
    void setImeOptions(Resources res, int options) {
        if (mEnterKey == null) {
            return;
        }
        switch (options&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) {
            case EditorInfo.IME_ACTION_GO:
                mEnterKey.iconPreview = null;
                mEnterKey.icon = null;
                mEnterKey.label = res.getText(R.string.label_go_key);
                break;
            case EditorInfo.IME_ACTION_NEXT:
                mEnterKey.iconPreview = null;
                mEnterKey.icon = null;
                mEnterKey.label = res.getText(R.string.label_next_key);
                break;
            case EditorInfo.IME_ACTION_SEARCH:
                mEnterKey.icon = res.getDrawable(R.drawable.ic_search_24dp);
                mEnterKey.label = null;
                break;
            case EditorInfo.IME_ACTION_SEND:
                mEnterKey.iconPreview = null;
                mEnterKey.icon = null;
                mEnterKey.label = res.getText(R.string.label_send_key);
                break;
            default:
                mEnterKey.icon = res.getDrawable(R.drawable.ic_check_circle_24dp);
                mEnterKey.label = null;
                break;
        }
    }
    void setSpaceIcon(final Drawable icon) {
        if (mSpaceKey != null) {
            mSpaceKey.icon = icon;
        }
    }
    private static class LatinKey extends Keyboard.Key {

        LatinKey(Resources res, Keyboard.Row parent, int x, int y,
                 XmlResourceParser parser) {
            super(res, parent, x, y, parser);
        }

        @Override
        public boolean isInside(int x, int y) {
            return super.isInside(x, codes[0] == KEYCODE_CANCEL ? y - 10 : y);
        }
    }
}

错误日志是:

E/AndroidRuntime: 致命异常: main 进程:com.sunzala.afghankeyboard,PID:8894 java.lang.NullPointerException 在 com.sunzala.afghankeyboard.android.LatinKeyboard.setLanguageSwitchKeyVisibility(LatinKeyboard.java:87) 在 com.sunzala.afghankeyboard.android.SoftKeyboard.setLatinKeyboard(SoftKeyboard.java:211) 在 com.sunzala.afghankeyboard.android.SoftKeyboard.onInitializeInterface(SoftKeyboard.java:151) 在 android.inputmethodservice.InputMethodService.initialize(InputMethodService.java:774)

我了解应用程序崩溃是因为 mModeChangeKeymLanguageSwitchKey 为空,这是因为我提到的方法。我检查了该方法并运行,但它没有创建与切换语言键码匹配的键。

如果有人有兴趣查看,我将应用程序上传到 GitHub: https://github.com/maihannijat/AndroidKeyboard

【问题讨论】:

  • 请提供足够的信息。没有人知道这个问题与你在your old question中提到的sample有关。
  • @Toris 这个问题与我之前的问题无关。应用程序崩溃,我找到了原因,但我无法修复它。如果您有具体问题,请告诉我。谢谢。
  • 从示例中,private void setLatinKeyboard(LatinKeyboard nextKeyboard) { final boolean shouldSupportLanguageSwitchKey = mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken()); nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey); } 我认为 NullPointerException 是由于“nextKeyboard”为空而引起的。
  • @Toris 感谢您的提示。让我检查一下,几分钟后给您回复。
  • 关于 'mLanguageSwitchKey' 部分:KeyEvent.KEYCODE_LANGUAGE_SWITCH > 在某些设备上,按 Shift+空格键可以执行相同的功能。我认为 key.codes[0] 与 KEYCODE_LANGUAGE_SWITCH 不匹配。 (或者如果存在匹配项,则可能在其他索引中)

标签: java android android-custom-keyboard


【解决方案1】:

从另一个question 中提到的sample 代码显示,如果“nextKeyboard”为空,则会抛出 NullPointerException。

private void setLatinKeyboard(LatinKeyboard nextKeyboard) {
    final boolean shouldSupportLanguageSwitchKey =
            mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken());
    nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey);
    mInputView.setKeyboard(nextKeyboard);
}

【讨论】:

    猜你喜欢
    • 2018-12-04
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多