OnCloseListener di SearchView non funziona


101

Sto cercando di aggiungere il supporto per SearchViewnell'ActionBar di Android 3.0+, ma non riesco a farlo OnCloseListenerfunzionare.

Ecco il mio codice:

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

La ricerca funziona alla grande e tutti funzionano tranne il OnCloseListener. Non viene stampato nulla su Logcat. Ecco il Logcat per quando premo il pulsante "Chiudi":

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

Ho esaminato la documentazione e gli esempi, ma nulla sembrava cambiarli. Lo sto eseguendo su un Asus Transformer Prime e un Galaxy Nexus, entrambi su Ice Cream Sandwich. Qualche idea?

Aggiornare:

System.out.println() , funziona. Ecco la prova:

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

Risultati in questo 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, funziona bene per me con Android 3.2 ma NON per 4.0+
PJL

10
Bug sollevato, 25758
PJL

3
Sono contento che non sia solo io ad avere questo problema. Qualcuno ha altri hack diversi da quello qui sotto?
bencallis

2
Ho imparato due cose se showAsActionè impostato su always. La casella di ricerca ha un pulsante di chiusura proprio ma se è impostata su ifRoom | collapseActionViewsi espande sulla barra delle azioni.
Beraki

Risposte:


153

Incontro anche questo problema e non ho altra scelta che rinunciare a "oncloselistener". Invece, puoi ottenere il tuo menuItem, quindi setOnActionExpandListener. Quindi sovrascrivi i metodi unimplents.

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

Credo che stiamo parlando solo di SearchView di ActionBar che è solo a nido d'ape +
NKijak

non preoccuparti di usare onCloseListener, usa questo con la tua voce di menu.
Robert

12
Penso che tu possa utilizzare MenuItemCompat.OnActionExpandListener per i livelli API precedenti: developer.android.com/reference/android/support/v4/view/…
Ripityom

2
Risposta completa:if (Build.VERSION.SdkInt > BuildVersionCodes.NMr1) item.SetOnActionExpandListener(this); else MenuItemCompat.SetOnActionExpandListener(item, this);
FindOutIslamNow

61

Per Android API 14+ (ICS e versioni successive) utilizzare questo codice:

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

Per ulteriori informazioni: http://developer.android.com/guide/topics/ui/actionbar.html#ActionView

Rif: onActionCollapse / onActionExpand


31

Per questo problema ho pensato a qualcosa di simile,

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
Cosa succede se hai sempre espanso usando setIconofiedByDefault (false)? Non funziona ... :(
Joan Casadellà

19

Ho riscontrato lo stesso problema su Android 4.1.1. Sembra che si tratti di un bug noto: https://code.google.com/p/android/issues/detail?id=25758

Ad ogni modo, come soluzione alternativa ho usato il listener di modifica dello stato (quando SearchView è scollegato dalla barra delle azioni, è anche chiuso ovviamente).

view.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {

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

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

Il codice sopra ha funzionato bene nel mio caso.


Pubblico la stessa risposta qui: https://stackoverflow.com/a/24573266/2162924


Sì, quel bug è stato creato subito dopo aver pubblicato questa domanda. Vedi i commenti sulla domanda originale.
Michell Bak

Oh ok, guarda ora. Ma comunque, forse questa soluzione alternativa con l'ascoltatore del cambiamento di stato potrebbe essere utile anche per altri.
Dario

Sebbene sia deludente che OnCloseListener non funzioni come si potrebbe pensare, questa è in realtà una soluzione carina e pulita. Complimenti!
welshk91

10

Ho finito per usare un po 'di un trucco, che funziona bene per il mio scopo - non sono sicuro che funzionerà con tutti gli scopi. Comunque, sto facendo un controllo per vedere se la query di ricerca è vuota. Questo non è realmente correlato a SearchView's OnCloseListenerperò - non funziona ancora!

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

Bene, questo ha risolto il mio problema:

Voce di menu con 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"/>

e in attività

searchView.setOnCloseListener(new OnCloseListener() {

        @Override
        public boolean onClose() {

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

1
L'impostazione del alwaysvalore per l' showAsActionattributo risolve il problema. La cosa importante è che quando il alwaysvalore è is notpresente in showAsAction, espanso SearchViewpresenta il pulsante di chiusura (icona a forma di croce) solo se la query inSearchView è Stringa non nulla. Il SearchView.onCloseClickedpulsante che gestisce gli eventi del pulsante di chiusura indica che il callback a OnCloseListenerviene chiamato solo se la query è vuota, in caso contrario - viene cancellato prima - ma poi, dopo aver cancellato la query, il pulsante di chiusura scompare e non siamo in grado di fornire il onClosecallback aOnCloseListener
bpawlowski

1
Solo un suggerimento: questo metodo viene chiamato quando l'utente chiude la visualizzazione di ricerca (abbastanza ovvio, ma mi ci sono volute alcune volte per rendermene conto). La prima volta che l'utente fa clic sulla X, cancella il testo e non ho ricevuto l'aggiornamento, al secondo clic sulla X chiude SearchView e viene richiamato onClose. Spero che sia d'aiuto!
Federico Alvarez

4

Per eseguire il OnCloseListenerlavoro, assicurati che showAsActionsia impostato su alwaysnella voce di menu di ricerca.

<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

Ho riscontrato lo stesso problema con onCloseListener che non richiama per SearchView. Capire dal problema del bug sollevato nel 25758 e da alcuni post che ho letto, per invocare onCloseListener, è necessario impostare:

searchView.setIconifiedByDefault(true);

Ma per il mio caso volevo che la visualizzazione della ricerca fosse aperta e non iconizzata tutto il tempo. Riesco a risolverlo aggiungendo un'altra riga sotto:

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

SearchView.setIconified (false) causerà l'apertura di searchView, nonostante l'impostazione predefinita su iconified su true nella riga precedente. In questo modo, sono riuscito ad avere sia un SearchView che si apre tutto il tempo e che richiama onCloseListener.


2

Crea la voce di menu con l' app:showAsActionimpostazione sempre.

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

Quando crei il metodo SearchViewnel onCreateOptionsMenumetodo, fai qualcosa di simile

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

Le search.setIconifiedByDefault(true)necessità di essere impostati trueper chiamare il onClose()metodo sul SearchView.OnCloseListener()creato in precedenza.



0

Il motivo per cui OnCloseListenernon viene chiamato è perché c'è un bug nel codice Android: l'ascoltatore viene chiamato solo se chiami anche tu setIconifiedByDefault(true).


7
Ho appena provato ad aggiungere setIconifiedByDefault (true) ma non si chiama
Giuseppe

@ Joseph Earl: Sto riscontrando un problema simile qui: stackoverflow.com/questions/43702055/… . Qualche pensiero o idea su come risolvere il problema?
AJW

0

sembra già un vecchio thread, ma all'inizio pensavo di avere lo stesso problema con l'API 18. Dopo aver cercato su Google, ho trovato questo thread, un'altra ora ho letto il javadoc provato ed errato per qualcosa che non pretendo di comprendere appieno in javadoc, il seguente lavoro per me ora:

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

Ho giocato un po 'con vero / falso, questo in qualche modo fa la differenza, e ora funziona per me. Si spera che possa far risparmiare tempo a qualcuno.


0

È una soluzione alternativa ma ha funzionato per me

  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
    }

se si fa clic su chiudi searchView ->

D / clic: chiudere cliccato


1
Le risposte con un blob di codice e alcune parole criptiche non sono particolarmente chiare. Usa semplicemente un linguaggio naturale per descrivere il motivo per cui pensi che questo risolva il problema, quindi mostra l'implementazione della soluzione.

0

Ho riscontrato questo problema durante il tentativo di rilevare la visualizzazione / chiusura di SearchView. Ho finito per usare un ascoltatore diverso e ha funzionato per quello di cui avevo bisogno:

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

0

Ho usato il pulsante di chiusura di SearchView e ho impostato un setOnClickListener su di esso

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

-2

Non c'è nessuna console in Android a cui accedere. Utilizza invece il framework di registrazione Android:

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

Vedi anche questa domanda: Perché "System.out.println" non funziona su Android?


2
Non è vero, funziona benissimo. Si prega di consultare la mia domanda aggiornata: ho aggiunto una riga nel metodo onQueryTextChange per dimostrarlo. Ho anche provato ad aggiungere Log.d (), ma neanche questo ha mostrato nulla.
Michell Bak

Oh, colpa mia! Sembra che da qualche parte lungo la strada abbiano deciso di inviare System.out.println al Log.i. Buona fortuna
Chris Knight

-3

Esistono due modelli comuni per SearchView.setOnCloseListener() . Questo è veramente vero per tutti gli ascoltatori, ma sto affrontando la tua domanda in modo specifico. Il primo modo è creare una funzione listener e collegarla a una variabile membro, e il secondo è fare in modo che la classe implementi l'interfaccia e faccia in modo che il gestore sia una funzione membro.

La creazione di un oggetto listener ha questo aspetto:

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

L'implementazione dell'ascoltatore a livello di classe è simile a questa:

public class MyClass implements OnCloseListener {
    private SearchView mSearchView;

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

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

Non ho visto alcun esempio che crei l' OnCloseListenerad-hoc, come hai fatto nella tua domanda.


Ehi Sparky, grazie per aver commentato questo. Non vedo davvero come dovrebbe cambiare qualcosa. Un listener annidato è un modo valido per realizzarlo e funziona su Honeycomb, come puoi vedere in base ai commenti qui. Non ho avuto problemi con ascoltatori annidati su ICS oltre a questo, che funziona di nuovo su Honeycomb.
Michell Bak

Per ascoltatori annidati intendo classi interne anonime.
Michell Bak

Sono d'accordo che non dovrebbe importare. Sto solo commentando ciò che è presente nel codice di base. Cercherò di vedere se forse le condizioni in cui onClose sono state ridefinite.
Sparky

Non sono sicuro che tu capisca Java: si chiama classe interna anonima.
Joseph Earl
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.