Untuk membantu memperjelas kegilaan ini, saya ingin memulai dengan meminta maaf atas nama semua pengguna Android atas perlakuan konyol Google terhadap keyboard lunak. Alasan ada begitu banyak jawaban, masing-masing berbeda, untuk pertanyaan sederhana yang sama adalah karena API ini, seperti banyak lainnya di Android, dirancang dengan mengerikan. Saya tidak bisa memikirkan cara yang sopan untuk menyatakannya.
Saya ingin menyembunyikan keyboard. Saya berharap untuk memberikan Android dengan pernyataan berikut: Keyboard.hide(). Tamat. Terima kasih banyak. Tapi Android punya masalah. Anda harus menggunakan InputMethodManageruntuk menyembunyikan keyboard. OKE, baiklah, ini adalah API Android untuk keyboard. TAPI! Anda harus memiliki Contextuntuk mendapatkan akses ke IMM. Sekarang kita punya masalah. Saya mungkin ingin menyembunyikan keyboard dari kelas statis atau utilitas yang tidak memiliki kegunaan atau kebutuhan apa pun Context. atau Dan JAUH lebih buruk, IMM mengharuskan Anda menentukan apa View(atau bahkan lebih buruk, apa Window) yang ingin Anda sembunyikan dari keyboard.
Inilah yang membuat menyembunyikan keyboard sangat menantang. Dear Google: Ketika saya mencari resep kue, tidak ada RecipeProviderdi Bumi yang akan menolak untuk memberi saya resep kecuali saya pertama kali menjawab SIAPA kue itu akan dimakan oleh DAN di mana ia akan dimakan !!
Kisah sedih ini berakhir dengan kebenaran yang buruk: untuk menyembunyikan keyboard Android, Anda akan diminta untuk memberikan 2 bentuk identifikasi: a Contextdan salah satu Viewatau a Window.
Saya telah membuat metode utilitas statis yang dapat melakukan pekerjaan SANGAT solid, asalkan Anda menyebutnya dari sebuah 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);
}
Ketahuilah bahwa metode utilitas ini HANYA berfungsi saat dipanggil dari Activity! Metode di atas memanggil getCurrentFocustarget Activityuntuk mengambil token jendela yang tepat.
Tapi misalkan Anda ingin menyembunyikan keyboard dari EditTexthost di DialogFragment? Anda tidak dapat menggunakan metode di atas untuk itu:
hideKeyboard(getActivity()); //won't work
Ini tidak akan berhasil karena Anda akan memberikan referensi ke Fragmenthost 's Activity, yang tidak akan memiliki kontrol terfokus saat Fragmentditampilkan! Wow! Jadi, untuk menyembunyikan keyboard dari fragmen, saya beralih ke level yang lebih rendah, lebih umum, dan lebih jelek:
public static void hideKeyboardFrom(Context context, View view) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
Di bawah ini adalah beberapa informasi tambahan yang diperoleh dari semakin banyak waktu yang terbuang mengejar solusi ini:
Tentang windowSoftInputMode
Masih ada hal lain yang perlu diperhatikan. Secara default, Android akan secara otomatis menetapkan fokus awal ke EditTextkontrol pertama atau yang dapat fokus di Activity. Secara alami, InputMethod (biasanya keyboard lunak) akan merespons acara fokus dengan menunjukkan dirinya. The windowSoftInputModeatribut dalam AndroidManifest.xml, ketika diatur ke stateAlwaysHidden, menginstruksikan keyboard untuk mengabaikan fokus awal ini secara otomatis ditugaskan.
<activity
android:name=".MyActivity"
android:windowSoftInputMode="stateAlwaysHidden"/>
Hampir tidak dapat dipercaya, tampaknya tidak melakukan apa pun untuk mencegah keyboard membuka ketika Anda menyentuh kontrol (kecuali focusable="false"dan / atau focusableInTouchMode="false"ditugaskan ke kontrol). Rupanya, pengaturan windowSoftInputMode hanya berlaku untuk acara fokus otomatis, bukan untuk memfokuskan acara yang dipicu oleh acara sentuh.
Oleh karena itu, stateAlwaysHiddenmemang SANGAT buruk namanya. Mungkin seharusnya disebut ignoreInitialFocussebaliknya.
Semoga ini membantu.
PEMBARUAN: Lebih banyak cara untuk mendapatkan token jendela
Jika tidak ada tampilan terfokus (mis. Bisa terjadi jika Anda baru saja mengubah fragmen), ada tampilan lain yang akan menyediakan token jendela yang bermanfaat.
Ini adalah alternatif untuk kode di atas. if (view == null) view = new View(activity); Ini tidak merujuk secara eksplisit ke aktivitas Anda.
Di dalam kelas fragmen:
view = getView().getRootView().getWindowToken();
Diberikan fragmen fragmentsebagai parameter:
view = fragment.getView().getRootView().getWindowToken();
Mulai dari badan konten Anda:
view = findViewById(android.R.id.content).getRootView().getWindowToken();
UPDATE 2: Hapus fokus untuk menghindari menampilkan keyboard lagi jika Anda membuka aplikasi dari latar belakang
Tambahkan baris ini ke akhir metode:
view.clearFocus();