Как показать программную клавиатуру на родной активности

Когда я пытаюсь использовать 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, который вы хотите получить.

Другие вопросы по тегам