إغلاق / إخفاء لوحة مفاتيح Android Soft


14 Answers

للمساعدة في توضيح هذا الجنون ، أود أن أبدأ بالاعتذار نيابةً عن جميع مستخدمي Android لمعالجتها السخيفة من Google للوحة المفاتيح الناعمة. السبب في وجود العديد من الإجابات ، كل منها مختلف ، لنفس السؤال البسيط هو أن واجهة برمجة التطبيقات هذه ، مثلها مثل العديد من التطبيقات الأخرى في Android ، مصممة بشكل فظيع. لا أستطيع التفكير في طريقة مهذبة لإعلانها.

اريد اخفاء لوحة المفاتيح. أتوقع توفير Android مع العبارة التالية: Keyboard.hide() . النهاية. شكرا جزيلا. لكن Android لديه مشكلة. يجب عليك استخدام InputMethodManager لإخفاء لوحة المفاتيح. حسنًا ، جيد ، هذه واجهة برمجة تطبيقات Android إلى لوحة المفاتيح. لكن! يجب أن يكون لديك Context أجل الوصول إلى IMM. الآن لدينا مشكلة. قد أرغب في إخفاء لوحة المفاتيح من فئة ثابتة أو أداة مساعدة ليس لها أي استخدام أو حاجة لأي Context . أو أسوأ من ذلك ، يتطلب IMM أن تحدد ما View (أو ما هو أسوأ ، ما هي Window ) التي تريد إخفاء لوحة المفاتيح من.

هذا ما يجعل إخفاء لوحة المفاتيح أمرًا صعبًا. عزيزي Google: عندما أبحث عن وصفة كعكة ، لا يوجد RecipeProvider على الأرض التي ترفض أن RecipeProvider بالوصفة ما لم أجيب أولاً على منظمة الصحة العالمية بأن الكعكة سوف تؤكل من قبل وأين ستؤكل !!

تنتهي هذه القصة الحزينة بالحقيقة القبيحة: لإخفاء لوحة مفاتيح Android ، سيُطلب منك تقديم شكلين من تعريفات: Context وعرض إما أو Window .

لقد قمت بإنشاء طريقة فائدة ثابتة والتي يمكن أن تؤدي المهمة بجهد كبير ، بشرط أن تسميها من أحد Activity .

public static void hideKeyboard(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    //Find the currently focused view, so we can grab the correct window token from it.
    View view = activity.getCurrentFocus();
    //If no view currently has focus, create a new one, just so we can grab a window token from it
    if (view == null) {
        view = new View(activity);
    }
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

كن على علم بأن هذه الطريقة تعمل فقط عندما يتم استدعاؤها من Activity ! تقوم الطريقة المذكورة أعلاه باستدعاء getCurrentFocus المستهدف لجلب الرمز المميز للنافذة المناسبة.

ولكن لنفترض أنك تريد إخفاء لوحة المفاتيح من EditText المستضاف في DialogFragment ؟ لا يمكنك استخدام الطريقة المذكورة أعلاه لذلك:

hideKeyboard(getActivity()); //won't work

لن ينجح هذا لأنك ستجتاز مرجعًا Fragment المضيف في Fragment ، والذي لن يكون له أي تحكم في التركيز أثناء ظهور Fragment ! نجاح باهر لذا ، لإخفاء لوحة المفاتيح من الأجزاء ، ألجأ إلى المستوى الأدنى ، والأكثر شيوعًا ، والأكثر جرأة:

public static void hideKeyboardFrom(Context context, View view) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

فيما يلي بعض المعلومات الإضافية التي تم جمعها من خلال المزيد من الوقت لإهدارها في حل هذا الحل:

حول windowSoftInputMode

هناك نقطة خلاف أخرى يجب أن تكون على علم بها. بشكل افتراضي ، سيحدد Android التركيز الأولي تلقائيًا على أول EditText أو عنصر التحكم في نشاطك. يتبع ذلك بشكل طبيعي أن InputMethod (عادة ما تكون لوحة المفاتيح الناعمة) سوف يستجيب للحدث المركّز من خلال إظهار نفسه. windowSoftInputMode السمة windowSoftInputMode في AndroidManifest.xml ، عند stateAlwaysHidden إلى stateAlwaysHidden ، لوحة المفاتيح لتجاهل هذا التركيز الأولي المعيَّن تلقائيًا.

<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="stateAlwaysHidden"/>

بشكل لا يصدق ، يبدو أنه لا يفعل شيئًا لمنع لوحة المفاتيح من الفتح عند لمس عنصر التحكم (ما لم يتم تعيين focusable="false" و / أو focusableInTouchMode="false" إلى عنصر التحكم). على ما يبدو ، ينطبق الإعداد windowSoftInputMode فقط على أحداث التركيز التلقائي ، وليس لتركيز الأحداث التي تم إطلاقها من أحداث اللمس.

لذلك ، يتم تسمية stateAlwaysHidden بشكل stateAlwaysHidden جدًا. ربما يجب أن يتم استدعاء ignoreInitialFocus بدلاً من ذلك.

أتمنى أن يساعدك هذا.

استكمال: المزيد من الطرق للحصول على رمز نافذة

إذا لم يكن هناك طريقة عرض مركزة (على سبيل المثال ، يمكن أن يحدث إذا قمت بتغيير الأجزاء فقط) ، فهناك طرق عرض أخرى توفر رمزًا مفيدًا للنافذة.

هذه بدائل للرمز أعلاه if (view == null) view = new View(activity); هذه لا تشير صراحة إلى نشاطك.

داخل فئة جزء:

view = getView().getRootView().getWindowToken();

بالنظر إلى جزء fragment كمعامل:

view = fragment.getView().getRootView().getWindowToken();

بدءًا من نص المحتوى:

view = findViewById(android.R.id.content).getRootView().getWindowToken();

تحديث 2: مسح التركيز لتجنب إظهار لوحة المفاتيح مرة أخرى إذا قمت بفتح التطبيق من الخلفية

أضف هذا السطر إلى نهاية الطريقة:

view.clearFocus();

Question

لدي EditText و Button في EditText .

بعد الكتابة في حقل التحرير والنقر على Button ، أريد إخفاء لوحة المفاتيح الافتراضية. أفترض أن هذا هو جزء بسيط من التعليمات البرمجية ، ولكن أين يمكنني العثور على مثال على ذلك؟




الجواب القصير

في المستمع OnClick استدعاء onEditorAction من EditText مع IME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        someEditText.onEditorAction(EditorInfo.IME_ACTION_DONE)
    }
});

الحفر

أشعر أن هذه الطريقة أفضل وأبسط وأكثر توافقاً مع نمط تصميم Android. في المثال البسيط أعلاه (وعادةً في معظم الحالات الشائعة) سيكون لديك نص EditText له / لديها تركيز ، وعادةً ما يكون هو نفسه الذي يستدعي لوحة المفاتيح في المقام الأول (وهو بالتأكيد قادر على استدعائه في العديد من السيناريوهات الشائعة). وبهذه الطريقة نفسها ، ينبغي أن تكون هي الجهة التي تقوم بإصدار لوحة المفاتيح ، وعادة ما يمكن تنفيذها بواسطة ImeAction . فقط انظر كيف يعمل EditText مع android:imeOptions="actionDone" ، تريد تحقيق نفس السلوك بنفس الوسائل.

تحقق من هذه الإجابة ذات الصلة




يرجى المحاولة تحت الرمز أدناه في oncreate ()

EditText edtView = (EditText) findViewById (R.id.editTextConvertValue)؛ edtView.setInputType (0)؛




لدي الحالة ، حيث EditTextيمكن أن يكون موقعي موجودًا أيضًا AlertDialog، لذا يجب إغلاق لوحة المفاتيح عند الرفض. يبدو أن التعليمة البرمجية التالية تعمل في أي مكان:

public static void hideKeyboard( Activity activity ) {
    InputMethodManager imm = (InputMethodManager)activity.getSystemService( Context.INPUT_METHOD_SERVICE );
    View f = activity.getCurrentFocus();
    if( null != f && null != f.getWindowToken() && EditText.class.isAssignableFrom( f.getClass() ) )
        imm.hideSoftInputFromWindow( f.getWindowToken(), 0 );
    else 
        activity.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN );
}



Simple and Easy to use method, just call hideKeyboardFrom(YourActivity.this); to hide keyboard

/**
 * This method is used to hide keyboard
 * @param activity
 */
public static void hideKeyboardFrom(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}



Thanks to this SO answer , I derived the following which, in my case, works nicely when scrolling through the the fragments of a ViewPager...

private void hideKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

private void showKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
    }
}



أستخدم لوحة مفاتيح مخصصة لإدخال رقم سداسي عشري لذا لا يمكنني عرض لوحة مفاتيح IMM ...

في v3.2.4_r1 تم إضافة setSoftInputShownOnFocus(boolean show) للتحكم في الطقس أو عدم عرض لوحة المفاتيح عندما يتم التركيز على TextView ، ولكن لا يزال يجب استخدام ما يلي:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
    try {
        Method method = TextView.class.getMethod("setSoftInputShownOnFocus", boolean.class);
        method.invoke(mEditText, false);
    } catch (Exception e) {
        // Fallback to the second method
    }
}

بالنسبة إلى الإصدارات الأقدم ، حصلت على نتائج جيدة جدًا (ولكن بعيدًا عن الكمال) مع OnGlobalLayoutListener ، تمت إضافتها بمساعدة من ViewTreeObserver من وجهة نظري على الجذر ثم التحقق مما إذا كانت لوحة المفاتيح تظهر على النحو التالي:

@Override
public void onGlobalLayout() {
    Configuration config = getResources().getConfiguration();

    // Dont allow the default keyboard to show up
    if (config.keyboardHidden != Configuration.KEYBOARDHIDDEN_YES) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
    }
}

قد يعرض هذا الحل الأخير لوحة المفاتيح لجزء من الثانية ويعبث بمقابض الاختيار.

عندما يدخل في لوحة المفاتيح ملء الشاشة ، لا يتم استدعاء onGlobalLayout. لتجنب ذلك ، استخدم TextView#setImeOptions(int) أو في تعريف XML TextView:

android:imeOptions="actionNone|actionUnspecified|flagNoFullscreen|flagNoExtractUi"

تحديث: فقط العثور على ما تستخدمه مربعات الحوار لعدم إظهار لوحة المفاتيح مطلقًا ولا تعمل في جميع الإصدارات:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
        WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);



If you want to close the soft keyboard during a unit or functional test, you can do so by clicking the "back button" from your test:

// Close the soft keyboard from a Test
getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);

I put "back button" in quotes, since the above doesn't trigger the onBackPressed() for the Activity in question. It just closes the keyboard.

Make sure to pause for a little while before moving on, since it takes a little while to close the back button, so subsequent clicks to Views, etc., won't be registered until after a short pause (1 second is long enough ime).




This worked for me for all the bizarre keyboard behavior

private boolean isKeyboardVisible() {
    Rect r = new Rect();
    //r will be populated with the coordinates of your view that area still visible.
    mRootView.getWindowVisibleDisplayFrame(r);

    int heightDiff = mRootView.getRootView().getHeight() - (r.bottom - r.top);
    return heightDiff > 100; // if more than 100 pixels, its probably a keyboard...
}

protected void showKeyboard() {
    if (isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if (getCurrentFocus() == null) {
        inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    } else {
        View view = getCurrentFocus();
        inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_FORCED);
    }
}

protected void hideKeyboard() {
    if (!isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    View view = getCurrentFocus();
    if (view == null) {
        if (inputMethodManager.isAcceptingText())
            inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
    } else {
        if (view instanceof EditText)
            ((EditText) view).setText(((EditText) view).getText().toString()); // reset edit text bug on some keyboards bug
        inputMethodManager.hideSoftInputFromInputMethod(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}



بدلاً من ذلك ، إلى هذا الحل في كل مكان ، إذا كنت ترغب في إغلاق لوحة المفاتيح الناعمة من أي مكان دون وجود مرجع إلى الحقل (EditText) الذي تم استخدامه لفتح لوحة المفاتيح ، ولكن لا تزال ترغب في القيام بذلك إذا كان الحقل مركّزًا ، فيمكنك استخدام هذا (من نشاط):

if (getCurrentFocus() != null) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}



For my case, I was using the a SearchView in the actionbar. After a user performs a search, the keyboard would pop open again.

Using the InputMethodManager did not close the keyboard. I had to clearFocus and set the focusable of the search view to false:

mSearchView.clearFocus();
mSearchView.setFocusable(false);



protected void hideSoftKeyboard(EditText input) {
    input.setInputType(0);
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}



Just use this optimized code in your activity:

if (this.getCurrentFocus() != null) {
    InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
    inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}



حصلت على حل آخر لإخفاء لوحة المفاتيح:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

هنا HIDE_IMPLICIT_ONLY عند موضع showFlag و 0 في موضع hiddenFlag . وسوف تغلق بقوة لوحة المفاتيح الناعمة.




لدى سوراب باريك أفضل إجابة حتى الآن.

قد تستخدم الأعلام الصحيحة كذلك.

/* hide keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

/* show keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

مثال على الاستخدام الحقيقي

/* click button */
public void onClick(View view) {      
  /* hide keyboard */
  ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
      .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

  /* start loader to check parameters ... */
}

/* loader finished */
public void onLoadFinished(Loader<Object> loader, Object data) {
    /* parameters not valid ... */

    /* show keyboard */
    ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
        .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

    /* parameters valid ... */
}





Related