Как показать программную клавиатуру на родной активности
Когда я пытаюсь использовать ANativeActivity_showSoftInput()
, это не вызывает мягкую клавиатуру.
Я пытался использовать ANativeActivity_showSoftInput(engine->app->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED)
а также ANativeActivity_showSoftInput(engine->app->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT)
показать softinput, но тоже не удалось.
Я прочитал исходный код, и я нашел после запуска nativeActivity
, NativeContentView(extend View)
будет создан и при вызове ANativeActivity_showSoftInput
позвонит showSoftInput()
в сторону Java. Я думаю, что, возможно, софт-клавиатура не включена.
Вы можете мне помочь?
3 ответа
У меня точно такая же проблема. Нет способа показать клавиатуру с помощью этого API.
Единственный способ, который я нашел, - использовать JNI, но, конечно, я не удовлетворен этим решением:
android_app* mApplication;
...
void displayKeyboard(bool pShow) {
// Attaches the current thread to the JVM.
jint lResult;
jint lFlags = 0;
JavaVM* lJavaVM = mApplication->activity->vm;
JNIEnv* lJNIEnv = mApplication->activity->env;
JavaVMAttachArgs lJavaVMAttachArgs;
lJavaVMAttachArgs.version = JNI_VERSION_1_6;
lJavaVMAttachArgs.name = "NativeThread";
lJavaVMAttachArgs.group = NULL;
lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs);
if (lResult == JNI_ERR) {
return;
}
// Retrieves NativeActivity.
jobject lNativeActivity = mApplication->activity->clazz;
jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity);
// Retrieves Context.INPUT_METHOD_SERVICE.
jclass ClassContext = lJNIEnv->FindClass("android/content/Context");
jfieldID FieldINPUT_METHOD_SERVICE =
lJNIEnv->GetStaticFieldID(ClassContext,
"INPUT_METHOD_SERVICE", "Ljava/lang/String;");
jobject INPUT_METHOD_SERVICE =
lJNIEnv->GetStaticObjectField(ClassContext,
FieldINPUT_METHOD_SERVICE);
jniCheck(INPUT_METHOD_SERVICE);
// Runs getSystemService(Context.INPUT_METHOD_SERVICE).
jclass ClassInputMethodManager = lJNIEnv->FindClass(
"android/view/inputmethod/InputMethodManager");
jmethodID MethodGetSystemService = lJNIEnv->GetMethodID(
ClassNativeActivity, "getSystemService",
"(Ljava/lang/String;)Ljava/lang/Object;");
jobject lInputMethodManager = lJNIEnv->CallObjectMethod(
lNativeActivity, MethodGetSystemService,
INPUT_METHOD_SERVICE);
// Runs getWindow().getDecorView().
jmethodID MethodGetWindow = lJNIEnv->GetMethodID(
ClassNativeActivity, "getWindow",
"()Landroid/view/Window;");
jobject lWindow = lJNIEnv->CallObjectMethod(lNativeActivity,
MethodGetWindow);
jclass ClassWindow = lJNIEnv->FindClass(
"android/view/Window");
jmethodID MethodGetDecorView = lJNIEnv->GetMethodID(
ClassWindow, "getDecorView", "()Landroid/view/View;");
jobject lDecorView = lJNIEnv->CallObjectMethod(lWindow,
MethodGetDecorView);
if (pShow) {
// Runs lInputMethodManager.showSoftInput(...).
jmethodID MethodShowSoftInput = lJNIEnv->GetMethodID(
ClassInputMethodManager, "showSoftInput",
"(Landroid/view/View;I)Z");
jboolean lResult = lJNIEnv->CallBooleanMethod(
lInputMethodManager, MethodShowSoftInput,
lDecorView, lFlags);
} else {
// Runs lWindow.getViewToken()
jclass ClassView = lJNIEnv->FindClass(
"android/view/View");
jmethodID MethodGetWindowToken = lJNIEnv->GetMethodID(
ClassView, "getWindowToken", "()Landroid/os/IBinder;");
jobject lBinder = lJNIEnv->CallObjectMethod(lDecorView,
MethodGetWindowToken);
// lInputMethodManager.hideSoftInput(...).
jmethodID MethodHideSoftInput = lJNIEnv->GetMethodID(
ClassInputMethodManager, "hideSoftInputFromWindow",
"(Landroid/os/IBinder;I)Z");
jboolean lRes = lJNIEnv->CallBooleanMethod(
lInputMethodManager, MethodHideSoftInput,
lBinder, lFlags);
}
// Finished with the JVM.
lJavaVM->DetachCurrentThread();
}
Другой способ - использовать гибридное решение, в котором вы расширяете NativeActivity в Java и имеете вспомогательные функции для отображения и скрытия клавиатуры.
import android.view.inputmethod.InputMethodManager;
import android.content.Context;
public class MyNativeActivity extends android.app.NativeActivity
{
public void showKeyboard()
{
InputMethodManager imm = ( InputMethodManager )getSystemService( Context.INPUT_METHOD_SERVICE );
imm.showSoftInput( this.getWindow().getDecorView(), InputMethodManager.SHOW_FORCED );
}
public void hideKeyboard()
{
InputMethodManager imm = ( InputMethodManager )getSystemService( Context.INPUT_METHOD_SERVICE );
imm.hideSoftInputFromWindow( this.getWindow().getDecorView().getWindowToken(), 0 );
}
}
И на родной стороне...
void DisplayKeyboard( bool bShow )
{
// Attaches the current thread to the JVM.
JavaVM* pJavaVM = m_pNativeActivity->vm;
JNIEnv* pJNIEnv = m_pNativeActivity->env;
JavaVMAttachArgs javaVMAttachArgs;
javaVMAttachArgs.version = JNI_VERSION_1_6;
javaVMAttachArgs.name = "NativeThread";
javaVMAttachArgs.group = NULL;
jint nResult = pJavaVM->AttachCurrentThread( &pJNIEnv, &javaVMAttachArgs );
if ( nResult != JNI_ERR )
{
// Retrieves NativeActivity.
jobject nativeActivity = m_pNativeActivity->clazz;
jclass ClassNativeActivity = pJNIEnv->GetObjectClass( nativeActivity );
if ( bShow )
{
jmethodID MethodShowKeyboard = pJNIEnv->GetMethodID( ClassNativeActivity, "showKeyboard", "()V" );
pJNIEnv->CallVoidMethod( nativeActivity, MethodShowKeyboard );
}
else
{
jmethodID MethodHideKeyboard = pJNIEnv->GetMethodID( ClassNativeActivity, "hideKeyboard", "()V" );
pJNIEnv->CallVoidMethod( nativeActivity, MethodHideKeyboard );
}
// Finished with the JVM.
pJavaVM->DetachCurrentThread();
}
}
Это позволяет вам иметь дело со специфическими для Android вещами в Java, как это было задумано, и иметь собственный код, вызывающий обертки, что снижает сложность синтаксиса на нативной стороне.
У меня было много проблем, когда я пытался закрыть программную клавиатуру при смене вида, пока не понял, что должен был удалить ее специально из вида, который ее вызывал:
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
Есть также метод showSoftInput, который, вероятно, должен работать (при условии, что он выполняет то, что говорит имя метода) аналогичным образом, где ему нужно представление, чтобы привязать себя к:
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(editText.getWindowToken(), 0);
Сам пока не могу проверить это на самом деле, но я подумал, что это может помочь вам и стоило бы попробовать. Просто убедитесь, что "editText" связан с EditText, который вы хотите получить.