【问题标题】:How to show the soft keyboard on native activity如何在本机活动上显示软键盘
【发布时间】:2011-08-17 09:53:57
【问题描述】:

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

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

看了源码,发现启动nativeActivity后,会创建NativeContentView(extend View),调用ANativeActivity_showSoftInput时,会在java端调用showSoftInput()。我想也许软键盘没有打开。

你能帮帮我吗?

【问题讨论】:

  • 请准确发布您是如何致电ANativeActivity_showSoftInput() 的,并详细说明您因通话而遇到的问题。
  • 我尝试 ANativeActivity_showSoftInput(engine->app->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED) 和 ANativeActivity_showSoftInput(engine->app->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT) 来显示软输入,但失败了。看了源码,发现启动nativeActivity后,会创建NativeContentView(extend View),调用ANativeActivity_showSoftInput时,会在java端调用showSoftInput()。我想也许软键盘没有打开。你能帮帮我吗?
  • @Mike Pennington,请帮帮我
  • 我对Android或java一无所知,但我已经尽力了。
  • @Mike Pennington,非常感谢

标签: java android android-softkeyboard


【解决方案1】:

我遇到了完全相同的问题。无法使用此 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 的内容,并将本机代码调用到包装器中,从而降低本机端语法的复杂性。

    【讨论】:

      【解决方案3】:

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

      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。

      【讨论】:

        猜你喜欢
        • 2018-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-20
        • 1970-01-01
        • 2016-02-11
        相关资源
        最近更新 更多