EditText के बाहर क्लिक करने के बाद एंड्रॉइड पर सॉफ्ट कीबोर्ड कैसे छिपाएं?


354

ठीक है, हर कोई जानता है कि एक कीबोर्ड को छिपाने के लिए जिसे आपको लागू करने की आवश्यकता है:

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);

लेकिन यहां बड़ी बात यह है कि उपयोगकर्ता द्वारा किसी अन्य स्थान EditTextको छूने या चुनने पर कीबोर्ड को कैसे छिपाया जाता है जो कि सॉफ्टकबोर्ड नहीं है?

मैंने onTouchEvent()अपने माता-पिता पर उपयोग करने की कोशिश की, Activityलेकिन यह केवल तभी काम करता है जब उपयोगकर्ता किसी अन्य दृश्य के बाहर छूता है और कोई स्क्रॉलव्यू नहीं है।

मैंने बिना किसी सफलता के एक टच, क्लिक, फोकस श्रोता को लागू करने की कोशिश की।

मैंने स्पर्श घटनाओं को रोकने के लिए अपने स्वयं के स्क्रॉलव्यू को लागू करने की भी कोशिश की, लेकिन मैं केवल घटना के निर्देशांक प्राप्त कर सकता हूं, न कि क्लिक किए गए दृश्य।

क्या ऐसा करने का कोई मानक तरीका है ?? iPhone में यह वास्तव में आसान था।


वैसे मुझे एहसास हुआ कि स्क्रोलव्यू वास्तव में समस्या नहीं थी, लेकिन जो लेबल वहां हैं। दृश्य कुछ के साथ एक ऊर्ध्वाधर लेआउट है: TextView, EditText, TextView, EditText, आदि .. और textViews एडिटेक्स को फ़ोकस को ढीला करने और कीबोर्ड को छिपाने की अनुमति नहीं देगा
htafoya

आप getFields()यहाँ के लिए एक समाधान पा सकते हैं : stackoverflow.com/questions/7790487/…
Reto

कीबोर्ड रिटर्न बटन को दबाकर बंद किया जा सकता है, इसलिए मैं कहूंगा कि यह संदिग्ध है कि क्या यह प्रयास के लायक है
gerrytan

4
मुझे यह उत्तर मिला: stackoverflow.com/a/28939113/2610855 सबसे अच्छा।
Loenix

जवाबों:


575

निम्नलिखित स्निपेट केवल कीबोर्ड छुपाता है:

public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = 
        (InputMethodManager) activity.getSystemService(
            Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(
        activity.getCurrentFocus().getWindowToken(), 0);
}

आप इसे एक उपयोगिता वर्ग में डाल सकते हैं, या यदि आप इसे किसी गतिविधि के भीतर परिभाषित कर रहे हैं, तो गतिविधि पैरामीटर, या कॉल से बचें hideSoftKeyboard(this)

मुश्किल हिस्सा है जब यह फोन करने के लिए। आप एक ऐसी विधि लिख सकते हैं Viewजो आपकी गतिविधि में प्रत्येक के माध्यम से पुनरावृत्ति करती है , और जांचें कि क्या यह एक घटक के लिए instanceof EditTextरजिस्टर नहीं है setOnTouchListenerऔर सब कुछ जगह में गिर जाएगा। मामले में आप सोच रहे हैं कि यह कैसे करना है, यह वास्तव में काफी सरल है। यहाँ आप क्या करते हैं, आप निम्न की तरह एक पुनरावर्ती विधि लिखते हैं, वास्तव में आप इसका उपयोग कुछ भी करने के लिए कर सकते हैं, जैसे सेटअप कस्टम टाइपफेस आदि ... यहाँ विधि है

public void setupUI(View view) {

    // Set up touch listener for non-text box views to hide keyboard.
    if (!(view instanceof EditText)) {
        view.setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard(MyActivity.this);
                return false;
            }
        });
    }

    //If a layout container, iterate over children and seed recursion.
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            View innerView = ((ViewGroup) view).getChildAt(i);
            setupUI(innerView);
        }
    }
}

यह सब है, बस setContentViewअपनी गतिविधि में आपके बाद इस पद्धति को कॉल करें । यदि आप सोच रहे हैं कि आप किस पैरामीटर से गुजरेंगे, तो यह idमूल कंटेनर का है। idअपने माता-पिता के कंटेनर की तरह असाइन करें

<RelativeLayoutPanel android:id="@+id/parent"> ... </RelativeLayout>

और बुलाओ setupUI(findViewById(R.id.parent)), वह सब है।

यदि आप इसे प्रभावी ढंग से उपयोग करना चाहते हैं, तो आप एक विस्तारित बना सकते हैं Activity और में इस विधि रखा, और अपने आवेदन में अन्य सभी गतिविधियों इस गतिविधि का विस्तार करने और अपने फोन बनाने setupUI()में onCreate()विधि।

आशा है ये मदद करेगा।

यदि आप 1 से अधिक गतिविधि का उपयोग करते हैं, तो माता-पिता के लेआउट की तरह सामान्य आईडी को परिभाषित करते हैं <RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>

फिर से एक वर्ग का विस्तार करें और इसके भीतर Activityपरिभाषित करें और `` गतिविधि के बजाय इस वर्ग का विस्तार करेंsetupUI(findViewById(R.id.main_parent))OnResume()in your program


यहाँ उपरोक्त फ़ंक्शन का कोटलिन संस्करण है:

@file:JvmName("KeyboardUtils")

fun Activity.hideSoftKeyboard() {
    currentFocus?.let {
        val inputMethodManager = ContextCompat.getSystemService(this, InputMethodManager::class.java)!!
        inputMethodManager.hideSoftInputFromWindow(it.windowToken, 0)
    }
}

मैंने खुद का परीक्षण नहीं किया है, लेकिन ऐसा लगता है कि यह काम करेगा और इसकी उच्च समीक्षा के साथ मैं इसका उत्तर स्वीकार कर लूंगा।
htafoya

4
बहुत कठिन नहीं होना चाहिए? मैं अभी एंड्रॉइड प्रोग्रामिंग से बाहर हूं, इसलिए यदि मैं गलत हूं तो मुझे सुधारें। आप किसी भी समय किसी भी समय केंद्रित EditText को ट्रैक कर सकते हैं, और इसे OnTouchEvent के दौरान फोकस करने के लिए खो देने का अनुरोध कर सकते हैं?
नवनीत जी

25
यकीन नहीं होता कि किसी और ने इस मुद्दे को चलाया है, लेकिन यह एप्लिकेशन को क्रैश करने का कारण बनता है जब आप HideSoftKeyboard को कॉल करते हैं यदि कुछ भी ध्यान केंद्रित नहीं है। आप इसे विधि की दूसरी पंक्ति के साथ हल कर सकते हैंif(activity.getCurrentFocus() != null) {...}
फ्रैंक कैन्गियालोसी

14
इस दृष्टिकोण के साथ समस्या यह है कि यह मानता है कि अन्य सभी विचारों को कभी भी OnTouchListenerउनके लिए सेट करने की आवश्यकता नहीं होगी । आप उस तर्क को ViewGroup.onInterceptTouchEvent(MotionEvent)मूल दृश्य में सेट कर सकते हैं।
एलेक्स.एफ

2
काम नहीं जब मैं कीबोर्ड को खुला रखते हुए अन्य नियंत्रणों पर क्लिक करता हूं
mohitum

285

आप निम्न चरणों का पालन करके इसे प्राप्त कर सकते हैं:

  1. निम्नलिखित विशेषताओं को जोड़कर अभिभावक दृश्य (आपकी गतिविधि का सामग्री दृश्य) क्लिक करने योग्य और ध्यान देने योग्य बनाएं

        android:clickable="true" 
        android:focusableInTouchMode="true" 
  2. एक HideKeyboard () विधि को लागू करें

        public void hideKeyboard(View view) {
            InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
  3. अंत में, अपने एडिटेक्स के onFocusChangeListener को सेट करें।

        edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (!hasFocus) {
                    hideKeyboard(v);
                }
            }
        });

जैसा कि नीचे दी गई टिप्पणियों में से एक में बताया गया है, यह काम नहीं कर सकता है यदि मूल दृश्य एक स्क्रॉल दृश्य है। इस तरह के मामले के लिए, क्लिक करने योग्य और ध्यान देने योग्यइनचाउटमोड को सीधे स्क्रॉलव्यू के तहत दृश्य में जोड़ा जा सकता है।


67
मेरी राय में यह सही उत्तर है। कम कोड, कोई अनावश्यक पुनरावृत्ति नहीं ...
gattshjoty

14
मुझे यह जवाब बहुत पसंद है। एक बात का ध्यान रखें कि यह मेरे लिए काम नहीं किया जब मैं clickableऔर focusableInTouchModeमेरे मूल ScrollViewतत्व को जोड़ने के लिए । मुझे अपने माता-पिता के सीधे माता-पिता से जोड़ना पड़ा EditTextजो कि ए LinearLayout
एडम जॉन्स

10
मेरे लिए पूरी तरह से काम किया। हालाँकि, यदि आपके पास दो edittext विजेट हैं, तो आपको यह सुनिश्चित करने की आवश्यकता है कि आप दोनों को सही ढंग से ऑनफोकस संभालते हैं अन्यथा आप अनावश्यक रूप से छुपाते हुए कीबोर्ड को टॉगल करेंगे।
मार्का ए

1
@Marka मुझे इससे कोई परेशानी नहीं थी, जब मैं अन्य EditText पर क्लिक करता हूं, तो कीबोर्ड ठहर जाता है, अगर उस पृष्ठभूमि पर क्लिक किया जाता है, जो उसे छिपाना चाहिए। मेरे पास onFocusChange में कुछ अन्य हैंडलिंग थी, बस एडिट टेक्स्ट की पृष्ठभूमि को बदलते हुए जब यह फोकस होता है, तो कुछ भी नहीं।
CularBytes

3
@ श्रीकांत - मैं कई संपादित ग्रंथों के साथ भी झिलमिलाहट देख रहा था। मैंने सिर्फ प्रत्येक संपादित पाठ के बजाय माता-पिता पर onFocusChangeListener सेट किया, और यह कहने के लिए शर्त को स्विच किया कि अगर (hasFocus) {HideKeyboard (v); } अभी तक btwn संपादन ग्रंथों स्विचन चंचल नहीं देखा है।
मनीषा

69

गतिविधि में बस नीचे कोड ओवरराइड करें

 @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (getCurrentFocus() != null) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
    }
    return super.dispatchTouchEvent(ev);
}

4
सरल समाधान, गतिविधि में जोड़ें और यह भी टुकड़े का ख्याल रखेगा
रोहित मौर्य

1
एक और उपाय यह है कि बेसएक्टिविटी बनाएं और सभी गतिविधियों में उसका विस्तार करें
सोनवणे

1
शानदार समाधान
अहमद इस्माइल

1
कीबोर्ड बंद करते समय आपने मेरी स्क्रीन को फ़्लिकर करने से मुझे बचाया। थम्स अप!
Dimas मेंडेस

1
अच्छा है, लेकिन यह सच होने के लिए बहुत अच्छा था: सरल, बहुत छोटा, और यह काम किया ... अफसोस, एक समस्या है: जब कीबोर्ड प्रदर्शित होता है, तो हर बार जब हम एडिट टेक्स्ट को स्पर्श करते हैं जो कीबोर्ड से पूछते हैं, तो यह नीचे जाता है और अपने आप।
क्राइसोट्रिबैक्स

60

मुझे स्वीकृत उत्तर थोड़ा जटिल लगता है।

यहाँ मेरा समाधान है। OnTouchListenerअपने मुख्य लेआउट में जोड़ें , अर्थात:

findViewById(R.id.mainLayout).setOnTouchListener(this)

और निम्नलिखित कोड को onTouch विधि में रखें।

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);

इस तरह से आपको सभी विचारों पर ध्यान नहीं देना है।


@roepit - एक लेआउट को एक दृश्य में डालने की कोशिश करने के लिए एक क्लासकैस्टसेप्शन प्राप्त कर रहा है। क्या मैं कुछ भूल रहा हूँ?
katzenhut

क्या आप अपने कोड का संदर्भ दे सकते हैं? जब मैं आपके लेआउट और गतिविधि / खंड एट वगैरह कोड को नहीं देख सकता, तो मैं बता नहीं सकता कि क्या गलत है।
रोपित

सबसे अच्छा जवाब वहाँ, फिर भी यह कैसे काम करता है के आसपास मेरे सिर को लपेटने की कोशिश कर रहा है।
user40797

अगर आप ऐप के टाइटल बार पर क्लिक करते हैं तो क्या यह काम करेगा?
user1506104

1
यह कीबोर्ड को छिपाने के लिए पूरी तरह से काम करता है! ध्यान दें कि यह वास्तव में EditText को अनफोकस नहीं करता है, यह सिर्फ कीबोर्ड को छुपाता है। EditText को अनफोकस करने के लिए, उदाहरण android:onClick="stealFocusFromEditTexts"के लिए मूल दृश्य के xml में जोड़ें और फिर public void stealFocusFromEditTexts(View view) {}उसकी गतिविधि पर जाएँ। ऑन-क्लिक विधि को कुछ भी करने की आवश्यकता नहीं है, यह केवल माता-पिता के देखने के लिए ध्यान देने योग्य / चयन योग्य होने के लिए मौजूद है, जो कि बच्चे से फोकस चोरी करने के लिए आवश्यक है EditText
याकूब आर

40

मुझे कीबोर्ड को छिपाने के लिए एक और समाधान मिला:

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

यहाँ से पारित HIDE_IMPLICIT_ONLYकी स्थिति में showFlagऔर 0की स्थिति में hiddenFlag। यह नरम कीबोर्ड को बलपूर्वक बंद कर देगा।


3
धन्यवाद यह काम है ..... ऊपर मैंने कोशिश की थी, लेकिन यह संवाद बॉक्स एडिट टेक्स्ट एनडी क्लोजिंग डायलॉगबॉक्स से मान प्राप्त करते हुए काम नहीं कर रहा है ...
पंकजएंड्रॉइड

धन्यवाद, यह केवल काम कर रहा है, और यह बहुत क्लीनर है तो ऊपर दूसरा! +1
एडमंड टैमास

यह काम कर रहा है के रूप में उम्मीद, अपने समाधान +1 के लिए धन्यवाद
TRYP

मेरे लिए एक आकर्षण की तरह काम करता है। सुरुचिपूर्ण समाधान के लिए +1।
संतजी

2
क्षमा करें, लेकिन यह विधि टॉगल है, इसलिए यदि कीबोर्ड स्थिति पहले से ही बंद है, तो यह कीबोर्ड को दिखाएगा
HendraWD

16

अच्छी तरह से मैं कुछ हद तक समस्या को हल करने का प्रबंधन करता हूं, मैं अपनी गतिविधि पर डिस्पैचटाउट को हटा देता हूं, वहां मैं कीबोर्ड को छिपाने के लिए निम्नलिखित का उपयोग कर रहा हूं।

 /**
 * Called to process touch screen events. 
 */
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {

    switch (ev.getAction()){
        case MotionEvent.ACTION_DOWN:
            touchDownTime = SystemClock.elapsedRealtime();
            break;

        case MotionEvent.ACTION_UP:
            //to avoid drag events
            if (SystemClock.elapsedRealtime() - touchDownTime <= 150){  

                EditText[] textFields = this.getFields();
                if(textFields != null && textFields.length > 0){

                    boolean clickIsOutsideEditTexts = true;

                    for(EditText field : textFields){
                        if(isPointInsideView(ev.getRawX(), ev.getRawY(), field)){
                            clickIsOutsideEditTexts = false;
                            break;
                        }
                    }

                    if(clickIsOutsideEditTexts){
                        this.hideSoftKeyboard();
                    }               
                } else {
                    this.hideSoftKeyboard();
                }
            }
            break;
    }

    return super.dispatchTouchEvent(ev);
}

संपादित करें: GetFields () विधि केवल एक विधि है जो व्यू में टेक्स्ट फ़ील्ड के साथ एक सरणी देता है। हर स्पर्श पर इस सरणी को बनाने से बचने के लिए, मैंने sFields नामक एक स्थिर सरणी बनाई, जिसे getFields () पद्धति से लौटाया गया है। यह सरणी ऑनस्टार्ट () विधियों पर आरंभिक है:

sFields = new EditText[] {mUserField, mPasswordField};


यह सही नहीं है, ड्रैग इवेंट का समय केवल आंकड़ों के आधार पर होता है इसलिए कभी-कभी यह लंबे क्लिक्स करते समय छिपता नहीं है, और मैं प्रति दृश्य सभी एडिटेक्स प्राप्त करने के लिए एक विधि बनाकर समाप्त कर देता हूं; जब अन्य EditText पर क्लिक करते हैं तो कीबोर्ड छिपा होता है और दिखाता है।

फिर भी, क्लीनर और छोटे समाधानों का स्वागत है


8
भविष्य में दूसरों की मदद करने के लिए, क्या आप अपने getFields()तरीके को शामिल करने के लिए अपने उत्तर में कोड को संपादित करने पर विचार करेंगे ? यह सटीक होना जरूरी नहीं है, उदाहरण के साथ सिर्फ कुछ टिप्पणियों से संकेत मिलता है कि यह EditTextवस्तुओं की एक सरणी देता है ।
स्क्वॉन्क

14

OnFocusChangeListener का उपयोग करें ।

उदाहरण के लिए:

editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (!hasFocus) {
            hideKeyboard();
        }
    }
});

अद्यतन : आप भी onTouchEvent()अपनी गतिविधि में ओवरराइड कर सकते हैं और स्पर्श के निर्देशांक की जांच कर सकते हैं । यदि निर्देशांक EditText के बाहर हैं, तो कीबोर्ड छिपाएँ।


9
समस्या यह है कि जब मैं किसी लेबल या अन्य दृश्य पर क्लिक करने पर ध्यान केंद्रित करने योग्य नहीं हूं, तो एडिटेक्स ढीली फोकस नहीं करता है।
14

इस मामले में मेरे पास एक और उपाय है। मैंने जवाब अपडेट कर दिया है।
सर्गेई ग्लोटोव

2
onTouchEvent कई बार कहा जाता है तो यह एक अच्छा अभ्यास भी नहीं है
19:41 पर यीशु डिमिक्स

13

मैंने इसे लागू करने के लिए गतिविधि में प्रेषण लागू किया:

private EditText mEditText;
private Rect mRect = new Rect();
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    final int action = MotionEventCompat.getActionMasked(ev);

    int[] location = new int[2];
    mEditText.getLocationOnScreen(location);
    mRect.left = location[0];
    mRect.top = location[1];
    mRect.right = location[0] + mEditText.getWidth();
    mRect.bottom = location[1] + mEditText.getHeight();

    int x = (int) ev.getX();
    int y = (int) ev.getY();

    if (action == MotionEvent.ACTION_DOWN && !mRect.contains(x, y)) {
        InputMethodManager input = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        input.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
    }
    return super.dispatchTouchEvent(ev);
}

और मैंने इसका परीक्षण किया, सही काम करता है!


काम करता है, लेकिन इसमें समस्या यह है कि अगर हमारे पास एक से अधिक EditText हैं, तो हमें उस पर भी विचार करने की आवश्यकता है, लेकिन मुझे आपका उत्तर :-) पसंद आया
ललित पोपटानी

getActionMasked (ev) पदावनत है, इसलिए अब उपयोग करें: अंतिम int क्रिया = ev.getActionMasked (); पहली पंक्ति के लिए।
एंड्रयू

12

TextInputEditText (यह दृष्टिकोण EditTextView के साथ भी संगत है ) का उपयोग कर एक अधिक कोटलिन और सामग्री डिज़ाइन तरीका है ...

1. निम्नलिखित विशेषताओं को जोड़कर मूल दृश्य (आपकी गतिविधि / अंश का सामग्री दृश्य) क्लिक करने योग्य और ध्यान देने योग्य बनाएं

android:focusable="true"
android:focusableInTouchMode="true"
android:clickable="true"

2. सभी दृश्य के लिए एक एक्सटेंशन बनाएँ (उदाहरण के लिए ViewExtension.kt फ़ाइल के अंदर):

fun View.hideKeyboard(){
    val inputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    inputMethodManager.hideSoftInputFromWindow(this.windowToken, 0)
}

3. एक BaseTextInputEditText बनाएँ जो TextInputEditText की विरासत है। जब दृश्य केंद्रित न हो तो कीबोर्ड को छिपाने के लिए ऑनफोकसचेंज किए गए तरीके को लागू करें:

class BaseTextInputEditText(context: Context?, attrs: AttributeSet?) : TextInputEditText(context, attrs){
    override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect)
        if (!focused) this.hideKeyboard()
    }
}

4. अपने XML में अपने ब्रांड के नए कस्टम दृश्य को कॉल करें:

<android.support.design.widget.TextInputLayout
        android:id="@+id/textInputLayout"
        ...>

        <com.your_package.BaseTextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            ... />

    </android.support.design.widget.TextInputLayout> 

बस इतना ही। इस दोहराव वाले मामले को संभालने के लिए अपने नियंत्रकों (टुकड़ा या गतिविधि) को संशोधित करने की आवश्यकता नहीं है


हाँ, एक अच्छा है, लेकिन मैं चाहता हूँ कि वहाँ एक सरल तरीका था!
देवीदिजय

11

किसी भी गतिविधि (या गतिविधि के वर्ग का विस्तार) में सार्वजनिक बूलियन डिस्पैचटवेंट (मोशन इवेंट) को ओवरराइड करें

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    View view = getCurrentFocus();
    boolean ret = super.dispatchTouchEvent(event);

    if (view instanceof EditText) {
        View w = getCurrentFocus();
        int scrcoords[] = new int[2];
        w.getLocationOnScreen(scrcoords);
        float x = event.getRawX() + w.getLeft() - scrcoords[0];
        float y = event.getRawY() + w.getTop() - scrcoords[1];

        if (event.getAction() == MotionEvent.ACTION_UP 
 && (x < w.getLeft() || x >= w.getRight() 
 || y < w.getTop() || y > w.getBottom()) ) { 
            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
        }
    }
 return ret;
}

और आपको बस इतना ही करना है


यह सबसे आसान तरीका था जो मुझे काम करने के लिए मिला।
एडिटेक्स

कई EditTexts के साथ इसका परीक्षण किया; यह काम करता हैं! एकमात्र नुकसान यह है कि जब आप एक ड्रैग मूवमेंट करते हैं तो वह भी छिप जाता है।
रोमिनाव

9

मैंने आंद्रे लुइस आईएम के समाधान को संशोधित किया मैंने इसे हासिल किया:

मैंने उसी तरह से सॉफ्ट कीबोर्ड को छिपाने के लिए एक उपयोगिता विधि बनाई, जो आंद्रे लुइज़ आईएम ने की थी:

public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

लेकिन हर दृश्य के लिए एक OnTouchListener रजिस्टर करने के बजाय, जो एक खराब प्रदर्शन देता है, मैंने सिर्फ रूट दृश्य के लिए OnTouchListener पंजीकृत किया। चूँकि जब तक इसका सेवन नहीं हो जाता है, तब तक ईवेंट बुलबुले (एडिट टेक्स्ट, डिफ़ॉल्ट रूप से इसका सेवन करने वाले विचारों में से एक है), यदि यह मूल दृश्य में आता है, तो इसका कारण यह है कि इसका उपभोग नहीं किया गया था, इसलिए मैं सॉफ्ट कीबोर्ड को बंद कर देता हूं।

findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Utils.hideSoftKeyboard(activity);
        return false;
    }
});

1
यह मुझे सुरक्षित लगता है।
superarts.org

9

मुझे पता है कि यह धागा काफी पुराना है, सही उत्तर मान्य लगता है और वहाँ बहुत सारे काम के समाधान हैं, लेकिन मुझे लगता है कि दृष्टिकोण में कहा गया है कि दक्षता और लालित्य के बारे में एक अतिरिक्त लाभ हो सकता है।

मैं अपने गतिविधियों के सभी के लिए इस व्यवहार की जरूरत है, तो मैं एक वर्ग बनाया CustomActivity वर्ग से इनहेरिट गतिविधि और "शौकीन" dispatchTouchEvent कार्य करते हैं। देखभाल करने के लिए मुख्य रूप से दो स्थितियाँ हैं:

  1. यदि फोकस अपरिवर्तित है और कोई व्यक्ति वर्तमान इनपुट फ़ील्ड के बाहर टैप कर रहा है, तो IME को खारिज कर दें
  2. यदि फ़ोकस बदल गया है और अगला फ़ोकस किया गया तत्व किसी भी प्रकार के इनपुट फ़ील्ड का उदाहरण नहीं है, तो IME को हटा दें

यह मेरा परिणाम है:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if(ev.getAction() == MotionEvent.ACTION_UP) {
        final View view = getCurrentFocus();

        if(view != null) {
            final boolean consumed = super.dispatchTouchEvent(ev);

            final View viewTmp = getCurrentFocus();
            final View viewNew = viewTmp != null ? viewTmp : view;

            if(viewNew.equals(view)) {
                final Rect rect = new Rect();
                final int[] coordinates = new int[2];

                view.getLocationOnScreen(coordinates);

                rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight());

                final int x = (int) ev.getX();
                final int y = (int) ev.getY();

                if(rect.contains(x, y)) {
                    return consumed;
                }
            }
            else if(viewNew instanceof EditText || viewNew instanceof CustomEditText) {
                return consumed;
            }

            final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

            inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0);

            viewNew.clearFocus();

            return consumed;
        }
    }       

    return super.dispatchTouchEvent(ev);
}

साइड नोट: इसके अतिरिक्त, मैं इन विशेषताओं को रूट दृश्य में देता हूं ताकि हर इनपुट क्षेत्र पर ध्यान केंद्रित करना संभव हो सके और इनपुट फ़ील्ड को गतिविधि स्टार्टअप पर ध्यान केंद्रित करने से रोका जा सके (सामग्री को "फोकस कैचर" बनाते हुए):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final View view = findViewById(R.id.content);

    view.setFocusable(true);
    view.setFocusableInTouchMode(true);
}

सुपर इसके काम ठीक धन्यवाद !! मैंने तुम्हारे उत्तर के लिए एक वर रखा है।
विजय

2
मुझे लगता है कि जटिल लेआउट के लिए यह सबसे अच्छा समाधान है। लेकिन मुझे अब तक 2 नुकसान मिले हैं: 1. EditText संदर्भ मेनू स्पष्ट नहीं है - इस पर कोई भी क्लिक EditText से फ़ोकस खोने का कारण बनता है। जब हमारा EditText किसी दृश्य के निचले भाग पर होता है और हम लंबे समय तक उस पर क्लिक करते हैं (शब्द का चयन करने के लिए), उसके बाद कीबोर्ड से पता चलता है कि हमारा "क्लिक पॉइंट" कीबोर्ड पर है, एडिट टेक्स्ट पर नहीं - इसलिए हम फिर से फोकस खो देते हैं: /
एडिट टेक्स्ट sosite

@sosite, मुझे लगता है कि मैंने अपने उत्तर में उन सीमाओं को संबोधित किया है; जरा देखो तो।
एंडी डेनी

6

मुझे dispatchTouchEventhtafoya द्वारा किए गए कॉलिंग के दृष्टिकोण को पसंद आया , लेकिन:

  • मुझे टाइमर वाला हिस्सा समझ नहीं आया (पता नहीं क्यों डाउनटाइम मापना आवश्यक होना चाहिए?)
  • मुझे हर दृश्य-परिवर्तन के साथ सभी EditTexts को पंजीकृत / अपंजीकृत करना पसंद नहीं है (जटिल पदानुक्रमों में बहुत सारे दृश्य और संपादनटैक्स हो सकते हैं)

तो, मैंने इसे कुछ हद तक आसान उपाय बना दिया:

@Override
public boolean dispatchTouchEvent(final MotionEvent ev) {
    // all touch events close the keyboard before they are processed except EditText instances.
    // if focus is an EditText we need to check, if the touchevent was inside the focus editTexts
    final View currentFocus = getCurrentFocus();
    if (!(currentFocus instanceof EditText) || !isTouchInsideView(ev, currentFocus)) {
        ((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE))
            .hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
    return super.dispatchTouchEvent(ev);
}

/**
 * determine if the given motionevent is inside the given view.
 * 
 * @param ev
 *            the given view
 * @param currentFocus
 *            the motion event.
 * @return if the given motionevent is inside the given view
 */
private boolean isTouchInsideView(final MotionEvent ev, final View currentFocus) {
    final int[] loc = new int[2];
    currentFocus.getLocationOnScreen(loc);
    return ev.getRawX() > loc[0] && ev.getRawY() > loc[1] && ev.getRawX() < (loc[0] + currentFocus.getWidth())
        && ev.getRawY() < (loc[1] + currentFocus.getHeight());
}

एक नुकसान है:

एक EditTextसे दूसरे में स्विच करने से EditTextकीबोर्ड छिप जाता है और फिर से शुरू हो जाता है - मेरे मामले में यह उस तरह से वांछित है, क्योंकि यह दिखाता है कि आपने अन्य इनपुट घटकों के बीच स्विच किया था।


इस विधि ने मेरे फ्रैगमेंटएक्टिविटी के साथ सिर्फ प्लग-एंड-प्ले करने में सक्षम होने के मामले में सबसे अच्छा काम किया।
BillyRayCyrus 20

धन्यवाद, यह सबसे अच्छा तरीका है! मैंने सिर्फ ईवेंट एक्शन के लिए जाँच को भी जोड़ा: int क्रिया = ev.getActionMasked (); if (क्रिया == MotionEvent.ACTION_DOWN || क्रिया == MotionEvent.ACTION_POINTER_DOWN) {...}
sergey.n

धन्यवाद ! आपने मेरा समय बचा लिया..बस जवाब।
.००।

6

दलील: मैं मानता हूं कि मेरा कोई ताल्लुक नहीं है, लेकिन कृपया मेरे जवाब को गंभीरता से लें।

मुसीबत: कीबोर्ड से दूर क्लिक करने या न्यूनतम कोड के साथ पाठ को संपादित करने पर नरम कीबोर्ड को खारिज करें।

समाधान: बाहरी पुस्तकालय जिसे बटरकैंफ के नाम से जाना जाता है

एक पंक्ति समाधान:

@OnClick(R.id.activity_signup_layout) public void closeKeyboard() { ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); }

अधिक पठनीय समाधान:

@OnClick(R.id.activity_signup_layout) 
public void closeKeyboard() {
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

स्पष्टीकरण: कार्य की XML लेआउट अभिभावक ID पर OnClick श्रोता को बाँधें, ताकि लेआउट पर कोई भी क्लिक (पाठ या कीबोर्ड पर संपादित न हो) कोड के उस स्निपेट को चलाएगा जो कीबोर्ड को छिपा देगा।

उदाहरण: यदि आपकी लेआउट फ़ाइल R.layout.my_layout है और आपकी लेआउट आईडी R.id.my_layout_id है, तो आपकी Butterknife बाइंड कॉल इस तरह दिखनी चाहिए:

(@OnClick(R.id.my_layout_id) 
public void yourMethod {
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

बटरकनीफ़ डॉक्यूमेंटेशन लिंक: http://jakewharton.github.io/butterknife/

प्लग: बटरकनीफ़ आपके एंड्रॉइड विकास में क्रांति लाएगा। गौर किजिए।

नोट: बाहरी पुस्तकालय Butterknife के उपयोग के बिना एक ही परिणाम प्राप्त किया जा सकता है। बस ऊपर वर्णित के रूप में मूल लेआउट के लिए एक OnClickListener सेट करें।


बहुत बढ़िया, सही समाधान! धन्यवाद।
nullforlife

6

कोटलिन में, हम निम्नलिखित कर सकते हैं। सभी विचारों को पुनरावृत्त करने की आवश्यकता नहीं है। यह टुकड़ों के लिए भी काम करेगा।

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    currentFocus?.let {
        val imm: InputMethodManager = getSystemService(
            Context.INPUT_METHOD_SERVICE
        ) as (InputMethodManager)
        imm.hideSoftInputFromWindow(it.windowToken, 0)
    }
    return super.dispatchTouchEvent(ev)
}

टुकड़े से काम नहीं करता है
Nurseyit Tursunkulov

यह काम करता है लेकिन इसमें एक बग है। उदाहरण के लिए, यदि मैं टेक्स्टव्यू में टेक्स्ट पेस्ट करना चाहता हूं, तो कीबोर्ड छुपाता है और फिर दिखाता है। यह थोड़ा कष्टप्रद है।
जॉर्ज शाल्वशिवली

तो मुझे सबसे अच्छा उपाय बताओ ..
साईं

4

यहाँ fje के उत्तर पर एक और भिन्नता है जो sosite द्वारा उठाए गए मुद्दों को संबोधित करता है।

यहां विचार यह है कि गतिविधि की dispatchTouchEventविधि में नीचे और ऊपर की कार्रवाई दोनों को संभालना है । डाउन एक्शन पर, हम वर्तमान में फ़ोकस किए गए दृश्य (यदि कोई हो) पर ध्यान दें और क्या स्पर्श इसके अंदर था, तो बाद में जानकारी के उन दोनों बिट्स को सहेजना।

ऊपर की कार्रवाई पर, हम पहले डिस्पैच करते हैं, संभावित रूप से ध्यान केंद्रित करने के लिए एक और दृश्य की अनुमति देते हैं। यदि उसके बाद, वर्तमान में केंद्रित दृश्य मूल रूप से केंद्रित दृश्य है, और डाउन टच उस दृश्य के अंदर था, तो हम कीबोर्ड को खुला छोड़ देते हैं।

यदि वर्तमान में केंद्रित दृश्य मूल रूप से केंद्रित दृश्य से भिन्न है और यह एक है EditText, तो हम कीबोर्ड को भी खुला छोड़ देते हैं।

अन्यथा हम इसे बंद कर देते हैं।

तो, संक्षेप में, यह इस प्रकार काम करता है:

  • वर्तमान में केंद्रित के अंदर स्पर्श करने पर EditText, कीबोर्ड खुला रहता है
  • जब EditTextकिसी दूसरे से ध्यान केंद्रित किया जाता है EditText, तो कीबोर्ड खुला रहता है (बंद / पुनः बंद नहीं होता है)
  • जब वर्तमान में बाहर कहीं भी स्पर्श किया EditTextजाता है EditText, तो वह दूसरा नहीं होता है , कीबोर्ड बंद हो जाता है
  • जब EditTextप्रासंगिक कार्रवाई पट्टी (कट / कॉपी / पेस्ट बटन के साथ) लाने के लिए लंबे समय से दबाया जाता है, तो कीबोर्ड खुला रहता है, भले ही यूपी कार्रवाई फोकस के बाहर हुई EditText(जो सीएबी के लिए जगह बनाने के लिए नीचे चली गई) । ध्यान दें, हालांकि, जब आप कैब में एक बटन पर टैप करते हैं, तो यह कीबोर्ड को बंद कर देगा। यह वांछनीय हो सकता है या नहीं; यदि आप एक क्षेत्र से काटकर / कॉपी करके दूसरे में पेस्ट करना चाहते हैं, तो यह होगा। यदि आप वापस उसी में चिपकाना चाहते हैंEditText , तो यह नहीं होगा।
  • जब फ़ोकस EditTextस्क्रीन के निचले भाग पर होता है और आप इसे चुनने के लिए कुछ टेक्स्ट पर लंबे समय तक क्लिक करते हैं, तो EditTextफ़ोकस रहता है और इसलिए कीबोर्ड आपकी इच्छानुसार खुलता है, क्योंकि हम डाउन एक्शन पर "टच द व्यू बाउंड्स" चेक करते हैं ऊपर की कार्रवाई नहीं।

    private View focusedViewOnActionDown;
    private boolean touchWasInsideFocusedView;
    
    
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                focusedViewOnActionDown = getCurrentFocus();
                if (focusedViewOnActionDown != null) {
                    final Rect rect = new Rect();
                    final int[] coordinates = new int[2];
    
                    focusedViewOnActionDown.getLocationOnScreen(coordinates);
    
                    rect.set(coordinates[0], coordinates[1],
                            coordinates[0] + focusedViewOnActionDown.getWidth(),
                            coordinates[1] + focusedViewOnActionDown.getHeight());
    
                    final int x = (int) ev.getX();
                    final int y = (int) ev.getY();
    
                    touchWasInsideFocusedView = rect.contains(x, y);
                }
                break;
    
            case MotionEvent.ACTION_UP:
    
                if (focusedViewOnActionDown != null) {
                    // dispatch to allow new view to (potentially) take focus
                    final boolean consumed = super.dispatchTouchEvent(ev);
    
                    final View currentFocus = getCurrentFocus();
    
                    // if the focus is still on the original view and the touch was inside that view,
                    // leave the keyboard open.  Otherwise, if the focus is now on another view and that view
                    // is an EditText, also leave the keyboard open.
                    if (currentFocus.equals(focusedViewOnActionDown)) {
                        if (touchWasInsideFocusedView) {
                            return consumed;
                        }
                    } else if (currentFocus instanceof EditText) {
                        return consumed;
                    }
    
                    // the touch was outside the originally focused view and not inside another EditText,
                    // so close the keyboard
                    InputMethodManager inputMethodManager =
                            (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    inputMethodManager.hideSoftInputFromWindow(
                        focusedViewOnActionDown.getWindowToken(), 0);
                    focusedViewOnActionDown.clearFocus();
    
                    return consumed;
                }
                break;
        }
    
        return super.dispatchTouchEvent(ev);
    }

4

यह बहुत सरल है, बस अपने हाल के लेआउट को इस कोड द्वारा क्लिक करने योग्य बनाएं:

android:id="@+id/loginParentLayout"
android:clickable="true"
android:focusableInTouchMode="true"

और फिर उस लेआउट के लिए एक विधि और एक OnClickListner लिखें, ताकि जब ऊपरवाले के लेआउट को किसी भी स्थान पर स्पर्श किया जाए, तो वह उस पद्धति को कॉल करेगा जिसमें आप कीबोर्ड को खारिज करने के लिए कोड लिखेंगे। निम्नलिखित दोनों के लिए कोड है; // आपको यह OnCreate () में लिखना है

 yourLayout.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View view) {
                    hideKeyboard(view);
                }
            });

श्रोता से बुलाया विधि: -

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

4

मुझे इस सरल आवश्यकता के लिए स्वीकृत उत्तर बिट कॉम्प्लेक्स लगता है। यहां मेरे लिए बिना किसी गड़बड़ के काम किया गया है।

findViewById(R.id.mainLayout).setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
            return false;
        }
    });

1
यदि आप NestedScrollViewजटिल लेआउट का उपयोग करते हैं, तो स्वीकृत उत्तर देखें: stackoverflow.com/a/11656129/2914140 । आपको पता होना चाहिए कि अन्य कंटेनर स्पर्श का उपभोग कर सकते हैं।
CoolMind

3

आईफोन एक ही मुद्दे पर आधारित एक सरल दृष्टिकोण है। बस टच इवेंट पर पृष्ठभूमि के लेआउट को ओवरराइड करें, जहां संपादन पाठ निहित है। इस कोड को गतिविधि के ऑनक्रीट (login_fondo रूट लेआउट है) में उपयोग करें:

    final LinearLayout llLogin = (LinearLayout)findViewById(R.id.login_fondo);
    llLogin.setOnTouchListener(
            new OnTouchListener()
            {
                @Override
                public boolean onTouch(View view, MotionEvent ev) {
                    InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(
                            android.content.Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(mActivity.getCurrentFocus().getWindowToken(), 0);
                    return false;
                }
            });

1
जैसा कि मैंने कहा था और मुझे याद है, यह केवल तभी काम करता है जब फॉर्म एक स्क्रॉल दृश्य के अंदर न हो।
htafoya

1
यह बहुत अच्छी तरह से काम नहीं करता है अगर पृष्ठभूमि लेआउट में अन्य बच्चे लेआउट हैं।
एक्सईफेक्ट

यह याद दिलाने के लिए धन्यवाद कि onClick एकमात्र विकल्प नहीं था।
हरप्रीत

3

सॉफ्ट कीबोर्ड दिखाने / छिपाने की विधि

InputMethodManager inputMethodManager = (InputMethodManager) currentActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
    if (isShow) {
        if (currentActivity.getCurrentFocus() == null) {
            inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
        } else {
            inputMethodManager.showSoftInput(currentActivity.getCurrentFocus(), InputMethodManager.SHOW_FORCED);    
        }

    } else {
        if (currentActivity.getCurrentFocus() == null) {
            inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
        } else {
            inputMethodManager.hideSoftInputFromInputMethod(currentActivity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);    
        }

    }

मुझे आशा है कि वे उपयोगी रहे हैं


3

यह मेरे लिए सबसे आसान उपाय है (और मेरे द्वारा काम किया गया)।

यह कीबोर्ड को छिपाने की विधि है।

public void hideKeyboard(View view){
        if(!(view instanceof EditText)){
            InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
        }
    }

अब गतिविधि के मूल लेआउट की ऑनक्लिक विशेषता को hideKeyboardअपनी XML फ़ाइल के डिज़ाइन दृश्य या कोड के नीचे कोड लिखने से डिज़ाइन विधि से ऊपर की विधि पर सेट करें।

android:onClick="hideKeyboard"

2

मैंने विधि को परिष्कृत किया है, निम्नलिखित कोड को कुछ यूआई उपयोगिता वर्ग (अधिमानतः, आवश्यक नहीं) में रखा है ताकि इसे अपने उद्देश्य की सेवा के लिए आपकी सभी गतिविधि या फ्रैगमेंट कक्षाओं से एक्सेस किया जा सके।

public static void serachAndHideSoftKeybordFromView(View view, final Activity act) {
    if(!(view instanceof EditText)) {
        view.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard(act);
                return false;
            }
        });
    }
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            View nextViewInHierarchy = ((ViewGroup) view).getChildAt(i);
            serachAndHideSoftKeybordFromView(nextViewInHierarchy, act);
        }
    }
}
public static void hideSoftKeyboard (Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

फिर उदाहरण के लिए कहें कि आपको इसे गतिविधि से कॉल करने की आवश्यकता है, इसे निम्नानुसार कॉल करें;

UIutils.serachAndHideSoftKeybordFromView(findViewById(android.R.id.content), YourActivityName.this);

नोटिस

findViewById (android.R.id.content)

यह हमें वर्तमान समूह का मूल दृश्य देता है (आपने आईडी को रूट दृश्य पर सेट नहीं किया होगा)।

चियर्स :)



2

गतिविधि

 @Override
 public boolean dispatchTouchEvent(MotionEvent ev) {
     ScreenUtils.hideKeyboard(this, findViewById(android.R.id.content).getWindowToken());
     return super.dispatchTouchEvent(ev);
 }

ScreenUtils

 public static void hideKeyboard(Context context, IBinder windowToken) {
     InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
     imm.hideSoftInputFromWindow(windowToken, InputMethodManager.HIDE_NOT_ALWAYS);
 }

3
यह कोड सरल है, लेकिन इसमें एक स्पष्ट मुद्दा है: यह कीबोर्ड को बंद कर देता है जब कहीं भी छुआ जाता है। यदि आप इनपुट कर्सर को स्थानांतरित करने के लिए EditText के किसी भिन्न स्थान पर टैप करते हैं, तो यह कीबोर्ड को छुपाता है, और कीबोर्ड सिस्टम द्वारा फिर से पॉप अप करता है।
डेमन वेजिटेबल्स

2

बस इस कोड को वर्ग @Overide में जोड़ें

public boolean dispatchTouchEvent(MotionEvent ev) {
    View view = getCurrentFocus();
    if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("android.webkit.")) {
        int scrcoords[] = new int[2];
        view.getLocationOnScreen(scrcoords);
        float x = ev.getRawX() + view.getLeft() - scrcoords[0];
        float y = ev.getRawY() + view.getTop() - scrcoords[1];
        if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom())
            ((InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((this.getWindow().getDecorView().getApplicationWindowToken()), 0);
    }
    return super.dispatchTouchEvent(ev);
}

3
हालांकि यह प्रश्न का उत्तर दे सकता है, उत्तर के आवश्यक भागों की व्याख्या करना बेहतर है और संभवतः ओपी कोड के साथ समस्या क्या थी।
पिरहो

हां @ पिरहो मैं भी आपसे सहमत हूं हसीब को उचित जवाब देने पर ध्यान केंद्रित करने की आवश्यकता है।
दिलीप

2
@Dilip क्या आप जानते हैं कि आप उन टिप्पणियों को भी रद्द कर सकते हैं जिनसे आप सहमत हैं? यह सिर्फ टिप्पणी अनुभाग को साफ रखने के लिए है ताकि कई टिप्पणियां वास्तव में एक ही बिंदु पर न हों।
पीहरो

2

इसके बजाय सभी विचारों के माध्यम से पुनरावृत्ति या dispatchTouchEvent ओवरराइडिंग।

गतिविधि के onUserInteraction () को ओवरराइड क्यों न करें, जब भी उपयोगकर्ता EditText के बाहर टैप करता है, तो यह सुनिश्चित करता है कि कीबोर्ड बर्खास्त हो जाएगा।

जब EditText स्क्रॉलव्यू के अंदर होगा तब भी काम करेगा।

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

यह बेहतर उत्तर है
ओवलुका

हाँ! यह एक सुपर साफ जवाब है। और यदि आप एक AbstractActivity बनाते हैं जो आपकी अन्य सभी गतिविधियाँ बढ़ाती हैं, तो आप इसे अपने ऐप में डिफ़ॉल्ट व्यवहार के रूप में देख सकते हैं।
Wildcat12

1

मुझे यह काम फर्नांडो कैमारैगो के समाधान पर एक मामूली रूप से मिला। अपनी ऑनक्रिएट विधि में मैं एक सिंगल ऑनटचलिस्ट को रूट व्यू में संलग्न करता हूं, लेकिन एक तर्क के रूप में गतिविधि के बजाय दृश्य भेजें।

        findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {           
        public boolean onTouch(View v, MotionEvent event) {
            Utils.hideSoftKeyboard(v);
            return false;
        }
    });

एक अलग बर्तन वर्ग में है ...

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

1

यह पुराना हो सकता है लेकिन मुझे यह काम एक कस्टम वर्ग का अनुमान लगाकर मिला है

public class DismissKeyboardListener implements OnClickListener {

    Activity mAct;

    public DismissKeyboardListener(Activity act) {
        this.mAct = act;
    }

    @Override
    public void onClick(View v) {
        if ( v instanceof ViewGroup ) {
            hideSoftKeyboard( this.mAct );
        }
    }       
}

public void hideSoftKeyboard(Activity activity) {
        InputMethodManager imm = (InputMethodManager)
        getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
}

यहां सबसे अच्छा अभ्यास हेल्पर क्लास बनाना है और प्रत्येक कंटेनर रिलेटिव / लीनियर लेआउट को इसे लागू करना चाहिए।

**** केवल नोट करें मुख्य कंटेनर को इस वर्ग को लागू करना चाहिए (अनुकूलन के लिए) ****

और इसे इस तरह लागू करें:

Parent.setOnClickListener( new DismissKeyboardListener(this) ); 

यह गतिविधि के लिए कीवर्ड है। इसलिए यदि आप खंड पर हैं तो आप गेटएक्टिविटी () की तरह उपयोग करते हैं;

--- अंगूठे अगर यह आपकी मदद करता है ... --- राल्फ को खुश करता है ---


1

यह fje के उत्तर का थोड़ा संशोधित संस्करण है, जो ज्यादातर पूरी तरह से काम करता है।

यह संस्करण ACTION_DOWN का उपयोग करता है इसलिए स्क्रॉल क्रिया करने से भी कीबोर्ड बंद हो जाता है। जब तक आप किसी अन्य EditText पर क्लिक नहीं करते हैं, तब तक यह घटना का प्रचार नहीं करता है। इसका मतलब यह है कि आपके EditText के बाहर कहीं भी क्लिक करने पर, यहां तक ​​कि एक और क्लिक करने योग्य पर, बस कीबोर्ड बंद हो जाता है।

@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
    if(ev.getAction() == MotionEvent.ACTION_DOWN)
    {
        final View view = getCurrentFocus();

        if(view != null)
        {
            final View viewTmp = getCurrentFocus();
            final View viewNew = viewTmp != null ? viewTmp : view;

            if(viewNew.equals(view))
            {
                final Rect rect = new Rect();
                final int[] coordinates = new int[2];

                view.getLocationOnScreen(coordinates);

                rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight());

                final int x = (int) ev.getX();
                final int y = (int) ev.getY();

                if(rect.contains(x, y))
                {
                    super.dispatchTouchEvent(ev);
                    return true;
                }
            }
            else if(viewNew instanceof EditText || viewNew instanceof CustomEditText)
            {
                super.dispatchTouchEvent(ev);
                return true;
            }

            final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

            inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0);

            viewNew.clearFocus();

            return true;
        }
    }
    return super.dispatchTouchEvent(ev);
}

कुछ यहीं नहीं दिखता है; तुम दोनों बताए रहे हैं viewऔर viewTmpकरने के लिए getCurrentFocus(), इसलिए वे हमेशा एक ही मूल्य होने के लिए जा रहे हैं।
एंडी डेनी

1

मैंने इस तरह किया है:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
   View view = getCurrentFocus();
   if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("android.webkit.")) {
            int scrcoords[] = new int[2];
            view.getLocationOnScreen(scrcoords);
            float x = ev.getRawX() + view.getLeft() - scrcoords[0];
            float y = ev.getRawY() + view.getTop() - scrcoords[1];
            if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom())
                hideKeyboard(this);
        }
    return super.dispatchTouchEvent(ev);
}

कीबोर्ड कोड छिपाएँ :

public static void hideKeyboard(Activity act) {
    if(act!=null)
      ((InputMethodManager)act.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((act.getWindow().getDecorView().getApplicationWindowToken()), 0);
  }

किया हुआ

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.