Ошибка Null указателя с помощью hideSoftInputFromWindow

Я получаю исключение нулевого указателя в этой строке:

public void hideKeyboard(){ 
InputMethodManager inputManager = (InputMethodManager)            
            this.getSystemService(Context.INPUT_METHOD_SERVICE);    
inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(),      
            InputMethodManager.HIDE_NOT_ALWAYS);
}

Это вызывается из следующего метода:

@Override
public void onBackPressed() {
    super.onBackPressed();
    hideKeyboard();
}

Это единственное действие. Задняя кнопка нажата из фрагмента.

STACK:

09-28 19:14:40.301: E/InputEventSender(30324): Exception dispatching finished signal.
09-28 19:14:40.301: E/MessageQueue-JNI(30324): Exception in MessageQueue callback: handleReceiveCallback
09-28 19:14:40.325: E/MessageQueue-JNI(30324): java.lang.NullPointerException
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at com.example.ecohelp.MainActivity.hideKeyboard(MainActivity.java:75)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at com.example.ecohelp.MainActivity.onBackPressed(MainActivity.java:31)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.app.Activity.onKeyUp(Activity.java:2159)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.KeyEvent.dispatch(KeyEvent.java:2647)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.app.Activity.dispatchKeyEvent(Activity.java:2389)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1860)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:3791)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3774)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3379)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3429)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3398)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3483)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3406)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3540)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3379)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3429)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3398)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3406)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3379)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3429)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3398)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3516)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3666)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:1982)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1698)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1689)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:1959)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.os.MessageQueue.nativePollOnce(Native Method)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.os.MessageQueue.next(MessageQueue.java:132)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.os.Looper.loop(Looper.java:124)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at android.app.ActivityThread.main(ActivityThread.java:5103)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at java.lang.reflect.Method.invokeNative(Native Method)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at java.lang.reflect.Method.invoke(Method.java:525)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
09-28 19:14:40.325: E/MessageQueue-JNI(30324):  at dalvik.system.NativeStart.main(Native Method)

Ответы

Ответ 1

Как упоминалось в CommonsWare, getCurrentFocus() является нулевым, поскольку нет компонента View внутри текущего Activity удерживая фокус.

Если у вас уже есть представление в своей деятельности, используйте его, чтобы получить токен окна. Например, если у меня есть компонент Button:

inputManager.hideSoftInputFromWindow(myButton.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);

Или, что еще хуже, если у меня нет никакого представления в моей деятельности, я мог бы сделать это:

inputManager.hideSoftInputFromWindow(new View(this).getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);

Это решит вашу проблему NPE, но, надеюсь, вы найдете описание полезным.

Еще одна вещь о клавиатурах заключается в том, что когда пользователь нажимает кнопку "Назад", когда клавиатура видна, клавиатура получает и потребляет нажатие клавиши "Назад", чтобы скрыть себя. Или, по крайней мере, большинство клавиатур ведут себя так.

Ответ 2

Мне просто нужно проверить, есть ли сфокусированный вид, прежде чем скрывать клавиатуру.

Например, если у вас есть EditText в вашей деятельности или фрагменте, это, вероятно, будет сфокусированным видом. Когда EditText больше не фокусируется, getCurrentFocus() может возвращать значение null (если не сфокусировано другое представление).

void hideKeyboard() {
    InputMethodManager inputManager = (InputMethodManager) getActivity().getSystemService(
            Context.INPUT_METHOD_SERVICE);
    View focusedView = getActivity().getCurrentFocus();
    /*
     * If no view is focused, an NPE will be thrown
     * 
     * Maxim Dmitriev
     */
    if (focusedView != null) {
        inputManager.hideSoftInputFromWindow(focusedView.getWindowToken(),
                InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

Ответ 3

Все выше правильно указали, что getWindowToken() возвращает null.

Я использовал код по умолчанию getCurrentFocus().getWindowToken(), чтобы скрыть клавиатуру, когда я столкнулся с той же проблемой.

Тогда я понял, что, поскольку нет представления, получающего фокус, я получил NullPointerException.

Мы можем изменить сказанное выше:

anyView.getWindowToken()

где anyView - это просто любое представление в вашем макете.

Ответ 4

У меня была такая же проблема, когда getCurrentFocus() возвращал значение null. Таким образом, этот метод работал у меня, и я бы просто назвал его на моем onClick, чтобы скрыть клавиатуру, если ее показало или все еще не выбрасывает исключение нулевого указателя, даже если клавиатура не была показана:

public void hiddenInputMethod() {

    InputMethodManager imm = (InputMethodManager) getSystemService(MyActivity.this.INPUT_METHOD_SERVICE);
    if (getCurrentFocus() != null)
        imm.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}

Ответ 5

Если вы хотите скрыть клавиатуру при касании на экране, используйте приведенный ниже код

       @Override
public boolean onTouchEvent(MotionEvent event) {
    InputMethodManager imm = (InputMethodManager)this.getSystemService(Context.
            INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(this.getWindow().getDecorView().getRootView().getWindowToken(), 0);
    return true;
}

Если вы хотите сделать это в определенном представлении (EditText)

      public void  hideKeyBoard(EditText edt) {
    InputMethodManager imm = (InputMethodManager)this.getSystemService(Context.
            INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(edt.getWindowToken(), 0);

}

или вы можете использовать любой вид.

Чтобы получить текущий вид

    imm.hideSoftInputFromWindow(this.getWindow().getDecorView().getRootView().getWindowToken(), 0);

Ответ 6

Основная проблема заключается в

getCurrentFocus().getWindowToken()

Здесь getcurrentFocus(). Эта проблема может быть легко решена путем предоставления действительного вида на текущем экране, например

yourButtonOnScreen.getWindowToken()

Эта кнопка wo'nt будет пустой, поскольку она отображается на вашем экране, поэтому она решит проблему.

Тем не менее, если у вас нет действительного представления на экране, просто замените

getCurrentFocus().getWindowToken()...

с

//in case of fragment

new View(getActivity()).getWindowToken()

//in case of activity

new View(this).getWindowToken()

надеюсь, что это решит проблему... удачи!

Ответ 7

Используйте это, если вы получаете ошибку: вызвано: java.lang.NullPointerException: попытка вызвать виртуальный метод 'android.os.IBinder android.view.View.getWindowToken()' для ссылки на нулевой объект


InputMethodManager inputMethodManager = (InputMethodManager) MainActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE);

   if(MainActivity.this.getCurrentFocus() != null)
        {
         inputMethodManager.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().
getWindowToken(), 0);
        }

Ответ 8

Я столкнулся с той же проблемой, скрывая клавиатуру, я нашел простое решение, сделав корневой вид макета в режиме touch-touch.

<RelativeLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:id="@+id/rlSignActivity"
android:focusableInTouchMode="true"
xmlns:android="http://schemas.android.com/apk/res/android" >
    .......
</RelativeLayout>

Ответ 9

попробуйте следующее:

public void hideKeyboard(){ 
InputMethodManager inputManager = (InputMethodManager)            
            this.getSystemService(Context.INPUT_METHOD_SERVICE);    
inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);
}

Ответ 10

Просто используйте это:

public void hideKeyboard(View v){ 
  InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
  imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}