Cómo usar SearchView en la barra de herramientas de Android

124

El código en el que estoy trabajando está usando un Toolbar e infla a menu.

Aqui esta el codigo

private Toolbar mToolbar;
mToolbar.inflateMenu(R.menu.chat_screen_menu);
setupMenu ();
private void setupMenu ()
   {
   mMenu = mToolbar.getMenu();
   if (mMenu != null)
      {
       if (mChatPager != null && mChatPager.getCurrentItem() > 0)
          {
          mMenu.setGroupVisible(R.id.menu_group_chats, true);
          mMenu.setGroupVisible(R.id.menu_group_contacts, false);
          }
       else
          {
           mMenu.setGroupVisible(R.id.menu_group_chats, false);
           mMenu.setGroupVisible(R.id.menu_group_contacts, true);
           mMenu.setGroupVisible(R.id.menu_group_otr_verified,false);
           mMenu.setGroupVisible(R.id.menu_group_otr_unverified,false);
           mMenu.setGroupVisible(R.id.menu_group_otr_off,false);
          }
    }
    mToolbar.setOnMenuItemClickListener(new OnMenuItemClickListener ()
    {
    ..........
    }
}

Pero ahora, requieren un Searchbotón en el tool_bar. Me las arreglé para ponerlo, seguí una guía aquí. Cuando trato de escribir algo para buscar, el brindis que había puesto para probar lo listenernunca mostrado. que indica que listenerno funciona

@Override
    public boolean onCreateOptionsMenu(Menu menu) {

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

    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_menu_search));
    final Toast toast = new Toast(mApp);

    if (mSearchView != null )
    {
        mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        mSearchView.setIconifiedByDefault(false);

        SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener()
        {
            public boolean onQueryTextChange(String newText)
            {
                mSearchString = newText;
                //doFilterAsync(mSearchString);
                toast.makeText(getApplicationContext(), "Test1", Toast.LENGTH_LONG).show();
                return true;
            }

            public boolean onQueryTextSubmit(String query)
            {
                mSearchString = query;
                //doFilterAsync(mSearchString);
                toast.makeText(getApplicationContext(), "Test2", Toast.LENGTH_LONG).show();

                return true;
            }
        };

        mSearchView.setOnQueryTextListener(queryTextListener);
    }

    return true;

}
Shudy
fuente

Respuestas:

205

Tienes que usar la Appcompatbiblioteca para eso. Que se usa como a continuación:

dashboard.xml

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

    <item
        android:id="@+id/action_search"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="always|collapseActionView"
        app:actionViewClass="androidx.appcompat.widget.SearchView"
        android:title="Search"/>
</menu>

Archivo de actividad (en Java):

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater menuInflater = getMenuInflater();
    menuInflater.inflate(R.menu.dashboard, menu);

     MenuItem searchItem = menu.findItem(R.id.action_search);

    SearchManager searchManager = (SearchManager) MainActivity.this.getSystemService(Context.SEARCH_SERVICE);

    SearchView searchView = null;
    if (searchItem != null) {
        searchView = (SearchView) searchItem.getActionView();
    }
    if (searchView != null) {
        searchView.setSearchableInfo(searchManager.getSearchableInfo(MainActivity.this.getComponentName()));
    }
        return super.onCreateOptionsMenu(menu);
}

Archivo de actividad (en Kotlin):

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.menu_search, menu)

    val searchItem: MenuItem? = menu?.findItem(R.id.action_search)
    val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
    val searchView: SearchView? = searchItem?.actionView as SearchView

    searchView?.setSearchableInfo(searchManager.getSearchableInfo(componentName))
    return super.onCreateOptionsMenu(menu)
}

archivo de manifiesto:

<meta-data 
      android:name="android.app.default_searchable" 
      android:value="com.apkgetter.SearchResultsActivity" /> 

        <activity
            android:name="com.apkgetter.SearchResultsActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop" >
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
            </intent-filter>

            <meta-data
                android:name="android.app.searchable"
                android:resource="@xml/searchable" />
        </activity>

archivo xml de búsqueda:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/search_hint"
    android:label="@string/app_name" />

Y por fin, tu SearchResultsActivitycódigo de clase. para mostrar el resultado de su búsqueda.

Sagar Maiyad
fuente
18
Tenga en cuenta que ahora debería hacerloimport android.support.v7.widget.SearchView
Joaquin Iurchuk
Gracias, ¿alguna idea de cómo manejar el clic "Ir"? ayudaría
Bala Vishnu
2
Solo vincularé la documentación oficial donde también puede encontrar cómo reaccionar a la consulta developer.android.com/training/search/setup.html
koesclem
2
Tenga en cuenta la aplicación: actionViewClass en lugar de android: actionViewClass
DragonT
1
Si ha migrado a AndroidX use:androidx.appcompat.widget.SearchView
Daniil
169

Si desea configurar la función de búsqueda dentro de su Fragment, simplemente agregue estas pocas líneas:

Paso 1 : agrega el campo de búsqueda toolbar:

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

Paso 2 : agrega la lógica a tuonCreateOptionsMenu()

import android.support.v7.widget.SearchView; // not the default !

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

    MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
    searchView = (SearchView) myActionMenuItem.getActionView();
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            // Toast like print
            UserFeedback.show( "SearchOnQueryTextSubmit: " + query);
            if( ! searchView.isIconified()) {
                searchView.setIconified(true);
            }
            myActionMenuItem.collapseActionView();
            return false;
        }
        @Override
        public boolean onQueryTextChange(String s) {
            // UserFeedback.show( "SearchOnQueryTextChanged: " + s);
            return false;
        }
    });
    return true;
}
tm1701
fuente
29
Esta respuesta es mucho más útil si no desea crear / moverse a una nueva actividad cuando un usuario ha enviado la consulta de búsqueda. Esto le permitirá permanecer en la misma actividad / fragmento y simplemente actualizar una vista basada en la entrada de los usuarios. Buena cosa.
Nick.D el
3
UserFeedback ... es mi método similar a Toast.
tm1701
Entrada de teclado no tomada en la vista de búsqueda
Saravanan
¿Qué es R.menu.main?
Alston
public void onCreateOptionsMenu (@NonNull Menu menu, @NonNull MenuInflater inflador) {} puede llamar directamente a este método aquí, puede inflar su propio menú y manejar este directoly desde el fragmento sin usar actividad. buen agradecimiento
Amar Singh
40

Si desea agregarlo directamente en la barra de herramientas.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.Toolbar
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <SearchView
            android:id="@+id/searchView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:iconifiedByDefault="false"
            android:queryHint="Search"
            android:layout_centerHorizontal="true" />

    </android.support.v7.widget.Toolbar>

</android.support.design.widget.AppBarLayout>

Ali
fuente
2
Si está utilizando el soporte SearchView, no olvide declararlo también android.support.v7.widget.SearchViewen el XML.
Carrito abandonado
no te olvides de agregar en gradleimplementation 'com.android.support:design:$latest_version'
Ali
¿Qué es iconificado ?
IgorGanapolsky
¨Si desea que el campo de búsqueda esté siempre visible, llame a setIconifiedByDefault (false) ¨ desde los documentos
noe
16

Integrando SearchView con RecyclerView

1) Agregar elemento de SearchView en el menú

SearchView se puede agregar como actionView en el menú usando

aplicación: useActionClass = "android.support.v7.widget.SearchView".

<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="rohksin.com.searchviewdemo.MainActivity">
<item
    android:id="@+id/searchBar"
    app:showAsAction="always"
    app:actionViewClass="android.support.v7.widget.SearchView"
    />
</menu>

2) Implemente SearchView.OnQueryTextListener en su Actividad

SearchView.OnQueryTextListenerTiene dos métodos abstractos. Por lo tanto, su esqueleto de actividad ahora se vería así después de implementar el escucha de texto SearchView.

YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{

   public boolean onQueryTextSubmit(String query)

   public boolean onQueryTextChange(String newText) 

}

3) Configurar texto de pista de SerchView, oyente, etc.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);

    MenuItem searchItem = menu.findItem(R.id.searchBar);

    SearchView searchView = (SearchView) searchItem.getActionView();
    searchView.setQueryHint("Search People");
    searchView.setOnQueryTextListener(this);
    searchView.setIconified(false);

    return true;
}

4) Implemente SearchView.OnQueryTextListener

Así es como puede implementar métodos abstractos del oyente.

@Override
public boolean onQueryTextSubmit(String query) {

    // This method can be used when a query is submitted eg. creating search history using SQLite DB

    Toast.makeText(this, "Query Inserted", Toast.LENGTH_SHORT).show();
    return true;
}

@Override
public boolean onQueryTextChange(String newText) {

    adapter.filter(newText);
    return true;
}

5) Escriba un método de filtro en su Adaptador RecyclerView.

Puede crear su propia lógica según sus requisitos. Aquí está el fragmento de código de muestra para mostrar la lista de Nombre que contiene el texto escrito en SearchView.

public void filter(String queryText)
{
    list.clear();

    if(queryText.isEmpty())
    {
        list.addAll(copyList);
    }
    else
    {

        for(String name: copyList)
        {
            if(name.toLowerCase().contains(queryText.toLowerCase()))
            {
                list.add(name);
            }
        }

    }

    notifyDataSetChanged();
}

Puede encontrar una muestra completa del código de trabajo> AQUÍ
También puede consultar el código en SearchView con una base de datos SQLite en esta aplicación de música

Rohit Singh
fuente
¿Por qué es necesario el menú?
IgorGanapolsky
1

Implementar SearchView sin el uso del menu.xmlarchivo y abrir a través del botón

En su caso, Activitydebemos utilizar el onCreateOptionsMenumétodo en el que inflaremos mediante programaciónSearchView

private MenuItem searchMenu;
private String mSearchString="";

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        SearchManager searchManager = (SearchManager) StoreActivity.this.getSystemService(Context.SEARCH_SERVICE);


        SearchView mSearchView = new SearchView(getSupportActionBar().getThemedContext());
        mSearchView.setQueryHint(getString(R.string.prompt_search)); /// YOUR HINT MESSAGE
        mSearchView.setMaxWidth(Integer.MAX_VALUE);

        searchMenu = menu.add("searchMenu").setVisible(false).setActionView(mSearchView);
        searchMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);


        assert searchManager != null;
        mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        mSearchView.setIconifiedByDefault(false);

        SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
            public boolean onQueryTextChange(String newText) {
                mSearchString = newText;

                return true;
            }

            public boolean onQueryTextSubmit(String query) {
                mSearchString = query;

                searchMenu.collapseActionView();


                return true;
            }
        };

        mSearchView.setOnQueryTextListener(queryTextListener);


        return true;
    }

Y en su clase de Actividad, puede abrir el SearchViewbotón de cualquier botón en la barra de herramientas como a continuación

YOUR_BUTTON.setOnClickListener(view -> {

            searchMenu.expandActionView();

        });
Ravindra Kushwaha
fuente