为什么 createKeyFromXml() 不创建语言切换键?
Why createKeyFromXml() doesn't create language switch key?
我正在开发 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: FATAL EXCEPTION: main
Process: com.sunzala.afghankeyboard, PID: 8894
java.lang.NullPointerException
at com.sunzala.afghankeyboard.android.LatinKeyboard.setLanguageSwitchKeyVisibility(LatinKeyboard.java:87)
at com.sunzala.afghankeyboard.android.SoftKeyboard.setLatinKeyboard(SoftKeyboard.java:211)
at com.sunzala.afghankeyboard.android.SoftKeyboard.onInitializeInterface(SoftKeyboard.java:151)
at android.inputmethodservice.InputMethodService.initialize(InputMethodService.java:774)
我知道应用程序崩溃是因为 mModeChangeKey
和 mLanguageSwitchKey
为空,这是因为我提到的方法。我检查了方法,它运行了,但它没有创建匹配切换语言键代码的键。
我在 GitHub 上上传了应用程序,如果有人有兴趣看一下:
https://github.com/maihannijat/AndroidKeyboard
从 sample code mentioned in another 可以看出,如果 "nextKeyboard" 为 null,将抛出 NullPointerException。
private void setLatinKeyboard(LatinKeyboard nextKeyboard) {
final boolean shouldSupportLanguageSwitchKey =
mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken());
nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey);
mInputView.setKeyboard(nextKeyboard);
}
我正在开发 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: FATAL EXCEPTION: main Process: com.sunzala.afghankeyboard, PID: 8894 java.lang.NullPointerException at com.sunzala.afghankeyboard.android.LatinKeyboard.setLanguageSwitchKeyVisibility(LatinKeyboard.java:87) at com.sunzala.afghankeyboard.android.SoftKeyboard.setLatinKeyboard(SoftKeyboard.java:211) at com.sunzala.afghankeyboard.android.SoftKeyboard.onInitializeInterface(SoftKeyboard.java:151) at android.inputmethodservice.InputMethodService.initialize(InputMethodService.java:774)
我知道应用程序崩溃是因为 mModeChangeKey
和 mLanguageSwitchKey
为空,这是因为我提到的方法。我检查了方法,它运行了,但它没有创建匹配切换语言键代码的键。
我在 GitHub 上上传了应用程序,如果有人有兴趣看一下: https://github.com/maihannijat/AndroidKeyboard
从 sample code mentioned in another
private void setLatinKeyboard(LatinKeyboard nextKeyboard) {
final boolean shouldSupportLanguageSwitchKey =
mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken());
nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey);
mInputView.setKeyboard(nextKeyboard);
}