Der OnCloseListener von SearchView funktioniert nicht


101

Ich versuche, Unterstützung für die SearchViewAndroid 3.0+ ActionBar hinzuzufügen, aber ich kann die nicht OnCloseListenerzum Laufen bringen .

Hier ist mein Code:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);
    searchView = (SearchView) menu.findItem(R.id.search_textbox).getActionView();
    searchView.setOnQueryTextListener(new OnQueryTextListener() {
        @Override
        public boolean onQueryTextChange(String newText) {
            searchLibrary(newText);
            return false;
        }
        @Override
        public boolean onQueryTextSubmit(String query) { return false; }
    });
    searchView.setOnCloseListener(new OnCloseListener() {
        @Override
        public boolean onClose() {
            System.out.println("Testing. 1, 2, 3...");
            return false;
        }
    });
    return true;
}

Die Suche funktioniert super und alle funktionieren bis auf die OnCloseListener. In Logcat wird nichts gedruckt. Hier ist der Logcat, wenn ich auf die Schaltfläche "Schließen" drücke:

02-17 13:01:52.914: I/TextType(446): TextType = 0x0
02-17 13:01:57.344: I/TextType(446): TextType = 0x0
02-17 13:02:02.944: I/TextType(446): TextType = 0x0

Ich habe die Dokumentation und Beispiele durchgesehen , aber nichts schien daran etwas zu ändern. Ich verwende es auf einem Asus Transformer Prime und einem Galaxy Nexus, beide auf Ice Cream Sandwich. Irgendwelche Ideen?

Aktualisieren:

Ja - System.out.println() funktioniert . Hier ist der Beweis:

   @Override
 public boolean onQueryTextChange(String newText) {
    System.out.println(newText + "hello");
    searchLibrary(newText);
    return false;
 }

Ergebnisse in diesem Logcat:

02-17 13:04:20.094: I/System.out(21152): hello
02-17 13:04:24.914: I/System.out(21152): thello
02-17 13:04:25.394: I/System.out(21152): tehello
02-17 13:04:25.784: I/System.out(21152): teshello
02-17 13:04:26.064: I/System.out(21152): testhello

Hmm, funktioniert OK für mich mit Android 3.2, aber NICHT für 4.0+
PJL


3
Ich bin froh, dass nicht nur ich dieses Problem habe. Hat jemand andere Hacks als den folgenden?
Bencallis

2
Ich habe zwei Dinge gelernt, wenn eingestellt showAsActionist always. Das Suchfeld verfügt über eine eigene Schaltfläche zum Schließen. Wenn diese Option aktiviert ist, wird ifRoom | collapseActionViewsie in der Aktionsleiste erweitert.
Beraki

Antworten:


153

Ich treffe auch dieses Problem, und ich habe keine andere Wahl, als "oncloselistener" aufzugeben. Stattdessen können Sie dann Ihr menuItem abrufen setOnActionExpandListener. Überschreiben Sie dann nicht implementierte Methoden.

@Override
public boolean onMenuItemActionExpand(MenuItem item) {
    // TODO Auto-generated method stub
    Log.d("*******","onMenuItemActionExpand");
    return true;
}

@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
    //do what you want to when close the sesarchview
    //remember to return true;
    Log.d("*******","onMenuItemActionCollapse");
    return true;
}

Ich glaube, wir sprechen nur über ActionBars SearchView, das nur Wabe +
NKijak

Verwenden Sie nicht onCloseListener, sondern nur diesen mit Ihrem Menüpunkt.
Robert

12
Ich denke, Sie können MenuItemCompat.OnActionExpandListener für frühere API-Ebenen verwenden: developer.android.com/reference/android/support/v4/view/…
Ripityom

2
Vollständige Antwort:if (Build.VERSION.SdkInt > BuildVersionCodes.NMr1) item.SetOnActionExpandListener(this); else MenuItemCompat.SetOnActionExpandListener(item, this);
FindOutIslamNow

61

Verwenden Sie für Android API 14+ (ICS und höher) diesen Code:

// When using the support library, the setOnActionExpandListener() method is
// static and accepts the MenuItem object as an argument
MenuItemCompat.setOnActionExpandListener(menuItem, new OnActionExpandListener() {
    @Override
    public boolean onMenuItemActionCollapse(MenuItem item) {
        // Do something when collapsed
        return true;  // Return true to collapse action view
    }

    @Override
    public boolean onMenuItemActionExpand(MenuItem item) {
        // Do something when expanded
        return true;  // Return true to expand action view
    }
});

Weitere Informationen: http://developer.android.com/guide/topics/ui/actionbar.html#ActionView

Ref: onActionCollapse / onActionExpand


31

Für dieses Problem habe ich mir so etwas ausgedacht,

private SearchView mSearchView;

@TargetApi(14)
@Override
public boolean onCreateOptionsMenu(Menu menu)
{

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.conversation_index_activity_menu, menu);

    mSearchView = (SearchView) menu.findItem(R.id.itemSearch).getActionView();

    MenuItem menuItem = menu.findItem(R.id.itemSearch);

    int currentapiVersion = android.os.Build.VERSION.SDK_INT;
    if (currentapiVersion >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    {
        menuItem.setOnActionExpandListener(new OnActionExpandListener()
        {

            @Override
            public boolean onMenuItemActionCollapse(MenuItem item)
            {
                // Do something when collapsed
                Log.i(TAG, "onMenuItemActionCollapse " + item.getItemId());
                return true; // Return true to collapse action view
            }

            @Override
            public boolean onMenuItemActionExpand(MenuItem item)
            {
                // TODO Auto-generated method stub
                Log.i(TAG, "onMenuItemActionExpand " + item.getItemId());
                return true;
            }
        });
    } else
    {
        // do something for phones running an SDK before froyo
        mSearchView.setOnCloseListener(new OnCloseListener()
        {

            @Override
            public boolean onClose()
            {
                Log.i(TAG, "mSearchView on close ");
                // TODO Auto-generated method stub
                return false;
            }
        });
    }


    return super.onCreateOptionsMenu(menu);

}

1
Was passiert, wenn Sie immer mit setIconofiedByDefault (false) erweitert haben? Es funktioniert nicht ... :(
Joan Casadellà

19

Ich bin auf Android 4.1.1 auf dasselbe Problem gestoßen. Es scheint ein bekannter Fehler zu sein: https://code.google.com/p/android/issues/detail?id=25758

Wie auch immer, als Problemumgehung habe ich den Listener für Statusänderungen verwendet (wenn SearchView von der Aktionsleiste getrennt ist, ist es offensichtlich auch geschlossen).

view.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {

    @Override
    public void onViewDetachedFromWindow(View arg0) {
        // search was detached/closed
    }

    @Override
    public void onViewAttachedToWindow(View arg0) {
        // search was opened
    }
});

Der obige Code hat in meinem Fall gut funktioniert.


Ich poste die gleiche Antwort hier: https://stackoverflow.com/a/24573266/2162924


Ja, dieser Fehler wurde direkt nach dem Posten dieser Frage erstellt. Siehe die Kommentare zur ursprünglichen Frage.
Michell Bak

Oh ok, jetzt sehen. Aber vielleicht ist diese Problemumgehung mit dem Listener für Statusänderungen auch für andere nützlich.
Dario

Obwohl es enttäuschend ist, dass OnCloseListener nicht so funktioniert, wie Sie denken, ist dies tatsächlich eine schöne, saubere Lösung. Ein großes Lob!
welshk91

10

Am Ende habe ich einen kleinen Hack verwendet, der für meinen Zweck gut funktioniert - ich bin mir nicht sicher, ob er für alle Zwecke geeignet ist. Wie auch immer, ich überprüfe, ob die Suchabfrage leer ist. Dies hängt jedoch nicht wirklich mit den SearchView's zusammen OnCloseListener- das funktioniert immer noch nicht!

searchView.setOnQueryTextListener(new OnQueryTextListener() {
            @Override
            public boolean onQueryTextChange(String newText) {
                if (newText.length() > 0) {
                    // Search
                } else {
                    // Do something when there's no input
                }
                return false;
            }
            @Override
            public boolean onQueryTextSubmit(String query) { return false; }
        });

7

Nun, das hat mein Problem gelöst:

Menüpunkt mit showAsAction="always"

<item
    android:id="@+id/action_search"
    android:icon="@drawable/ic_action_search"
    android:title="Search"
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="always"/>

und in Aktivität

searchView.setOnCloseListener(new OnCloseListener() {

        @Override
        public boolean onClose() {

            Log.i("SearchView:", "onClose");
            searchView.onActionViewCollapsed();
            return false;
        }
    });

1
Das Setzen eines alwaysWerts auf ein showAsActionAttribut löst das Problem. Wichtig ist, dass bei erweitertem alwaysWert is notdie showAsActionerweiterte SearchViewSchaltfläche zum Schließen (Kreuzsymbol) nur angezeigt SearchViewwird, wenn die Abfrage in eine Zeichenfolge ungleich Null ist. Das SearchView.onCloseClicked, das Ereignisse mit Schaltflächen zum Schließen behandelt, teilt mit, dass der Rückruf an OnCloseListenernur aufgerufen wird, wenn die Abfrage leer ist, wenn dies nicht der onCloseOnCloseListener
Fall ist

1
Nur ein Hinweis: Diese Methode wird aufgerufen, wenn der Benutzer die Suchansicht schließt (ziemlich offensichtlich, aber ich habe einige Male gebraucht, um dies zu realisieren). Wenn der Benutzer zum ersten Mal auf das X klickt, wird der Text gelöscht, und ich habe dieses Update nicht erhalten. Beim zweiten Klicken auf das X wird die Suchansicht geschlossen und onClose wird aufgerufen. Ich hoffe es hilft!
Federico Alvarez

4

OnCloseListenerStellen Sie sicher, dass dies im Suchmenüelement festgelegt showAsActionist , damit die Arbeit ausgeführt werden kann always.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      tools:context=".SearchActivity">

    <item
        android:id="@+id/search"
        android:title="@string/search"
        android:icon="@drawable/ic_search_toolbar"
        app:showAsAction="always"
        app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>

2

Ich habe das gleiche Problem festgestellt, wenn onCloseListener nicht für SearchView aufgerufen wurde. Um onCloseListener aufzurufen, müssen Sie Folgendes verstehen: Aus dem 25758 aufgetretenen Fehlerproblem und einigen von mir gelesenen Beiträgen müssen Sie Folgendes festlegen:

searchView.setIconifiedByDefault(true);

Aber für meinen Fall wollte ich, dass die Suchansicht geöffnet und nicht immer symbolisiert wird. Ich schaffe es, dies zu beheben, indem ich unten eine weitere Zeile hinzufüge:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.search_bar, menu);
    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    searchView = (SearchView) menu.findItem(R.id.search).getActionView();
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setOnQueryTextListener(queryTextListener);
    searchView.setIconifiedByDefault(true);
    searchView.setIconified(false);
    return true;
}

Die searchView.setIconified (false) bewirkt, dass die searchView geöffnet wird, obwohl die Standardeinstellung in der vorherigen Zeile auf true gesetzt ist. Auf diese Weise gelang es mir, sowohl eine SearchView zu haben, die sich ständig öffnet, als auch den onCloseListener aufzurufen.


2

Erstellen Sie den Menüpunkt mit der app:showAsActionEinstellung immer.

<item   
 android:id="@+id/action_search"  
 android:title="..."  
 android:icon="..."  
 app:actionViewClass="android.support.v7.widget.SearchView"  
 app:showAsAction="always"/>

Machen Sie beim Erstellen der SearchViewin der onCreateOptionsMenuMethode etwas Ähnliches

inflater.inflate(R.menu.menu_search, menu);
final MenuItem item = menu.findItem(R.id.action_search);
final SearchView search = (SearchView) item.getActionView();
search.setQueryHint(getString(R.string.search_brand_item));
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
  @Override
  public boolean onQueryTextSubmit(String query) {
    // add your code
    return false;
  }

  @Override
  public boolean onQueryTextChange(String newText) {
    // add your code 
    return false;
  }
});
search.setOnCloseListener(new SearchView.OnCloseListener() {
  @Override
  public boolean onClose() {
    // add your code here
    return false;
  }
});
search.setIconifiedByDefault(true); // make sure to set this to true

Es search.setIconifiedByDefault(true)muss festgelegt werden, dass die oben erstellte Methode trueaufgerufen wird .onClose()SearchView.OnCloseListener()



0

Der Grund, warum das OnCloseListenernicht aufgerufen wird, ist, dass der Android-Code einen Fehler enthält - der Listener wird nur aufgerufen, wenn Sie auch anrufen setIconifiedByDefault(true).


7
Ich habe gerade versucht, setIconifiedByDefault (true) hinzuzufügen, aber es heißt nicht
Giuseppe

@ Joseph Earl: Ich habe hier ein ähnliches Problem: stackoverflow.com/questions/43702055/… . Irgendwelche Gedanken oder Ideen zur Behebung?
AJW

0

scheint schon ein alter Thread zu sein, aber ich dachte, ich hätte am Anfang das gleiche Problem API 18. Nachdem ich herumgegoogelt habe, diesen Thread gefunden habe, habe ich eine weitere Stunde lang den Javadoc gelesen, der versucht und fehlerhaft für etwas war, das ich in Javadoc nicht vollständig verstehe, die folgende Arbeit für mich jetzt:

searchView.setIconifiedByDefault(true);

   // OnQueryTextListener
   @Override
   public boolean onQueryTextSubmit(String query) {
      Log.d(tag, "onQueryTextSubmit: " + query);
      return true;
   }

   @Override
   public boolean onQueryTextChange(String query) {
      Log.d(tag, "onQueryTextChange: " + query);
      return true;
   }

   // OnCloseListener
   @Override
   public boolean onClose() {
      Log.w(tag, "onClose: ");
      return false;
   }

Ich habe ein bisschen mit wahr / falsch gespielt, das macht irgendwie den Unterschied und es funktioniert jetzt für mich. Hoffentlich könnte es jemandem Zeit sparen.


0

Es ist eine Problemumgehung, hat aber für mich funktioniert

  searchView.setOnQueryTextListener(new android.widget.SearchView.OnQueryTextListener() {

                String lastText;

                @Override
                public boolean onQueryTextChange(final String newText) {
                    if (lastText != null && lastText.length() > 1 && newText.isEmpty()) {
                        // close ctn clicked

                        return true;
                    }
}

0
    searchView.setOnCloseListener {
        d("click", "close clicked")
        return@setOnCloseListener false
    }

Wenn Sie auf closeView klicken ->

D / Klick: Schließen geklickt


1
Antworten mit einem Code-Blob und einigen kryptischen Wörtern sind nicht besonders klar. Verwenden Sie einfach die natürliche Sprache, um zu beschreiben, warum Sie glauben, dass dies das Problem löst, und zeigen Sie dann die Implementierung der Lösung.

0

Ich bin auf dieses Problem gestoßen, als ich versucht habe, das Anzeigen / Löschen der SearchView zu erkennen. Am Ende habe ich einen anderen Hörer verwendet und es hat für das funktioniert, was ich brauche:

        setOnQueryTextFocusChangeListener { _, hasFocus ->
            if (hasFocus) {
                // SearchView is being shown
            } else {
                // SearchView was dismissed
            }
        }

0

Ich habe die SearchView-Schaltfläche zum Schließen verwendet und einen setOnClickListener darauf gesetzt

searchView.findViewById<ImageView>(R.id.search_close_btn).setOnClickListener {
    searchView.setQuery("", false)
    searchView.clearFocus()
}

-2

In Android gibt es keine Konsole, bei der Sie sich anmelden können. Verwenden Sie stattdessen das Android-Protokollierungsframework:

Log.d("Test Tag", "Testing.  1, 2, 3...");

Siehe auch diese Frage: Warum funktioniert "System.out.println" in Android nicht?


2
Nicht wahr, es funktioniert gut. Bitte lesen Sie meine aktualisierte Frage - Ich habe eine Zeile in die onQueryTextChange-Methode eingefügt, um dies zu beweisen. Ich habe auch versucht, Log.d () hinzuzufügen, aber das hat auch nichts angezeigt.
Michell Bak

Oh mein schlechtes! Sieht aus wie irgendwo auf dem Weg, auf dem sie beschlossen haben, System.out.println in Log.i auszugeben. Viel Glück
Chris Knight

-3

Es gibt zwei gängige Muster für SearchView.setOnCloseListener(). Dies gilt wirklich für alle Zuhörer, aber ich gehe speziell auf Ihre Frage ein. Die erste Möglichkeit besteht darin, eine Listener-Funktion zu erstellen und an eine Member-Variable anzuhängen. Die zweite Möglichkeit besteht darin, dass die Klasse die Schnittstelle implementiert und der Handler eine Member-Funktion ist.

Das Erstellen eines Listener-Objekts sieht folgendermaßen aus:

private SearchView mSearchView;
private final SearchView.OnCloseListener mOnCloseListener = 
    new SearchView.OnCloseListener() {
        public boolean onClose() {
            doStuff();
            return myBooleanResult;
        }
    };
mSearchView.setOnCloseListener(mOnCloseListener);

Das Implementieren von Listener auf Klassenebene sieht folgendermaßen aus:

public class MyClass implements OnCloseListener {
    private SearchView mSearchView;

    public MyClass(...) {
        mSearchView.setOnCloseListener(this);
    }

    @Override
    public boolean onClose() {
        doStuff();
        return false;
    }
}

Ich habe keine Beispiele gesehen, die das OnCloseListenerAd-hoc erstellen , wie Sie es in Ihrer Frage getan haben.


Hey Sparky, danke, dass du das kommentiert hast. Ich sehe nicht wirklich, wie das etwas ändern sollte. Ein verschachtelter Listener ist auch eine gültige Methode, um ihn zu erstellen, und er funktioniert mit Honeycomb, wie Sie anhand der Kommentare hier sehen können. Ich hatte keine Probleme mit verschachtelten Listenern auf ICS außer diesem - was wiederum auf Honeycomb funktioniert.
Michell Bak

Mit verschachtelten Zuhörern meine ich anonyme innere Klassen.
Michell Bak

Ich bin damit einverstanden, dass es keine Rolle spielen sollte. Ich kommentiere nur, was in der Codebasis vorhanden ist. Ich werde nachsehen, ob möglicherweise die Bedingungen, unter denen onClose neu definiert wurde, neu definiert wurden.
Sparky

Ich bin mir nicht sicher, ob Sie Java verstehen - es wird eine anonyme innere Klasse genannt.
Joseph Earl
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.