ActionBar SearchView auf der Softtastatur automatisch schließen

79

Ich verwende derzeit einen ActionBar-Menüpunkt, um eine Suchansicht in der Aktionsleiste anzuzeigen. Wenn der Suchmenüpunkt erweitert wird, wird die Softtastatur angezeigt, die ich möchte. Wenn der Benutzer jetzt die Zurück-Taste drückt, um die Softtastatur zu schließen, möchte ich auch die Suchansicht in der Aktionsleiste reduzieren.

Ich habe versucht, die folgenden Listener OnKeyListener und OnFocusChangeListener auf dem MenuItem und der ActionView zu implementieren. Ich habe auch versucht, OnBackPressed () in der Aktivität zu verwenden. Keiner der oben genannten Punkte erkennt, wann die Zurück-Taste zum Schließen der Softtastatur verwendet wird.

Irgendwelche Ideen?

Ich habe OnActionExpandListener implementiert, um zu wissen, wann die Suchansicht sichtbar ist.

user1258568
quelle
Hier ist eine sehr beliebte Antwort stackoverflow.com/questions/1109022/…
jmishra
2
es wird ihm nicht helfen, er muss die Zurück-Taste von der Tastatur
abfangen
@acrespo Welche Antwort? Sie kommentieren eine Frage ...
Der unglaubliche

Antworten:

100

Ich werde die Antwort von @ user1258568 für die Faulen erweitern. Das hat bei mir funktioniert. Beachten Sie, dass Ihre Abfrage gelöscht wird, wenn der Fokus verloren geht.

final MenuItem searchMenuItem = optionsMenu.findItem(R.id.search);
final SearchView searchView = (SearchView) searchMenuItem.getActionView();

searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View view, boolean queryTextFocused) {
        if(!queryTextFocused) {
            searchMenuItem.collapseActionView();
            searchView.setQuery("", false);
        }
    }
});
Jon Willis
quelle
1
Funktioniert perfekt. Wenn Sie eine Suchansicht in den Code einfügen, müssen Sie diese möglicherweise menu.getItem(yourSearchViewItemPosition)stattdessen verwenden.
GeeF
@AlexBonel Wie so? Ich weiß, dass der S3 und der S4 idiotische Hardwaretasten haben, aber ich bin mir nicht sicher, wie sich das auf dieses Snippet auswirken würde. Möglicherweise liegt es daran, dass das ActionBar-Menü ausgeblendet ist und searchMenuItem anders funktioniert. Ich habe einen S4 zur Hand, ich muss das testen.
Jon Willis
@ JonWillis Wenn es für Sie nicht schwierig ist, können Sie bitte Ihre Erfahrungen mit einem solchen Verhalten auf S4 teilen?
Alex Bonel
4
Schön, nach stundenlangen Recherchen und Implementierungen, um dies zu versuchen, habe ich Ihre Antwort gefunden :) ... Als erstes dachte ich, ich würde einen Fokus-Listener verwenden, aber ich habe setOnFocusChangeListener()stattdessen verwendet setOnQueryTextFocusChangeListener(). Mit Ihrer Methode funktioniert alles gut. Vielen Dank.
Ionut Negru
2
@IonutNegru Gern geschehen! Ich muss das Android SDK manchmal lieben. Ich möchte, dass sie es auf eine vernünftige, moderne Art und Weise umschreiben und die Unterstützung für das Erbe einstellen, aber das wird niemals passieren.
Jon Willis
37

Ich habe eine bessere Lösung gefunden.

searchView.setOnQueryTextFocusChangeListener(). 

Das OnQueryTextFocusChangeListenerwird aufgerufen, wenn die Tastatur angezeigt oder ausgeblendet wird. Wird zuerst aufgerufen, wenn die Tastatur angezeigt wird und die Suchansicht den Fokus hat. keyboardWird erneut aufgerufen, wenn es ausgeblendet ist und die Suchansicht den Fokus verliert, kann close search viewdann verwendet werden

menuItem.collapseActionView().
user1258568
quelle
5
Das ist irreführend. Das OnQueryTextFocusChangeListenerwird NICHT aufgerufen, wenn die Tastatur angezeigt oder ausgeblendet wird. Es wird nur aufgerufen, wenn das searchViewscharfgestellt wird und / oder unscharf wird. Wenn also das SearchViewzum ersten Mal OnQueryTextFocusChangeListenerscharfgestellt ist , wird das aufgerufen und auch die Tastatur angezeigt. Wenn nun die Zurück-Taste gedrückt wird, wird die Tastatur ausgeblendet, OnQueryTextFocusChangeListeneraber nicht aufgerufen. Wenn Sie die Zurück-Taste ein zweites Mal drücken, wird das searchViewFenster ausgeblendet und OnQueryTextFocusChangeListeneraufgerufen.
Faizal
11

OnBackPressed einfach so überschreiben:

@Override
    public void onBackPressed() {
        if (searchView.isShown()){
            searchView.onActionViewCollapsed();  //collapse your ActionView
            searchView.setQuery("",false);       //clears your query without submit
            isClosed = true;                     //needed to handle closed by back
        } else{
            super.onBackPressed();
        }
    }

und Ihr onCreateOptionsMenu würde die mSearchView folgendermaßen aufblasen:

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.menu_search, menu);
        mSearchView = (SearchView) menu.findItem(R.id.menu_action_search).getActionView();
        mSearchView.setOnQueryTextListener(this);
        mSearchView.setOnSearchClickListener(this);
        mSearchView.setOnCloseListener(this);
        isClosed = true;
        return true;
    }

Lassen Sie Ihre Klasse Folgendes wie folgt implementieren:

public class myActivity extends FragmentActivity implements
    SearchView.OnQueryTextListener, View.OnClickListener, SearchView.OnCloseListener {

was du auch brauchst:

@Override
public void onClick(View view) {
    isClosed = false;
}

@Override
public boolean onClose() {
    isClosed = true;
    return false;
}

Sie müssen "mSearchView" und "isClosed" beide globalen Variablen für die Aktivität festlegen.

Codeversiert
quelle
3
Ich denke nicht, dass das funktioniert; Nach meiner Erfahrung wird die onBackPressed-Methode nicht aufgerufen, wenn die Tastatur aktiv ist. Die Tastatur wird einfach geschlossen, und Sie müssen erneut drücken, damit diese Methode aufgerufen wird. Dies ist auf 2.3; Ich habe nicht mit 3.x und 4.0 experimentiert, aber ich vermute, dass dies auch dort so ist.
Kevlar
@ Kevin Ich denke, Sie können richtig sein. Ich werde das noch einmal testen und sicherstellen, dass es keinen Weg gibt. Meine Lösung scheint etwas anders zu sein als das, was sie wollen. Soweit ich weiß, gibt es meines Erachtens keine Möglichkeit, mit dem Rücken umzugehen, während die Softtastatur angezeigt wird. Meine Lösung funktioniert sicher, nachdem die Tastatur sicher geschlossen wurde. Wird auf verschiedenen SDKs getestet.
Codeversed
1
Ich hatte versucht, die Suche zu reduzieren mit: searchMenuItem.collapseActionView (); Es stellte sich jedoch heraus, dass searchView.onActionViewCollapsed (); hat den Trick für mich gemacht - danke!
Bkurzius
Ich denke nicht, dass Sie direkt ... Funktionen aufrufen sollten. Diese Funktionen können nicht direkt aus Ihrem Code aufgerufen werden ...
user457015
Wie benutzt man CollapseActionView () auf API Level 11.
Madan V
3

Die Antwort von Jon Willis funktioniert großartig. Dies ist eine Verbesserung seiner Antwort.

Erstellen Sie zunächst eine neue Klasse, die Folgendes implementiert View.OnFocusChangeListener:

public class SearchViewFocusListener implements View.OnFocusChangeListener {

    private final MenuItem mMenuItem;

    public SearchViewFocusListener(MenuItem menuItem) {
        mMenuItem = menuItem;
    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (!hasFocus) {
            mMenuItem.collapseActionView();
            if (v instanceof SearchView) {
                ((SearchView) v).setQuery("", false);
            }
        }
    }

}

Stellen Sie als Nächstes den Listener auf Folgendes ein SearchView:

searchView.setOnQueryTextFocusChangeListener(new SearchViewFocusListener(menuItem));
Jared Rummler
quelle
funktioniert gut, aber wie lösche ich den Fokus über das Suchsymbol? Der FocusChangeListener erfasst ein Drücken der Zurück-Taste auf einem Gerät. Dadurch wird die Softtastatur geschlossen und die Suchansicht geschlossen. Anschließend wird das Suchsymbol wie gewünscht angezeigt. Das Suchsymbol ist jedoch hervorgehoben (hat Fokus) und ich würde es vorziehen, wenn es keinen Fokus hat. Ich habe ein paar Wege versucht, um zu klären, aber ohne Glück. Irgendwelche Ideen?
AJW
2

Sie müssen nur das Attribut "destroyActionView" in das Menülayout einfügen

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_item_search"
        android:title="@string/search"
        android:iconifiedByDefault="true"
        android:icon="@drawable/ic_action_search" 
        app:actionViewClass="android.support.v7.widget.SearchView"
        app:showAsAction="ifRoom|collapseActionView"/> <--this one
</menu>

Dadurch erhalten Sie die Funktionalität, nach der Sie selbst suchen. Vergessen Sie nicht, die Methode "clearFocus" in der Suchansicht aufzurufen, um die Tastatur nach dem Senden der Abfrage zu schließen.

Rodrigo de Blas
quelle
1

Dies ist, was ich getan habe, um die Tastatur verschwinden zu lassen. Sie können versuchen zu sehen, ob dies für Sie funktioniert. Ich setze das searchViewauf unsichtbar und dann wieder auf sichtbar.

    //set query change listener
     searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
        @Override
        public boolean onQueryTextChange(String newText) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean onQueryTextSubmit(String query) {
            /**
             * hides and then unhides search tab to make sure keyboard disappears when query is submitted
             */
                  searchView.setVisibility(View.INVISIBLE);
                  searchView.setVisibility(View.VISIBLE);
            return false;
        }

     });
Parnit
quelle
Hat auch für mich funktioniert, aber Sie müssen getActivity () hinzufügen. SupportInvalidateOptionsMenu (); um
Aktionsleiste
1

Es ist so erreichbar:

   private void setupSearchView(Menu menu) {
        final MenuItem searchMenuItem = menu.findItem(R.id.action_search);
        final SearchView searchView = (SearchView) searchMenuItem.getActionView();

        [...]

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                searchMenuItem.collapseActionView();
                return false;
            }
            @Override
            public boolean onQueryTextChange(String newText) {
                return true;
            }
        });
    }

Lösungen, die auf setOnQueryTextFocusChangeListener () basieren, funktionierten bei mir nicht, weil das Ereignis nicht gestartet wurde. Die Suchansicht verlor beim Senden nicht den Fokus, wahrscheinlich weil ich die Suche in derselben Aktivität durchführe, die die Suchansicht enthält.

Ich denke jedenfalls, dass die Verwendung von OnQueryTextListener korrekter ist, da es das Ereignis der Textübermittlung genauer beschreibt.

GaRRaPeTa
quelle
0
@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getSupportMenuInflater().inflate(R.menu.home_screen, menu);

        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        final MenuItem searchMenuItem = menu.findItem(R.id.menu_search);
        final SearchView searchView = (SearchView) searchMenuItem
                .getActionView();
        searchView.setIconifiedByDefault(false);
        if (searchManager != null && searchView != null) {
            searchView.setSearchableInfo(searchManager
                    .getSearchableInfo(getComponentName()));

            searchView
                    .setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {

                        @Override
                        public void onFocusChange(View v, boolean hasFocus) {

                            if (!hasFocus) {
                                if (searchMenuItem != null) {
                                    searchMenuItem.collapseActionView();
                                }// end if
                                if (searchView != null) {
                                    searchView.setQuery("", false);

                                }// end if
                            }// end if

                        }
                    });

            searchView
                    .setOnQueryTextListener(new SearchView.OnQueryTextListener() {

                        @Override
                        public boolean onQueryTextSubmit(String query) {
                            /**
                             * hides and then unhides search tab to make sure
                             * keyboard disappears when query is submitted
                             */
                            if (searchView != null) {
                                searchView.setVisibility(View.INVISIBLE);
                                searchView.setVisibility(View.VISIBLE);

                            }
                            return false;
                        }

                        @Override
                        public boolean onQueryTextChange(String newText) {
                            // TODO Auto-generated method stub
                            return false;
                        }
                    });

        }

        return super.onCreateOptionsMenu(menu);
    }
Konfuzius
quelle
0

Wenn Sie die Tastatur reduzieren möchten, wenn der Benutzer auf das Suchsymbol auf der Tastatur klickt, kann dies einfach erreicht werden

inside onquerytextsubmitted {

searchView.clearfocus()

}

geniushkg
quelle
0

Sie müssen setIconified zweimal aufrufen.

Um Ihre Suchansicht tatsächlich zu reduzieren und die Tastatur zu schließen.
Beim ersten Anruf wird der Text der Suchansicht mit der zweiten Anruftastatur gelöscht und die Suchansicht geschlossen.

Nosaiba darwish
quelle
0

Aus irgendeinem Grund hat menuItem.collapseActionView()es nicht funktioniert, also habe ich searchView.setIconified(true)stattdessen verwendet.

Dies ergibt das folgende Ergebnis als Codebeispiel.

final MenuItem searchItem = (MenuItem) menu.findItem(R.id.menu_item_search);
final SearchView searchView = (SearchView) searchItem.getActionView();

searchView.setOnQueryTextFocusChangeListener(new SearchView.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (!hasFocus) {
            searchView.setIconified(true);
        }
    }
});
Bastien
quelle