android - SearchView''s OnCloseListener no funciona
android-3.0-honeycomb android-4.0 (15)
Estoy tratando de agregar compatibilidad para SearchView
en Android 3.0+ ActionBar, pero no puedo hacer que OnCloseListener
funcione.
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 bien y todo funciona, excepto OnCloseListener
. Nada se imprime en 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
Revisé la documentación y las muestras, pero nada pareció cambiarlo. Lo estoy ejecutando en un Asus Transformer Prime y un Galaxy Nexus, ambos en Ice Cream Sandwich. ¿Algunas ideas?
Actualizar:
Sí - System.out.println()
funciona. Aquí hay una prueba:
@Override
public boolean onQueryTextChange(String newText) {
System.out.println(newText + "hello");
searchLibrary(newText);
return false;
}
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
Bueno, esto resolvió mi problema:
showAsAction="always"
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;
}
});
Cree el elemento de menú con la app:showAsAction
establecido en always.
<item
android:id="@+id/action_search"
android:title="..."
android:icon="..."
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
Al crear SearchView
en el método onCreateOptionsMenu
, haga 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
El search.setIconifiedByDefault(true)
debe establecerse en true
para llamar al método onClose()
en el SearchView.OnCloseListener()
creado anteriormente.
Es una solución pero me ha funcionado
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;
}
}
Hay dos patrones comunes para SearchView.setOnCloseListener()
. Esto es realmente cierto para todos los oyentes, pero estoy abordando su pregunta específicamente. La primera es crear una función de escucha y adjuntarla a una variable de miembro, y la segunda es hacer que la clase implemente la interfaz y que el controlador sea una función miembro.
La creación de un objeto detector se ve así:
private SearchView mSearchView;
private final SearchView.OnCloseListener mOnCloseListener =
new SearchView.OnCloseListener() {
public boolean onClose() {
doStuff();
return myBooleanResult;
}
};
mSearchView.setOnCloseListener(mOnCloseListener);
La implementación del 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 hizo en su pregunta.
He encontrado el mismo problema con onCloseListener que no invoca para SearchView. Comprenda del problema de los errores planteado en 25758 , y algunas publicaciones que he leído, para invocar aCloseListener, debe configurar:
searchView.setIconifiedByDefault(true);
Pero para mi caso, quería que la vista de búsqueda se abriera y no se iconizara todo el tiempo. Me las arreglé 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;
}
El searchView.setIconified (false) hará que SearchView se abra, a pesar de establecer el valor predeterminado para iconified en true en la línea anterior. De esta manera, logré tener un SearchView que se abre todo el tiempo y que invoque onCloseListener.
La razón por la que no se llama a OnCloseListener
es porque hay un error en el código de Android; solo se llama al oyente si también se llama a setIconifiedByDefault(true)
.
Me encontré con el mismo problema en Android 4.1.1. Parece que se trata de un error conocido: https://code.google.com/p/android/issues/detail?id=25758
De todos modos, como solución alternativa utilicé el detector de cambios de estado (cuando SearchView está separado de la barra de acciones, 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.
Publiqué la misma respuesta aquí: https://.com/a/24573266/2162924
No hay consola en Android para iniciar sesión. En cambio, usa el marco de registro de Android:
Log.d("Test Tag", "Testing. 1, 2, 3...");
Vea también esta pregunta: ¿Por qué no funciona "System.out.println" en Android?
Para Android API 14+ (ICS y superior) 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
Para el problema de MenuItemCompat
, agregué ViewTreeObserver para rastrear el estado de visibilidad. Puede verificar mi respuesta aquí: https://.com/a/28762632/1633609
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);
}
Para que OnCloseListener
funcione, asegúrese de que showAsAction
esté configurado 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>
También me encuentro con este problema, y no tengo más remedio que renunciar a "oncloselistener". En cambio, puede obtener su elemento de menú, luego setOnActionExpandListener
. Luego, anule los métodos de 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;
}
Terminé usando un truco, que funciona bien para mi propósito, no estoy seguro de que funcione con todos los propósitos. De todos modos, estoy haciendo una comprobación para ver si la consulta de búsqueda está vacía. OnCloseListener
embargo, esto no está realmente relacionado con OnCloseListener
, ¡eso aún 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; }
});
parece un hilo viejo, pero pensé que tuve el mismo problema API 18 en el primer comienzo. Después de buscar en Google, encontré este hilo, otra hora leyó el javadoc probado y con errores para 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é con verdadero / falso un poco, que de alguna manera hace la diferencia, y ahora funciona para mí. Con suerte, podría ahorrarle tiempo a alguien.