Wie verstecke ich eine weiche Tastatur auf Android, nachdem ich außerhalb von EditText geklickt habe?

354

Ok, jeder weiß, dass zum Implementieren einer Tastatur Folgendes implementiert werden muss:

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

Aber die große Sache hier ist, wie man die Tastatur versteckt, wenn der Benutzer einen anderen Ort berührt oder auswählt, der kein EditTextSoftKeyboard ist?

Ich habe versucht, das onTouchEvent()für meine Eltern zu verwenden, Activityaber das funktioniert nur, wenn der Benutzer eine andere Ansicht berührt und keine Bildlaufansicht vorhanden ist.

Ich habe erfolglos versucht, einen Touch-, Click- und Focus-Listener zu implementieren.

Ich habe sogar versucht, meine eigene Bildlaufansicht zu implementieren, um Berührungsereignisse abzufangen, aber ich kann nur die Koordinaten des Ereignisses abrufen und nicht die angeklickte Ansicht.

Gibt es einen Standardweg, um dies zu tun? im iPhone war es wirklich einfach.

htafoya
quelle
Nun, mir wurde klar, dass die Bildlaufansicht nicht wirklich das Problem war, sondern die Beschriftungen, die es gibt. Die Ansicht ist ein vertikales Layout mit folgenden Elementen: TextView, EditText, TextView, EditText usw. Die Textansichten lassen den Edittext nicht den Fokus verlieren und die Tastatur ausblenden
htafoya
Eine Lösung finden Sie getFields()hier: stackoverflow.com/questions/7790487/…
Reto
Die Tastatur kann durch Drücken der
Eingabetaste
4
Ich habe diese Antwort gefunden: stackoverflow.com/a/28939113/2610855 Die beste.
Loenix

Antworten:

575

Das folgende Snippet verbirgt einfach die Tastatur:

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

Sie können dies in einer Dienstprogrammklasse ablegen oder, wenn Sie es innerhalb einer Aktivität definieren, den Aktivitätsparameter vermeiden oder aufrufen hideSoftKeyboard(this).

Der schwierigste Teil ist, wann man es nennt. Sie können eine Methode schreiben, die alle Viewin Ihrer Aktivität durchläuft , und prüfen, ob es sich um eine Methode handelt, die instanceof EditTextnicht setOnTouchListenerfür diese Komponente registriert ist , und alles passt zusammen. Falls Sie sich fragen, wie das geht, ist es in der Tat ganz einfach. Hier ist, was Sie tun, Sie schreiben eine rekursive Methode wie die folgende, in der Tat können Sie diese verwenden, um alles zu tun, wie benutzerdefinierte Schriften einzurichten usw. ... Hier ist die Methode

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);
        }
    }
}

Das ist alles, rufen Sie diese Methode einfach nach Ihnen setContentViewin Ihrer Aktivität auf. Wenn Sie sich fragen, welchen Parameter Sie übergeben würden, handelt es sich idum den übergeordneten Container. Weisen Sie idIhrem übergeordneten Container einen zu

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

und ruf an setupUI(findViewById(R.id.parent)), das ist alles.

Wenn Sie dies effektiv nutzen möchten, können Sie eine erweiterte ActivityMethode erstellen und diese Methode einfügen. Alle anderen Aktivitäten in Ihrer Anwendung können diese Aktivität erweitern und setupUI()in der onCreate()Methode aufrufen .

Ich hoffe es hilft.

Wenn Sie mehr als eine Aktivität verwenden, definieren Sie die allgemeine ID für das übergeordnete Layout wie <RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>

Erweitern Sie dann eine Klasse aus Activityund definieren Sie setupUI(findViewById(R.id.main_parent))Innerhalb ihrer OnResume()und erweitern Sie diese Klasse anstelle von `` Activityin your program


Hier ist eine Kotlin-Version der obigen Funktion:

@file:JvmName("KeyboardUtils")

fun Activity.hideSoftKeyboard() {
    currentFocus?.let {
        val inputMethodManager = ContextCompat.getSystemService(this, InputMethodManager::class.java)!!
        inputMethodManager.hideSoftInputFromWindow(it.windowToken, 0)
    }
}
Navneeth G.
quelle
Ich habe mich nicht selbst getestet, aber es sieht so aus, als würde es funktionieren. Da es hohe Bewertungen hat, werde ich die akzeptierte Antwort darauf ändern.
Htafoya
4
Sollte nicht sehr schwer sein? Ich habe gerade keine Android-Programmierung mehr. Korrigieren Sie mich, wenn ich falsch liege. Sie könnten den fokussierten EditText jederzeit irgendwie verfolgen und ihn einfach auffordern, während eines OnTouchEvent seinen Fokus zu verlieren?
Navneeth G
25
Ich bin nicht sicher, ob jemand anderes auf dieses Problem gestoßen ist, aber dies führt zum Absturz der App, wenn Sie hideSoftKeyboard aufrufen, wenn nichts fokussiert ist. Sie können dies lösen, indem Sie die zweite Zeile der Methode mitif(activity.getCurrentFocus() != null) {...}
Frank Cangialosi
14
Das Problem bei diesem Ansatz besteht darin, dass davon ausgegangen wird, dass alle anderen Ansichten niemals eine OnTouchListenerfür sie festlegen müssen. Sie können diese Logik einfach in einer Stammansicht festlegen ViewGroup.onInterceptTouchEvent(MotionEvent).
Alex.F
2
Funktioniert nicht, wenn ich auf andere Steuerelemente
klicke
285

Sie können dies erreichen, indem Sie die folgenden Schritte ausführen:

  1. Machen Sie die übergeordnete Ansicht (Inhaltsansicht Ihrer Aktivität) anklickbar und fokussierbar, indem Sie die folgenden Attribute hinzufügen

        android:clickable="true" 
        android:focusableInTouchMode="true" 
  2. Implementieren Sie eine hideKeyboard () -Methode

        public void hideKeyboard(View view) {
            InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
  3. Zuletzt legen Sie den onFocusChangeListener Ihres Edittextes fest.

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

Wie in einem der folgenden Kommentare ausgeführt, funktioniert dies möglicherweise nicht, wenn die übergeordnete Ansicht eine ScrollView ist. In diesem Fall kann der anklickbare und fokussierbare InTouchMode in der Ansicht direkt unter der ScrollView hinzugefügt werden.

vida
quelle
67
Meiner Meinung nach ist dies die richtige Antwort. Weniger Code, keine unnötigen Iterationen ...
Gattshjoty
14
Ich mag diese Antwort sehr. Eine Sache zu beachten ist, dass dies bei mir beim Hinzufügen clickableund focusableInTouchModezu meinem Stammelement nicht funktioniert hat ScrollView. Ich musste dem direkten Elternteil von mir hinzufügen, EditTextwelches ein war LinearLayout.
Adam Johns
10
Hat perfekt für mich funktioniert. Wenn Sie jedoch über zwei Edittext-Widgets verfügen, müssen Sie sicherstellen, dass Sie mit dem Fokus auf beide korrekt umgehen, da sonst die Tastatur unnötig umgeschaltet wird.
Marka A
1
@MarkaA Ich hatte keine Probleme damit. Wenn ich auf den anderen EditText klicke, bleibt die Tastatur erhalten. Wenn Sie auf den Hintergrund klicken, wird sie so ausgeblendet, wie sie sollte. Ich hatte eine andere Behandlung bei onFocusChange, nur den Hintergrund des EditText zu ändern, wenn er Fokus hat, nichts Fency.
CularBytes
3
@ Shrikant - Ich sah auch Flimmern mit mehreren Bearbeitungstexten. Ich habe einfach den onFocusChangeListener auf dem übergeordneten Element anstatt auf jedem Bearbeitungstext festgelegt und die Bedingung geändert, um zu sagen, ob (hasFocus) {hideKeyboard (v); } Ich habe kein Flackern mehr bemerkt, wenn ich zwischen den Bearbeitungstexten gewechselt habe.
Manisha
69

Überschreiben Sie einfach den folgenden Code in Aktivität

 @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);
}
sumit sonawane
quelle
4
Einfache Lösung, Aktivität hinzufügen und es wird sich auch um Fragmente kümmern
Rohit Maurya
1
Eine andere Lösung besteht darin, BaseActivity zu erstellen und in allen Aktivitäten zu erweitern
sumit sonawane
1
Geniale Lösung
Ahmed Adel Ismail
1
Sie haben mich davor bewahrt, meinen Bildschirm beim Schließen der Tastatur auszuschalten. Daumen hoch!
Dimas Mendes
1
Schön, aber es war zu schön, um wahr zu sein: einfach, sehr kurz, und es hat funktioniert ... leider gibt es ein Problem: Wenn die Tastatur angezeigt wird, geht sie jedes Mal, wenn wir den EditText berühren, der die Tastatur gefragt hat, runter und automatisch auf.
Chrysotribax
60

Ich finde die akzeptierte Antwort etwas kompliziert.

Hier ist meine Lösung. Fügen Sie OnTouchListenerIhrem Hauptlayout ein hinzu, dh:

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

und fügen Sie den folgenden Code in die onTouch-Methode ein.

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

Auf diese Weise müssen Sie nicht alle Ansichten durchlaufen.

Roepit
quelle
@roepit - Ich bekomme eine classCastexception für den Versuch, ein Layout in eine Ansicht umzuwandeln. vermisse ich etwas
Katzenhut
Können Sie Ihren Code irgendwo referenzieren? Ich kann nicht sagen, was falsch ist, wenn ich Ihr Layout und Ihren Aktivitäts- / Fragment- usw. Code nicht sehen kann.
Roepit
Die beste Antwort da draußen, ich versuche immer noch, meinen Kopf darum zu wickeln, wie es funktioniert.
user40797
Funktioniert dies, wenn Sie auf die Titelleiste der App klicken?
user1506104
1
Dies funktioniert perfekt zum Verstecken der Tastatur! Beachten Sie, dass dadurch der EditText nicht wirklich unscharf wird, sondern nur die Tastatur ausgeblendet wird. Um den EditText auch zu deaktivieren, fügen Sie z. B. android:onClick="stealFocusFromEditTexts"der XML- Datei der übergeordneten Ansicht und dann public void stealFocusFromEditTexts(View view) {}ihrer Aktivität hinzu. Die On-Click-Methode muss nichts tun, sie muss nur vorhanden sein, damit die übergeordnete Ansicht fokussierbar / auswählbar ist. Dies ist erforderlich, um dem Kind den Fokus zu stehlen. EditText
Jacob R
40

Ich habe noch eine Lösung, um die Tastatur zu verstecken:

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

Hier HIDE_IMPLICIT_ONLYan der Position von showFlagund 0an der Position von passieren hiddenFlag. Dadurch wird die Softtastatur gewaltsam geschlossen.

Saurabh Pareek
quelle
3
Danke, es ist Arbeit ..... vor allem hatte ich es versucht, aber es funktioniert nicht, während ich Wert aus dem Dialogfeld Editext-Text und dem Schließen des Dialogfelds erhalte ...
PankajAndroid
Danke, das funktioniert nur und es ist viel sauberer als das andere oben! +1
Edmond Tamas
Es funktioniert wie erwartet, danke für Ihre Lösung +1
Tryp
Funktioniert wie ein Zauber für mich. +1 für elegante Lösung.
Saintjab
2
Entschuldigung, aber diese Methode ist umschaltbar. Wenn der Tastaturstatus bereits geschlossen ist, wird die Tastatur
angezeigt
16

Nun, ich schaffe es, das Problem etwas zu lösen. Ich habe das dispatchTouchEvent bei meiner Aktivität überschrieben. Dort verwende ich Folgendes, um die Tastatur auszublenden.

 /**
 * 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);
}

BEARBEITEN : Die Methode getFields () ist nur eine Methode, die ein Array mit den Textfeldern in der Ansicht zurückgibt. Um zu vermeiden, dass dieses Array bei jeder Berührung erstellt wird, habe ich ein statisches Array namens sFields erstellt, das bei der Methode getFields () zurückgegeben wird. Dieses Array wird mit den onStart () -Methoden initialisiert, z.

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


Es ist nicht perfekt. Die Zeit für das Drag-Ereignis basiert nur auf Heuristiken, sodass sie manchmal nicht ausgeblendet wird, wenn lange Clics ausgeführt werden. Außerdem habe ich eine Methode erstellt, um alle editTexts pro Ansicht abzurufen. Andernfalls wird die Tastatur beim Klicken auf einen anderen EditText ausgeblendet und angezeigt.

Trotzdem sind sauberere und kürzere Lösungen willkommen

htafoya
quelle
8
Würden Sie den Code in Ihrer Antwort so bearbeiten, dass er Ihre getFields()Methode enthält, um anderen in Zukunft zu helfen ? Es muss nicht genau sein, nur ein Beispiel mit vielleicht nur einigen Kommentaren, die darauf hinweisen, dass es ein Array von EditTextObjekten zurückgibt .
Squonk
14

Verwenden Sie OnFocusChangeListener .

Zum Beispiel:

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

Update : Sie können auch onTouchEvent()Ihre Aktivität überschreiben und die Koordinaten der Berührung überprüfen. Wenn sich die Koordinaten außerhalb von EditText befinden, blenden Sie die Tastatur aus.

Sergey Glotov
quelle
9
Das Problem ist, dass der Edittext nicht den Fokus verliert, wenn ich auf ein Etikett oder andere Ansichten klicke, die nicht fokussierbar sind.
Htafoya
In diesem Fall habe ich noch eine Lösung. Ich habe die Antwort aktualisiert.
Sergey Glotov
2
onTouchEvent hat zu oft angerufen, daher ist dies auch keine gute Praxis
Jesus Dimrix
13

Ich habe dispatchTouchEvent in Activity implementiert, um dies zu tun:

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);
}

und ich habe es getestet, funktioniert perfekt!

Jishi Chen
quelle
funktioniert, aber das Problem dabei ist, dass wenn wir mehr als einen EditText haben, wir das auch berücksichtigen müssen, aber ich mochte Ihre Antwort :-)
Lalit Poptani
getActionMasked (ev) ist veraltet. Verwenden Sie jetzt: final int action = ev.getActionMasked (); für die erste Zeile.
Andrew
12

Eine mehr Kotlin & Material Design- Methode mit TextInputEditText (dieser Ansatz ist auch kompatibel mit EditTextView ) ...

1.Machen Sie die übergeordnete Ansicht (Inhaltsansicht Ihrer Aktivität / Ihres Fragments) anklickbar und fokussierbar, indem Sie die folgenden Attribute hinzufügen

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

2.Erstellen Sie eine Erweiterung für alle Ansichten (z. B. in einer ViewExtension.kt-Datei):

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

3.Erstellen Sie einen BaseTextInputEditText, der von TextInputEditText erbt. Implementieren Sie die Methode onFocusChanged, um die Tastatur auszublenden, wenn die Ansicht nicht fokussiert ist:

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. Rufen Sie einfach Ihre brandneue benutzerdefinierte Ansicht in Ihrem XML auf:

<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> 

Das ist alles. Sie müssen Ihre Controller (Fragment oder Aktivität) nicht ändern , um diesen sich wiederholenden Fall zu behandeln.

Phil
quelle
Ja gut, aber ich wünschte, es gäbe einen einfacheren Weg!
DevDeejay
11

Überschreiben Sie das öffentliche boolesche dispatchTouchEvent (MotionEvent-Ereignis) in einer beliebigen Aktivität (oder erweitern Sie die Aktivitätsklasse).

@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;
}

Und das ist alles was Sie tun müssen

Hoang Trinh
quelle
Dies war der einfachste Weg, den ich gefunden habe, um es zum Laufen zu bringen. Arbeiten mit mehreren EditTexts und einer Scrollview
RJH
Getestet mit mehreren EditTexts; Es klappt! Der einzige Nachteil ist, dass beim Ziehen auch eine Drag-Bewegung ausgeblendet wird.
RominaV
9

Ich habe die Lösung von Andre Luis IM modifiziert. Ich habe diese erreicht:

Ich habe eine Dienstprogrammmethode erstellt, um die Softtastatur genauso zu verbergen wie Andre Luiz IM:

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

Aber anstatt für jede Ansicht einen OnTouchListener zu registrieren, der eine schlechte Leistung bietet, habe ich den OnTouchListener nur für die Stammansicht registriert. Da das Ereignis sprudelt, bis es verbraucht ist (EditText ist eine der Ansichten, die es standardmäßig verbrauchen), liegt es daran, dass es nicht verbraucht wurde, wenn es in der Stammansicht ankommt. Deshalb schließe ich die Softtastatur.

findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Utils.hideSoftKeyboard(activity);
        return false;
    }
});
Fernando Camargo
quelle
1
Das scheint mir sicherer zu sein.
Superarts.org
9

Ich bin mir bewusst, dass dieser Thread ziemlich alt ist, die richtige Antwort gültig zu sein scheint und es viele funktionierende Lösungen gibt, aber ich denke, dass der unten angegebene Ansatz einen zusätzlichen Vorteil in Bezug auf Effizienz und Eleganz haben könnte.

Ich benötige dieses Verhalten für alle meine Aktivitäten, daher habe ich eine Klasse CustomActivity erstellt, die von der Klasse Activity erbt, und die Funktion dispatchTouchEvent "verknüpft" . Es sind hauptsächlich zwei Bedingungen zu beachten:

  1. Wenn der Fokus unverändert bleibt und jemand außerhalb des aktuellen Eingabefelds tippt, schließen Sie den IME
  2. Wenn sich der Fokus geändert hat und das nächste fokussierte Element keine Instanz eines Eingabefelds ist, schließen Sie den IME

Das ist mein Ergebnis:

@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);
}

Randnotiz: Zusätzlich ordne ich diese Attribute der Stammansicht zu, um den Fokus auf jedes Eingabefeld zu löschen und zu verhindern, dass Eingabefelder beim Aktivitätsstart den Fokus erhalten (wodurch die Inhaltsansicht zum "Fokusfänger" wird):

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

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

    view.setFocusable(true);
    view.setFocusableInTouchMode(true);
}
fje
quelle
Super es funktioniert gut danke !! Ich habe eine Gegenstimme für Ihre Antwort abgegeben.
Vijay
2
Ich denke, das ist die beste Lösung für komplexe Layouts. Bisher habe ich jedoch zwei Nachteile festgestellt: 1. Das EditText-Kontextmenü ist nicht anklickbar. Jeder Klick darauf führt dazu, dass der Fokus von EditText verloren geht. 2. Wenn sich unser EditText am unteren Rand einer Ansicht befindet und wir lange darauf klicken (um ein Wort auszuwählen), dann danach Tastatur gezeigt, unser "Klickpunkt" ist auf der Tastatur, nicht auf EditText - so verlieren wir wieder den Fokus: /
sosite
@sosite, ich glaube, ich habe diese Einschränkungen in meiner Antwort angesprochen. Schau mal.
Andy Dennie
6

Ich mochte den Ansatz dispatchTouchEventvon htafoya, anzurufen, aber:

  • Ich habe den Timer-Teil nicht verstanden (weiß nicht, warum die Messung der Ausfallzeit notwendig sein sollte?)
  • Ich möchte nicht bei jeder Ansichtsänderung alle EditTexts registrieren / die Registrierung aufheben (kann in komplexen Hierarchien eine ganze Reihe von Ansichtsänderungen und Edittexten sein).

Also habe ich diese etwas einfachere Lösung gemacht:

@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());
}

Es gibt einen Nachteil:

Wenn Sie von einer EditTextzur anderen EditTextwechseln, wird die Tastatur ausgeblendet und erneut angezeigt. In meinem Fall ist dies erwünscht, da angezeigt wird, dass Sie zwischen zwei Eingabekomponenten gewechselt haben.

Christian R.
quelle
Diese Methode hat am besten funktioniert, da ich nur Plug-and-Play mit meiner FragmentActivity durchführen konnte.
BillyRayCyrus
Danke, es ist der beste Weg! Ich habe gerade auch die Überprüfung auf Ereignisaktion hinzugefügt: int action = ev.getActionMasked (); if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) {...}
sergey.n
Vielen Dank ! Du hast mir Zeit gespart. Beste Antwort.
I.d007
6

Bitte: Ich erkenne, dass ich keine Schlagkraft habe, aber bitte nehmen Sie meine Antwort ernst.

Problem: Schließen Sie die Softtastatur, wenn Sie von der Tastatur wegklicken oder Text mit minimalem Code bearbeiten.

Lösung: Externe Bibliothek namens Butterknife.

Einzeilige Lösung:

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

Lesbarere Lösung:

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

Erläuterung: Binden Sie OnClick Listener an die übergeordnete XML-Layout-ID der Aktivität, damit bei jedem Klick auf das Layout (nicht auf den Bearbeitungstext oder die Tastatur) der Codeausschnitt ausgeführt wird, der die Tastatur verbirgt.

Beispiel: Wenn Ihre Layoutdatei R.layout.my_layout und Ihre Layout-ID R.id.my_layout_id lautet, sollte Ihr Butterknife-Bindungsaufruf folgendermaßen aussehen:

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

Link zur Butterknife-Dokumentation: http://jakewharton.github.io/butterknife/

Plug: Butterknife wird Ihre Android-Entwicklung revolutionieren. Denke darüber nach.

Hinweis: Das gleiche Ergebnis kann ohne die Verwendung einer externen Bibliothek Butterknife erzielt werden. Stellen Sie einfach einen OnClickListener wie oben beschrieben auf das übergeordnete Layout ein.

Charles Woodson
quelle
Tolle, perfekte Lösung! Vielen Dank.
nullforlife
6

In Kotlin können wir Folgendes tun. Es ist nicht erforderlich, alle Ansichten zu wiederholen. Es wird auch für Fragmente funktionieren.

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)
}
Sai
quelle
funktioniert nicht aus Fragment
Nurseyit Tursunkulov
Das funktioniert, aber es hat einen Fehler. Wenn ich beispielsweise Text in die Textansicht einfügen möchte, wird die Tastatur ausgeblendet und dann angezeigt. Es ist ein bisschen nervig.
George Shalvashvili
Also sag mir die beste Lösung ..
Sai
4

Hier ist eine weitere Variation der Antwort von fje, die sich mit den von sosite aufgeworfenen Fragen befasst.

Die Idee hier ist, sowohl die Abwärts- als auch die Aufwärtsaktionen in der Aktivitätsmethode zu behandeln dispatchTouchEvent. Bei der Abwärtsaktion notieren wir uns die aktuell fokussierte Ansicht (falls vorhanden) und ob sich die Berührung darin befand, und speichern beide Informationen für später.

Bei der Aufwärtsaktion versenden wir zuerst, damit eine andere Ansicht möglicherweise den Fokus erhält. Wenn danach die aktuell fokussierte Ansicht die ursprünglich fokussierte Ansicht ist und sich die Abwärtsberührung in dieser Ansicht befand, lassen wir die Tastatur offen.

Wenn sich die aktuell fokussierte Ansicht von der ursprünglich fokussierten Ansicht unterscheidet und eine ist EditText, lassen wir auch die Tastatur offen.

Ansonsten schließen wir es.

Zusammenfassend funktioniert dies also wie folgt:

  • beim Berühren in einem aktuell fokussierten EditText bleibt die Tastatur geöffnet
  • beim Übergang von einem fokussierten EditTextzu einem anderenEditText bleibt die Tastatur geöffnet (schließt / öffnet nicht)
  • Wenn Sie irgendwo außerhalb eines aktuell fokussierten Objekts berühren EditText, das kein anderes istEditText , die , wird die Tastatur geschlossen
  • Wenn Sie lange auf eine EditTextTaste drücken , um die Kontextaktionsleiste aufzurufen (mit den Schaltflächen Ausschneiden / Kopieren / Einfügen), bleibt die Tastatur geöffnet, obwohl die UP-Aktion außerhalb des Fokus ausgeführt wurde EditText(der nach unten verschoben wurde, um Platz für das CAB zu schaffen). . Beachten Sie jedoch, dass beim Tippen auf eine Schaltfläche im CAB die Tastatur geschlossen wird. Das kann wünschenswert sein oder nicht; Wenn Sie aus einem Feld ausschneiden / kopieren und in ein anderes einfügen möchten, ist dies der Fall. Wenn Sie wieder in dasselbe einfügen möchten EditText, wäre dies nicht der Fall.
  • Wenn sich der Fokus EditTextam unteren Bildschirmrand befindet und Sie lange auf einen Text klicken, um ihn auszuwählen, EditTextbleibt der Fokus erhalten, und daher wird die Tastatur wie gewünscht geöffnet, da bei der Abwärtsaktion die Option "Berühren ist innerhalb der Sichtgrenzen" ausgeführt wird , nicht die Up-Aktion.

    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);
    }
Andy Dennie
quelle
4

Es ist zu einfach. Machen Sie Ihr aktuelles Layout durch diesen Code anklickbar und fokussierbar:

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

Schreiben Sie dann eine Methode und einen OnClickListner für dieses Layout, sodass beim Berühren des obersten Layouts eine Methode aufgerufen wird, in die Sie Code schreiben, um die Tastatur zu schließen. Das Folgende ist der Code für beide; // du musst dies in OnCreate () schreiben

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

vom Listener aufgerufene Methode: -

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

Ich finde das akzeptierte Antwortbit komplex für diese einfache Anforderung. Hier ist, was für mich ohne Probleme funktioniert hat.

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;
        }
    });
Joohay
quelle
1
Wenn Sie NestedScrollViewkomplexe Layouts verwenden, lesen Sie die akzeptierte Antwort: stackoverflow.com/a/11656129/2914140 . Sie sollten wissen, dass andere Behälter Berührungen verbrauchen können.
CoolMind
3

Es gibt einen einfacheren Ansatz, der auf dem gleichen Problem des iPhone basiert. Überschreiben Sie einfach das Layout des Hintergrunds bei einem Berührungsereignis, in dem der Bearbeitungstext enthalten ist. Verwenden Sie diesen Code einfach in OnCreate der Aktivität (login_fondo ist das Root-Layout):

    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;
                }
            });
Alex RR
quelle
1
Wie gesagt und ich erinnere mich, funktioniert dies nur, wenn sich das Formular nicht in einer ScrollView befindet.
Htafoya
1
Dies funktioniert nicht sehr gut, wenn das Hintergrundlayout andere untergeordnete Layouts enthält.
AxeEffect
Vielen Dank, dass Sie daran erinnert haben, dass onClick nicht die einzige Option war.
Harpreet
3

Methode zum Ein- / Ausblenden der Softtastatur

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);    
        }

    }

Ich hoffe, sie waren nützlich

lalosoft
quelle
3

Dies ist die einfachste Lösung für mich (und von mir ausgearbeitet).

Dies ist die Methode zum Ausblenden der Tastatur.

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

Setzen Sie nun das onclick-Attribut des übergeordneten Layouts der Aktivität hideKeyboardentweder in der Entwurfsansicht Ihrer XML-Datei auf die obige Methode oder schreiben Sie den folgenden Code in die Textansicht Ihrer XML-Datei.

android:onClick="hideKeyboard"
NullByte08
quelle
2

Ich habe die Methode verfeinert und den folgenden Code in eine UI-Dienstprogrammklasse eingefügt (vorzugsweise nicht unbedingt), damit von allen Aktivitäts- oder Fragmentklassen auf sie zugegriffen werden kann, um ihren Zweck zu erfüllen.

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);
}

Sagen Sie dann zum Beispiel, Sie müssen es aus der Aktivität heraus aufrufen, rufen Sie es wie folgt auf;

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

Beachten

findViewById (android.R.id.content)

Dies gibt uns die Stammansicht der aktuellen Gruppe (Sie müssen die ID nicht in der Stammansicht festgelegt haben).

Prost :)

Uzair
quelle
2

Aktivität

 @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);
 }
Eisbügel
quelle
3
Dieser Code ist einfach, hat aber ein offensichtliches Problem: Er schließt die Tastatur, wenn eine Stelle berührt wird. Wenn Sie also auf eine andere Position des EditText tippen, um den Eingabecursor zu bewegen, wird die Tastatur ausgeblendet und die Tastatur wird vom System erneut angezeigt.
Verdammtes Gemüse
2

Fügen Sie diesen Code einfach in die Klasse @Overide ein

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);
}
Haseeb Javed
quelle
3
Während dies die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort und möglicherweise das Problem mit dem OP-Code zu erklären.
Pirho
yes @pirho Ich stimme dir auch zu. Haseeb muss sich darauf konzentrieren, die richtige Antwort zu geben.
Dilip
2
@ Dilip Wussten Sie, dass Sie auch Kommentare, denen Sie zustimmen, positiv bewerten können? Dies dient nur dazu, den Kommentarbereich sauber zu halten, damit nicht viele Kommentare tatsächlich denselben Punkt haben.
Pirho
2

Anstatt alle Ansichten zu durchlaufen oder dispatchTouchEvent zu überschreiben.

Warum nicht einfach die onUserInteraction () der Aktivität überschreiben, um sicherzustellen, dass die Tastatur geschlossen wird, wenn der Benutzer außerhalb von EditText tippt.

Funktioniert auch, wenn sich EditText in der scrollView befindet.

@Override
public void onUserInteraction() {
    if (getCurrentFocus() != null) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
    }
}
SKG
quelle
Dies ist die bessere Antwort
ovluca
Ja! Das ist eine super saubere Antwort. Wenn Sie eine AbstractActivity erstellen, die alle Ihre anderen Aktivitäten erweitern, können Sie diese als Standardverhalten in Ihrer App einbinden.
wildcat12
1

Ich habe dies mit einer kleinen Variante der Lösung von Fernando Camarago zum Laufen gebracht. In meiner onCreate-Methode hänge ich einen einzelnen onTouchListener an die Stammansicht an, sende jedoch die Ansicht und nicht die Aktivität als Argument.

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

In einer separaten Utils-Klasse ist ...

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

Das mag alt sein, aber ich habe es geschafft, indem ich eine benutzerdefinierte Klasse implementiert habe

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);
}

Die beste Vorgehensweise besteht darin, eine Helper-Klasse zu erstellen, und jeder Container mit relativen / linearen Layouts sollte dies implementieren.

**** Beachten Sie, dass nur der Hauptcontainer diese Klasse implementieren sollte (zur Optimierung) ****

und implementieren Sie es so:

Parent.setOnClickListener( new DismissKeyboardListener(this) ); 

Das Schlüsselwort ist dies für Aktivität. Wenn Sie sich also in einem Fragment befinden, verwenden Sie getActivity ().

--- Daumen hoch, wenn es dir hilft ... --- Prost Ralph ---

ralphgabb
quelle
1

Dies ist eine leicht modifizierte Version von fjes Antwort, die größtenteils perfekt funktioniert hat.

Diese Version verwendet ACTION_DOWN, sodass beim Ausführen einer Bildlaufaktion auch die Tastatur geschlossen wird. Das Ereignis wird auch nicht weitergegeben, es sei denn, Sie klicken auf einen anderen EditText. Dies bedeutet, dass durch Klicken auf eine beliebige Stelle außerhalb Ihres EditText, auch auf eine andere anklickbare, die Tastatur einfach geschlossen wird.

@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);
}
Cadmonkey33
quelle
Hier sieht etwas nicht richtig aus; Sie weisen beide viewund viewTmpzu getCurrentFocus(), sodass sie immer den gleichen Wert haben.
Andy Dennie
1

Ich habe so gemacht:

@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);
}

Tastaturcode ausblenden :

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

Erledigt

Hiren Patel
quelle