Um diesen Wahnsinn zu klären, möchte ich mich zunächst im Namen aller Android-Nutzer für Googles geradezu lächerliche Behandlung der Softtastatur entschuldigen. Der Grund, warum es so viele unterschiedliche Antworten für dieselbe einfache Frage gibt, ist, dass diese API, wie viele andere in Android, schrecklich gestaltet ist. Ich kann mir keinen höflichen Weg vorstellen, es auszudrücken.
Ich möchte die Tastatur verstecken. Ich erwarte, Android mit der folgenden Aussage zu versorgen : Keyboard.hide()
. Das Ende. Vielen Dank. Aber Android hat ein Problem. Sie müssen die verwenden InputMethodManager
, um die Tastatur auszublenden. OK, gut, dies ist die Android-API für die Tastatur. ABER! Sie benötigen eine Context
, um Zugriff auf das IMM zu erhalten. Jetzt haben wir ein Problem. Möglicherweise möchte ich die Tastatur vor einer statischen oder Utility-Klasse ausblenden, die keine Verwendung hat oder benötigt Context
. oder Und noch viel schlimmer, das IMM erfordert, dass Sie angeben, vor was View
(oder noch schlimmer, was Window
) Sie die Tastatur verstecken möchten.
Dies macht das Verstecken der Tastatur so schwierig. Lieber Google: Wenn ich das Rezept für einen Kuchen nachschlage, gibt es keinen RecipeProvider
auf der Erde, der sich weigert, mir das Rezept zu geben, es sei denn, ich antworte zuerst, von wem der Kuchen gegessen wird UND wo er gegessen wird !!
Diese traurige Geschichte endet mit der hässlichen Wahrheit: Um die Android-Tastatur zu verbergen, müssen Sie zwei Arten der Identifizierung angeben: a Context
und entweder a View
oder a Window
.
Ich habe eine statische Dienstprogrammmethode erstellt, die die Aufgabe SEHR solide erledigen kann, vorausgesetzt, Sie rufen sie von einem auf 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);
}
Beachten Sie, dass diese Dienstprogrammmethode NUR funktioniert, wenn sie von einem Activity
! Die obige Methode ruft getCurrentFocus
das Ziel Activity
auf, um das richtige Fenstertoken abzurufen.
Angenommen, Sie möchten die Tastatur vor einem EditText
gehosteten in einem verstecken DialogFragment
? Sie können die obige Methode dafür nicht verwenden:
hideKeyboard(getActivity()); //won't work
Dies funktioniert nicht, da Sie einen Verweis auf den Fragment
Host des Hosts übergeben Activity
, der keine fokussierte Kontrolle hat, solange der Fragment
angezeigt wird! Beeindruckend! Um die Tastatur vor Fragmenten zu verbergen, greife ich auf die niedrigere, häufigere und hässlichere Ebene zurück:
public static void hideKeyboardFrom(Context context, View view) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
Im Folgenden finden Sie einige zusätzliche Informationen, die aus mehr Zeitverschwendung bei der Suche nach dieser Lösung gewonnen wurden:
Informationen zu windowSoftInputMode
Es gibt noch einen weiteren Streitpunkt, den Sie beachten sollten. Standardmäßig weist Android dem ersten EditText
oder fokussierbaren Steuerelement in Ihrem automatisch den anfänglichen Fokus zu Activity
. Daraus folgt natürlich, dass die InputMethod (normalerweise die Softtastatur) auf das Fokusereignis reagiert, indem sie sich selbst zeigt. Wenn das windowSoftInputMode
Attribut in auf AndroidManifest.xml
gesetzt ist, stateAlwaysHidden
wird die Tastatur angewiesen, diesen automatisch zugewiesenen Anfangsfokus zu ignorieren.
<activity
android:name=".MyActivity"
android:windowSoftInputMode="stateAlwaysHidden"/>
Es ist fast unglaublich, dass es nichts zu tun scheint, um zu verhindern, dass sich die Tastatur öffnet, wenn Sie das Steuerelement berühren (es sei denn focusable="false"
und / oder focusableInTouchMode="false"
dem Steuerelement zugewiesen sind). Anscheinend gilt die Einstellung windowSoftInputMode nur für automatische Fokusereignisse, nicht für Fokusereignisse, die durch Berührungsereignisse ausgelöst werden.
Daher stateAlwaysHidden
ist in der Tat sehr schlecht benannt. Es sollte vielleicht stattdessen aufgerufen ignoreInitialFocus
werden.
Hoffe das hilft.
UPDATE: Weitere Möglichkeiten, um ein Fenstertoken zu erhalten
Wenn keine fokussierte Ansicht vorhanden ist (z. B. wenn Sie nur Fragmente geändert haben), gibt es andere Ansichten, die ein nützliches Fenstertoken bereitstellen.
Dies sind Alternativen für den obigen Code. if (view == null) view = new View(activity);
Diese beziehen sich nicht explizit auf Ihre Aktivität.
Innerhalb einer Fragmentklasse:
view = getView().getRootView().getWindowToken();
Gegeben ein Fragment fragment
als Parameter:
view = fragment.getView().getRootView().getWindowToken();
Ausgehend von Ihrem Inhaltskörper:
view = findViewById(android.R.id.content).getRootView().getWindowToken();
UPDATE 2: Deaktivieren Sie den Fokus, um zu vermeiden, dass die Tastatur erneut angezeigt wird, wenn Sie die App über den Hintergrund öffnen
Fügen Sie diese Zeile am Ende der Methode hinzu:
view.clearFocus();