如何在本地活动中显示软键盘

11

当我尝试使用ANativeActivity_showSoftInput()时,软键盘没有弹出。

我尝试使用ANativeActivity_showSoftInput(engine->app->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED)ANativeActivity_showSoftInput(engine->app->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT)来显示软输入法,但都失败了。

我查看了源代码,发现在启动nativeActivity后,将创建NativeContentView(扩展视图),并且在调用ANativeActivity_showSoftInput时,它会在Java端调用showSoftInput()。我认为可能没有打开软键盘。

你能帮我吗?


请提供您调用“ANativeActivity_showSoftInput()”的详细信息,以及由此调用导致的问题的更多特定信息。 - Mike Pennington
我尝试过使用 ANativeActivity_showSoftInput(engine->app->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED) 和 ANativeActivity_showSoftInput(engine->app->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT) 来显示软键盘,但是失败了。我阅读了源代码,发现在启动 NativeActivity 后,将会创建 NativeContentView(继承自 View),当调用 ANativeActivity_showSoftInput 时,它会在 Java 端调用 showSoftInput() 方法。我认为可能是因为软键盘没有打开。你能帮我吗? - Miles
@Mike Pennington,请帮帮我。 - Miles
我对Android或Java一无所知,但我已尽力而为。 - Mike Pennington
@Mike Pennington,非常感谢。 - Miles
3个回答

6

我遇到了完全相同的问题。使用这个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();
}

2
另一种方式是采用混合方案,在Java中扩展NativeActivity并具有显示和隐藏键盘的辅助函数。
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();
    }
}

这样可以让你在Java中处理Android特定的内容,并使本地代码调用包装器,从而减少本地端语法的复杂性。


1

我在尝试关闭软键盘时遇到了很多麻烦,直到我意识到我必须从调用它的视图中特别删除它:

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链接即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接