2014-03-19 9 views
12

Ich habe einen zusammenklappbaren SearchView in meinem ActionBar. Nachdem eine Suche durchgeführt wurde, wird das zugehörige Objekt ListView gefiltert, sodass nur übereinstimmende Elemente angezeigt werden. Während dieses Status ist die SearchView noch erweitert und zeigt die Suchzeichenfolge. Wenn der Benutzer die SearchView schließt, entferne ich den Filter.Gibt es eine bessere Möglichkeit, den Status von SearchView wiederherzustellen?

Ich möchte den Suchstatus wiederherstellen, z. bei Konfigurationsänderung oder wenn die Aktivität zerstört wurde, wenn ich von einer anderen Aktivität zu ihr zurückkehre.

ich zur Wiederherstellung des Abfrage-String in onRestoreInstanceState(), und wenn ich einen Abfrage-String in onCreateOptionsMenu() finden nenne ich

searchView.setQuery(query, true); 

, um die Abfrage erneut auszuführen. Es stellte sich heraus, dass dies besser ist als die sofortige Anwendung des Abfragefilters onRestoreInstanceState(). Bei letzterem wird die Liste ungefiltert angezeigt, erst dann wird die Abfrage erneut angewendet. Mit setQuery() passiert das nicht.

Problem: Die Abfrage wird ausgeführt und die Liste wird gefiltert, aber die Suchansicht bleibt minimiert. Daher kann der Benutzer die Suchansicht nicht zum Entfernen des Filters oder zum Anwenden einer anderen Abfrage verwenden.

In onCreateOptionsMenu() kann ich sicher sein, dass das Suchelement und die Suchansicht existiert, daher kann ich aufrufen. Seltsamerweise erweitert nur dies wirklich die ActionView - Aufruf setIconified(false) erweitert nicht die Ansicht, nicht einmal wenn es zweimal hintereinander aufgerufen wird.

Wenn ich expandActionView() verwenden, bevor ich setQuery() nennen, die SearchView geöffnet und zeigt den Text (sonst expandActionView() leert den SearchView).

Leider hat expandActionView() einen Nebeneffekt: die Vorschlagsliste wird ebenfalls angezeigt und die Tastatur öffnet sich.

Ich kann die Tastatur mit searchView.clearFocus() verstecken. Das verbleibende Problem ist also die Vorschlagsliste. Wie kann ich eine geöffnete Vorschlagsliste auf einem SearchView schließen, der Text hat?

Ich frage mich, ob es eine bessere Möglichkeit gibt, eine Suchansicht in der Aktionsleiste wiederherzustellen, die nicht so viele Nebenwirkungen hat.

+0

siehe [dies] (http://stackoverflow.com/questions/15024892/two-searchviews-in-one-activity-and-screen-rotation) kann Ihnen helfen – user3355820

+0

Dieser Fall unterscheidet sich darin, dass die Suche Die Ansicht ist in onRestoreInstanceState verfügbar. In meinem Fall ist die Suchansicht in der Aktionsleiste und nicht in onRestoreInstanceState verfügbar. – dschulten

+0

Es scheint, dass expandActionView aus irgendeinem Grund bewirkt, dass die aktuelle Abfragezeichenfolge auf leer zurückgesetzt wird. Wenn ich zuerst die Aktionsansicht expandiere und dann setQuery aufruft, wird die Abfrage geöffnet und der Text angezeigt. Das verbleibende Problem besteht nun darin, dass die Vorschlagsliste angezeigt wird und die Tastatur geöffnet ist. – dschulten

Antwort

9

Ich habe einen Workaround gefunden. Es ist extrem hässlich, aber es funktioniert.

Also hier ist, wie ich den Suchfeldinstanzstatus nach einer Konfigurationsänderung wiederherstellen konnte.

Zunächst einmal, stellen Sie die Query-String in onRestoreInstanceState

currentQuery = state.getString(KEY_SAVED_FILTER_CONSTRAINT); 

In onCreateOptionsMenu die Suchansicht einrichten und wenn es eine currentQuery ist, erweitern Sie den Suchbegriff ein und senden Sie die erneut Abfrage. Löschen Sie den Fokus, um die Tastatur zu verbergen.

MenuItem searchItem = menu.findItem(R.id.action_search); 
    searchView = (SearchView) searchItem.getActionView(); 
    searchView.setSearchableInfo(searchManager 
      .getSearchableInfo(getComponentName())); 

    if (!TextUtils.isEmpty(currentQuery)) { 
     searchItem.expandActionView(); 
     searchView.setQuery(currentQuery, true); 
     searchView.clearFocus(); 
    } 

Schließlich müssen wir die Vorschlagsliste schließen.Hier ist, wie die Abfrage Textansicht von der Suchansicht erhalten:

private AutoCompleteTextView findQueryTextView(ViewGroup viewGroup) { 
    AutoCompleteTextView queryTextView = null; 
    if (viewGroup != null) { 
     int childCount = viewGroup.getChildCount(); 
     for (int i = 0; i < childCount; i++) { 
      View child = viewGroup.getChildAt(i); 
      if (child instanceof AutoCompleteTextView) { 
       queryTextView = (AutoCompleteTextView) child; 
       break; 
      } else if (child instanceof ViewGroup) { 
       queryTextView = findQueryTextView((ViewGroup) child); 
       if (queryTextView != null) { 
        break; 
       } 
      } 
     } 
    } 
    return queryTextView; 
} 

Dann können Sie die Vorschlagsliste entlassen:

AutoCompleteTextView queryTextView = findQueryTextView(searchView); 
    if (queryTextView != null) { 
     queryTextView.dismissDropDown(); 
    } 

Dies funktioniert jedoch nicht aus onCreateOptionsMenu. Ich musste den Aufruf von "discloseDropDown" in die onNewIntent-Methode meiner Aktivität verschieben, damit sie funktioniert.

Was dies so hässlich macht, ist die Tatsache, dass die Wiederherstellungsschritte über verschiedene Phasen des Lebenszyklus verteilt sind und dass eine rekursive Ansichtssuche notwendig ist, um zur Vorschlagsliste zu gelangen.

+0

Leider ist 'searchItem.expandActionView(); 'nicht vor API-Level 14 verfügbar. Es sieht so aus, als ob Sie mit der Unterstützung von SearchView ziemlich viel Pech haben. – kurtisnelson

+3

Nein, mit Unterstützung lib sollten Sie MenuItemCompat.expandActionView() verwenden. – WindRider

+1

Bestellung ist WICHTIG! \t \t \t item.expandActionView(); \t \t \t searchView.setQuery (_eventSearchQuery.query, true); –

6

In meiner bescheidenen Meinung. Wenn Sie den Status searchView wiederherstellen möchten, sollten Sie onSaveInstanceState(Bundle outState) verwenden. Wird aufgerufen, um den Status pro Instanz von einer Aktivität abzurufen, bevor er beendet wird, sodass der Status in onCreate (Bundle) oder wiederhergestellt werden kann (das von dieser Methode aufgefüllte Bundle wird an beide übergeben).

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    // if you saved something on outState you can recover them here 
    if (savedInstanceState != null) { 
      mSearchString = savedInstanceState.getString(SEARCH_KEY); 
    } 
} 

// This is called before the activity is destroyed 
@Override 
protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    mSearchString = mSearchView.getQuery().toString(); 
    outState.putString(SEARCH_KEY, mSearchString); 
} 

Diese Methode wird aufgerufen, bevor eine Tätigkeit getötet werden, so dass, wenn es einige Zeit in der Zukunft zurückkommt kann es seinen Zustand wieder herzustellen. Wenn der Benutzer nun die Ausrichtung ändert, kann der Status der Benutzeroberfläche über onCreate (Bundle) oder onRestoreInstanceState (Bundle) wiederhergestellt werden.

Jetzt sollten wir onCreateOptionsMenu(Menu menu) verwenden, weil wir unser SearchView konzentrieren müssen.

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.main, menu); 

    MenuItem searchMenuItem = menu.findItem(R.id.menu_main_action_search); 

    mSearchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem); 

    //focus the SearchView 
    if (mSearchString != null && !mSearchString.isEmpty()) { 
     searchMenuItem.expandActionView(); 
     mSearchView.setQuery(mSearchString, true); 
     mSearchView.clearFocus(); 
    } 

    return super.onCreateOptionsMenu(menu); 
} 

Sie können auch this link mit vollständigem Code überprüfen.

+0

Sie hätten 'outState.putCharSequence (SEARCH_KEY, mSearchView.getQuery()); 'statt in String konvertieren können. – arekolek

+1

Auch für 'mSearchString! = Null &&! MSearchString.isEmpty() 'gibt es'! TextUtils.isEmpty (mSearchString) '. – arekolek

Verwandte Themen