SearchView del OnCloseListener no funciona
Pregunta
Estoy tratando de agregar soporte para el SearchView
en el Android 3.0+ ActionBar, pero no puedo obtener el OnCloseListener
para el trabajo.
Aquí está mi código:
@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 búsqueda funciona muy bien y todo es trabajo, excepto para el OnCloseListener
.Nada de lo que se imprime a Logcat.Aquí está el Logcat para cuando estoy presionando el botón "Cerrar":
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
He mirado a través de la documentación y muestras, pero nada parecía cambiar.Yo estoy corriendo en una Asus Transformer Prime y un Galaxy Nexus, tanto en Ice Cream Sandwich.Alguna idea?
Actualización:
Sí - System.out.println()
¿ trabajo.Aquí está la prueba:
@Override
public boolean onQueryTextChange(String newText) {
System.out.println(newText + "hello");
searchLibrary(newText);
return false;
}
Los resultados en este 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
Solución
También me encuentro con este problema, y yo no tenemos más remedio que renunciar a la "oncloselistener".En su lugar, usted puede conseguir su menuItem, entonces setOnActionExpandListener
.A continuación, reemplazar unimplents métodos.
@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;
}
Otros consejos
Para Android API 14+ (ICS y mayor) use este código:
// 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
}
});
Para más información: http://developer.android.com/guide/topics/ui/actionbar.html#actionview
Árbitro: onationCollapse/onactionExpand
Para este problema se me ocurrió algo como esto,
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);
}
Me encontré con el mismo problema en Android 4.1.1. Parece que es un error conocido: https://code.google.com/p/android/issues/detail?id=25758
De todos modos, como una solución, utilicé el oyente de cambio de estado (cuando SearchView se separa de la barra de acción, también se cierra obviamente).
view.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override
public void onViewDetachedFromWindow(View arg0) {
// search was detached/closed
}
@Override
public void onViewAttachedToWindow(View arg0) {
// search was opened
}
});
El código anterior funcionó bien en mi caso.
Publico la misma respuesta aquí: https://stackoverflow.com/a/24573266/2162924
Terminé usando un poco de hack, que funciona bien para mi propósito, no estoy seguro de que funcione con todos los propósitos. De todos modos, estoy haciendo un cheque para ver si la consulta de búsqueda está vacía. Esto no está realmente relacionado con el SearchView
's OnCloseListener
Sin embargo, ¡eso todavía no funciona!
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; }
});
Bueno, esto resolvió mi problema:
Elemento de menú 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"/>
y en actividad
searchView.setOnCloseListener(new OnCloseListener() {
@Override
public boolean onClose() {
Log.i("SearchView:", "onClose");
searchView.onActionViewCollapsed();
return false;
}
});
He encontrado el mismo problema con OnCloseListener que no invocó para SearchView. Comprender por el problema de errores planteado en 25758, y algunas publicaciones que he leído, para invocar a OnCloSeListener, debes establecer:
searchView.setIconifiedByDefault(true);
Pero para mi caso quería que se abriera la vista de búsqueda y no se haya iconificado todo el tiempo. Me las arreglo para resolver esto agregando una línea más a continuación:
@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) hará que la SearchView se abra, a pesar de establecer el valor predeterminado en Iconified a True en la línea anterior. De esta manera, logré tener una vista de búsqueda que se abre todo el tiempo y que invoque el OnCloSelistener.
Para hacer el OnCloseListener
trabajar, asegúrese de que showAsAction
se establece en always
En el elemento del menú de búsqueda.
<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>
Para MenuItemCompat
Problema Agregué ViewTreeObServer para rastrear el estado de visibilidad. Puedes consultar mi respuesta aquí:https://stackoverflow.com/a/28762632/1633609
Crea el elemento de menú con el app:showAsAction
establecido para siempre.
<item
android:id="@+id/action_search"
android:title="..."
android:icon="..."
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
Al crear el SearchView
en el onCreateOptionsMenu
método hacer algo similar
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
los search.setIconifiedByDefault(true)
necesita ser configurado en true
para llamar al onClose()
método en el SearchView.OnCloseListener()
creado arriba.
La razón por la que el OnCloseListener
no se llama es porque hay un error en el código de Android: el oyente solo se llama si también llama setIconifiedByDefault(true)
.
Parece un hilo viejo ya, pero pensé que tengo el mismo problema API 18 en el primer comienzo. Después de buscar en Google, encontré este hilo, otra hora leyó que el Javadoc probó y erró por algo que no pretendo entender completamente en Javadoc, el siguiente trabajo para mí ahora:
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;
}
Jugué un poco con True/False, que de alguna manera marca la diferencia, y ahora funciona para mí. Con suerte, podría ahorrar tiempo a alguien.
Es una solución pero ha funcionado para mí
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;
}
}
searchView.setOnCloseListener {
d("click", "close clicked")
return@setOnCloseListener false
}
Si hace clic en SearchView Cerrar ->
D/Haga clic: Cerrar Haga clic
Encontré este problema mientras intentaba detectar la muestra/despido de SearchView. Terminé usando un oyente diferente y funcionó para lo que necesito:
setOnQueryTextFocusChangeListener { _, hasFocus ->
if (hasFocus) {
// SearchView is being shown
} else {
// SearchView was dismissed
}
}
No hay consola en Android para registrar. En su lugar, use el marco de registro de Android:
Log.d("Test Tag", "Testing. 1, 2, 3...");
Ver también esta pregunta: ¿Por qué no funciona "System.out.println" en Android?
Hay dos patrones comunes para SearchView.setOnCloseListener()
. Esto es realmente cierto para todos los oyentes, pero estoy abordando su pregunta específicamente. La primera forma es crear una función de oyente y adjuntarla a una variable miembro, y la segunda es hacer que la clase implementa la interfaz y hacer que el controlador sea una función miembro.
Crear un objeto de oyente se ve así:
private SearchView mSearchView;
private final SearchView.OnCloseListener mOnCloseListener =
new SearchView.OnCloseListener() {
public boolean onClose() {
doStuff();
return myBooleanResult;
}
};
mSearchView.setOnCloseListener(mOnCloseListener);
Implementar el oyente a nivel de clase se ve así:
public class MyClass implements OnCloseListener {
private SearchView mSearchView;
public MyClass(...) {
mSearchView.setOnCloseListener(this);
}
@Override
public boolean onClose() {
doStuff();
return false;
}
}
No he visto ningún ejemplo que cree el OnCloseListener
ad-hoc, como lo hiciste en tu pregunta.