इस पागलपन को स्पष्ट करने में मदद करने के लिए, मैं Google के सभी उपयोगकर्ताओं की ओर से नरम कीबोर्ड के सर्वथा हास्यास्पद उपचार के लिए माफी माँगता हूँ। कारण इतने सारे उत्तर हैं, एक ही सरल प्रश्न के लिए प्रत्येक अलग, क्योंकि यह एपीआई, एंड्रॉइड के कई अन्य लोगों की तरह, बहुत ही खराब तरीके से डिज़ाइन किया गया है। मैं इसे बताने का कोई विनम्र तरीका नहीं सोच सकता।
मैं कीबोर्ड को छिपाना चाहता हूं। मैं निम्नलिखित कथन के साथ Android प्रदान करने की उम्मीद करता हूं Keyboard.hide()
:। समाप्त। आपका बहुत बहुत धन्यवाद। लेकिन Android में एक समस्या है। InputMethodManager
कीबोर्ड को छिपाने के लिए आपको इसका उपयोग करना होगा । ठीक है, ठीक है, यह कीबोर्ड के लिए एंड्रॉइड का एपीआई है। परंतु! Context
IMM तक पहुँचने के लिए आपके पास एक होना आवश्यक है । अब हमें एक समस्या है। मैं कीबोर्ड को एक स्थिर या उपयोगिता वर्ग से छुपाना चाह सकता हूं जिसका कोई उपयोग या आवश्यकता नहीं है Context
। या इससे भी बदतर, IMM के लिए आवश्यक है कि आप निर्दिष्ट करें View
(या इससे भी बदतर, क्या Window
) आप कीबोर्ड से छिपाना चाहते हैं।
यह वह है जो कीबोर्ड को इतना चुनौतीपूर्ण बनाता है। प्रिय Google: जब मैं केक की रेसिपी देख रहा हूँ, तो RecipeProvider
पृथ्वी पर ऐसा कोई भी नहीं है जो मुझे रेसिपी प्रदान करने से मना कर दे, जब तक कि मैं पहले जवाब न दूं कि केक किसके द्वारा खाया जाएगा और कहाँ खाया जाएगा !!
यह दुखद कहानी बदसूरत सच्चाई के साथ समाप्त होती है: एंड्रॉइड कीबोर्ड को छिपाने के लिए, आपको पहचान के 2 रूप प्रदान करने होंगे: a Context
और a View
या a 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
के लिए लक्ष्य की कॉल करती है Activity
।
लेकिन मान लीजिए कि आप किसी EditText
होस्ट से कीबोर्ड को छिपाना चाहते हैं DialogFragment
? आप इसके लिए उपरोक्त विधि का उपयोग नहीं कर सकते हैं:
hideKeyboard(getActivity()); //won't work
यह काम नहीं करेगा क्योंकि आप एक Fragment
मेजबान के लिए एक संदर्भ पारित करेंगे Activity
, जिसमें 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
से आपके पहले या फ़ोकस करने योग्य नियंत्रण पर प्रारंभिक ध्यान केंद्रित करेगा Activity
। यह स्वाभाविक रूप से निम्नानुसार है कि InputMethod (आमतौर पर सॉफ्ट कीबोर्ड) स्वयं को दिखा कर फोकस ईवेंट का जवाब देगा। windowSoftInputMode
में विशेषता AndroidManifest.xml
है, जब करने के लिए सेट stateAlwaysHidden
, कीबोर्ड इस स्वत: सौंपा प्रारंभिक ध्यान अनदेखी करने के लिए निर्देश देता है।
<activity
android:name=".MyActivity"
android:windowSoftInputMode="stateAlwaysHidden"/>
लगभग अविश्वसनीय रूप से, यह कीबोर्ड को खोलने से रोकने के लिए कुछ भी नहीं करता है जब आप नियंत्रण को छूते हैं (जब तक focusable="false"
और नियंत्रण focusableInTouchMode="false"
को सौंपा नहीं जाता है)। स्पष्ट रूप से, windowSoftInputMode सेटिंग केवल स्वचालित फोकस घटनाओं पर लागू होती है, स्पर्श घटनाओं द्वारा ट्रिगर की गई घटनाओं पर ध्यान केंद्रित करने के लिए नहीं।
इसलिए, stateAlwaysHidden
वास्तव में बहुत खराब नाम है। इसे शायद ignoreInitialFocus
इसके बजाय कहा जाना चाहिए ।
उम्मीद है की यह मदद करेगा।
UPDATE: विंडो टोकन प्राप्त करने के और तरीके
यदि कोई केंद्रित दृश्य नहीं है (उदाहरण के लिए, यदि आप केवल टुकड़ों को बदल सकते हैं तो हो सकता है), ऐसे अन्य विचार हैं जो एक उपयोगी विंडो टोकन की आपूर्ति करेंगे।
उपरोक्त कोड के लिए ये विकल्प हैं 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();