Búsqueda de Android con fragmentos

161

¿Alguien sabe de un tutorial o un ejemplo de cómo implementar la interfaz de búsqueda estándar de Android con Fragments? En otras palabras, ¿es posible poner una búsqueda estándar con un SearchManageren un Fragmento?

Cinta negra
fuente
¿A quién le otorgarías el bono a @blackbelt? Raghav dio la respuesta que estaba buscando. pero Alex LockWood también respondió a la primera parte de tu pregunta.
Snicolas
Acepto la respuesta de LockWood. Otorga la recompensa como quieras (creo que es mejor)
Blackbelt
44
¡Me alegra que hayamos obtenido una variedad de respuestas correctas y soluciones alternativas! :)
Alex Lockwood
¿Alguien puede darme la respuesta a esta pregunta ...? Estoy atrapado aquí stackoverflow.com/questions/10600660/…
Novato
1
Estoy usando esta técnica para permanecer dentro del fragmento después de agregar SearchView a la barra de acción: stackoverflow.com/a/6939735/1068167 . Mi aplicación aún no está terminada, pero espero que funcione.
abarcan el

Respuestas:

91

En resumen, no puedes. Hay un par de razones por las cuales Fragmentno es posible crear una interfaz de búsqueda dentro de a .

  1. Al crear una interfaz de búsqueda, debe especificar una "actividad de búsqueda" predeterminada en su manifiesto de Android. Como estoy seguro de que sabe, a Fragmentno puede existir sin un padre Activityy, por lo tanto, esta separación no es posible.

  2. Si ya descubrió el número 1, supongo que hizo esta pregunta con la esperanza de que haya algún "truco" mágico que pueda hacer el trabajo. Sin embargo, la documentación establece que,

    Cuando el usuario ejecuta una búsqueda en el cuadro de diálogo o widget de búsqueda, el sistema inicia su actividad de búsqueda y le entrega la consulta de búsqueda en un Intento con la acción ACTION_SEARCH. Su actividad de búsqueda recupera la consulta del QUERY extra del intento, luego busca sus datos y presenta los resultados.

    El sistema interno subyacente que es responsable de proporcionar resultados de búsqueda espera un Activity, no un Fragment; por lo tanto, implementar una interfaz de búsqueda que sea completamente independiente de un Activityno es posible, ya que requeriría cambios en el sistema subyacente . Mira el código fuente de la SearchableInfoclase si no me crees :).

Dicho esto, no parece que sea demasiado difícil lograr algo similar a lo que estás describiendo. Por ejemplo, puede considerar implementar su actividad de búsqueda para que acepte la android.intent.action.SEARCHintención y (en lugar de mostrar inmediatamente los resultados en a ListView, por ejemplo) pase la consulta de búsqueda a su Fragmentcorreo electrónico. Por ejemplo, considere la siguiente Actividad de búsqueda:

public class SearchableActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {
          String query = intent.getStringExtra(SearchManager.QUERY);
          doMySearch(query);
        }
    }

    /**
     * Performs a search and passes the results to the container
     * Activity that holds your Fragments.
     */
    public void doMySearch(String query) {
        // TODO: implement this
    }
}

Cuando se realiza una solicitud de búsqueda, el sistema iniciará su actividad de búsqueda, realizará la consulta y pasará los resultados a alguna Actividad de contenedor (según su implementación de doMySearch). La actividad del contenedor pasará estos resultados a la búsqueda contenida Fragment, en la que se mostrarán los resultados. La implementación requiere un poco más de trabajo de lo que probablemente esperaba, pero estoy seguro de que hay formas de hacerlo más modular, y parece que esto podría ser lo mejor que puede hacer.

ps Si utiliza este enfoque, es posible que tenga que prestar especial atención a las actividades que se agregan / eliminan en la pila. Vea esta publicación para obtener más información sobre cómo se puede hacer esto.

pps También puede olvidarse por completo de la interfaz de búsqueda estándar e implementar una búsqueda simple dentro de una Fragmenttal como se describe en la publicación de Raghav a continuación .

Alex Lockwood
fuente
@Alex, definitivamente es posible implementar la interfaz de búsqueda estándar de Android usando fragmentos. Pero se necesita MUCHO trabajo ... :-)
Vinay S Shenoy
@VinaySShenoy sí, quiero decir que tendrías que volver a implementar todo SearchManagerpor Fragments, ¿verdad? (o algo así)
Alex Lockwood
1
Para entregar los resultados de búsqueda, he implementado algo similar a lo que sugirió, entregando la intención a la Actividad que la entrega al fragmento correcto si es visible. La parte más difícil fue repoblar la tabla de sugerencias sobre la carga de fragmentos con los datos correctos para permitirme manejar la visualización de sugerencias, así como manejar la búsqueda de envío y hacer clic en las sugerencias. Pero ahora tengo un buen marco para futuras aplicaciones ... :-)
Vinay S Shenoy
Encontré que esta es una mejor respuesta: stackoverflow.com/questions/6938952/… Esto permitirá "buscar" desde Fragmentos. Es cierto que no es el mecanismo de búsqueda oficial proporcionado por Google, pero funciona bien.
Kyle Falconer
76

Aquí está el ejemplo para buscar algo usando fragmentos. Espero que ayude y esto es lo que estás buscando:

public class LoaderCursor extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        FragmentManager fm = getFragmentManager();

        // Create the list fragment and add it as our sole content.
        if (fm.findFragmentById(android.R.id.content) == null) {
            CursorLoaderListFragment list = new CursorLoaderListFragment();
            fm.beginTransaction().add(android.R.id.content, list).commit();
        }
    }

    public static class CursorLoaderListFragment extends ListFragment
            implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {

        // This is the Adapter being used to display the list's data.
        SimpleCursorAdapter mAdapter;

        // If non-null, this is the current filter the user has provided.
        String mCurFilter;

        @Override public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);

            // Give some text to display if there is no data.  In a real
            // application this would come from a resource.
            setEmptyText("No phone numbers");

            // We have a menu item to show in action bar.
            setHasOptionsMenu(true);

            // Create an empty adapter we will use to display the loaded data.
            mAdapter = new SimpleCursorAdapter(getActivity(),
                    android.R.layout.simple_list_item_2, null,
                    new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
                    new int[] { android.R.id.text1, android.R.id.text2 }, 0);
            setListAdapter(mAdapter);

            // Start out with a progress indicator.
            setListShown(false);

            // Prepare the loader.  Either re-connect with an existing one,
            // or start a new one.
            getLoaderManager().initLoader(0, null, this);
        }

        @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            // Place an action bar item for searching.
            MenuItem item = menu.add("Search");
            item.setIcon(android.R.drawable.ic_menu_search);
            item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
            SearchView sv = new SearchView(getActivity());
            sv.setOnQueryTextListener(this);
            item.setActionView(sv);
        }

        public boolean onQueryTextChange(String newText) {
            // Called when the action bar search text has changed.  Update
            // the search filter, and restart the loader to do a new query
            // with this filter.
            mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
            getLoaderManager().restartLoader(0, null, this);
            return true;
        }

        @Override public boolean onQueryTextSubmit(String query) {
            // Don't care about this.
            return true;
        }

        @Override public void onListItemClick(ListView l, View v, int position, long id) {
            // Insert desired behavior here.
            Log.i("FragmentComplexList", "Item clicked: " + id);
        }

        // These are the Contacts rows that we will retrieve.
        static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
            Contacts._ID,
            Contacts.DISPLAY_NAME,
            Contacts.CONTACT_STATUS,
            Contacts.CONTACT_PRESENCE,
            Contacts.PHOTO_ID,
            Contacts.LOOKUP_KEY,
        };

        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            // This is called when a new Loader needs to be created.  This
            // sample only has one Loader, so we don't care about the ID.
            // First, pick the base URI to use depending on whether we are
            // currently filtering.
            Uri baseUri;
            if (mCurFilter != null) {
                baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                        Uri.encode(mCurFilter));
            } else {
                baseUri = Contacts.CONTENT_URI;
            }

            // Now create and return a CursorLoader that will take care of
            // creating a Cursor for the data being displayed.
            String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
                    + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
                    + Contacts.DISPLAY_NAME + " != '' ))";
            return new CursorLoader(getActivity(), baseUri,
                    CONTACTS_SUMMARY_PROJECTION, select, null,
                    Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
        }

        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
            // Swap the new cursor in.  (The framework will take care of closing the
            // old cursor once we return.)
            mAdapter.swapCursor(data);

            // The list should now be shown.
            if (isResumed()) {
                setListShown(true);
            } else {
                setListShownNoAnimation(true);
            }
        }

        public void onLoaderReset(Loader<Cursor> loader) {
            // This is called when the last Cursor provided to onLoadFinished()
            // above is about to be closed.  We need to make sure we are no
            // longer using it.
            mAdapter.swapCursor(null);
        }
    }
}
Novato
fuente
El OP solicitó una "interfaz de búsqueda estándar", pero esto logra una simple "búsqueda" dentro de una, Fragmentasí que no me quejaría. Felicidades! : P
Alex Lockwood
30
La próxima vez es posible que desee citar sus fuentes .
Adrian Monk
Consulte crear una interfaz de búsqueda en el sitio del desarrollador. El OP preguntó si era posible crear un "Fragmento de búsqueda" que funcione con la búsqueda estándar de Android como se describe en la documentación.
Alex Lockwood
Algunas trampas: 1-El uso de un icono de búsqueda personalizado no funciona. 2-SearchView tiene que tener algún código de gestión, como para desactivar el contenido, la manipulación posterior, etc.
AlikElzin-Kilaka
En mi caso onQueryTextChange, no se llama al método.
Shajeel Afzal
57

Es muy posible buscar en un fragmento utilizando la API estándar ActionBar SearchView ActionView. Esto también funcionará con Android 2.1 (API nivel 7) usando las clases de soporte de AppCompat v7.

En tu fragmento:

@Override
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater){
    inflater.inflate(R.menu.search, menu);
    MenuItem item = menu.findItem(R.id.action_search);
    SearchView sv = new SearchView(((YourActivity) getActivity()).getSupportActionBar().getThemedContext());
    MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
    MenuItemCompat.setActionView(item, sv);
    sv.setOnQueryTextListener(new OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            System.out.println("search query submit");
            return false;
        }

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

En tu menú XML

<item
    android:id="@+id/action_search"
    android:icon="@drawable/ic_action_search"
    android:title="Search Waste Items"
    android:showAsAction="ifRoom|collapseActionView"
    nz.govt.app:actionViewClass="android.support.v7.widget.SearchView"
    nz.govt.app:showAsAction="ifRoom|collapseActionView" />
David
fuente
Esto funciona muy bien con la nueva aplicación ActionBarActivitycomcompat v7, gracias
Pelanes
1
leyendo la respuesta aceptada, perdí la esperanza ... las otras respuestas son complejas, ¡leí tu respuesta! ¡Tan sencillo! eso es todo ... muchas gracias
MBH
2
Creo que tenemos que agregar setHasOptionsMenu (verdadero) en onActivityCreated. Según lo visto por @MBH.
Raymond Lukanta
2
@GowthamanM Simplemente use MenuItem.SHOW_AS_ACTION ... si puede, AppCompat está en desuso en API posteriores
David
1
Hola @GowthamanM, usa así: item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM); item.setActionView(searchView);
Rod Lima
15

Uso de las clases de soporte de AppCompat v7. Simplemente añadiendo algo a @ David solución 's de @Rookie solución para conseguir que funcione correctamente de una manera sencilla, aquí está mi código de fragmento:

MyFragment :

public class MyFragment extends Fragment implements SearchView.OnQueryTextListener {

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // What i have added is this
        setHasOptionsMenu(true);
    }

    @Override
    public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {

        //inflater.inflate(R.menu.main, menu); // removed to not double the menu items
        MenuItem item = menu.findItem(R.id.action_search);
        SearchView sv = new SearchView(((MainActivity) getActivity()).getSupportActionBar().getThemedContext());
        MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
        MenuItemCompat.setActionView(item, sv);
        sv.setOnQueryTextListener(this);
        sv.setIconifiedByDefault(false);
        sv.setOnSearchClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Utils.LogDebug("Clicked: ");
            }
        });

        MenuItemCompat.setOnActionExpandListener(item, new MenuItemCompat.OnActionExpandListener() {
            @Override
            public boolean onMenuItemActionCollapse(MenuItem item) {
                // Do something when collapsed
                Utils.LogDebug("Closed: ");
                return true;  // Return true to collapse action view
            }

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

        super.onCreateOptionsMenu(menu,inflater);
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        Utils.LogDebug("Submitted: "+query);
        return true;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        Utils.LogDebug("Changed: "+newText);
        return false;
    }
}

Agregué el onActivityCreatedprimo sin llamarsetHasOptionsMenu(true); el sistema no sabrá que este fragmento tiene que interactuar con el menú.

luego quité la línea inflater.inflate(R.menu.main, menu); porque duplicó los elementos del menú ya que Activity infló un menú, luego Fragment infló otro menú

Gracias a @David y @Rookie

MBH
fuente
7

Al trabajar con Fragmentsusted todavía necesita usar un Activitypara controlar y asignar el Fragments. Esto Activitypuede tener la funcionalidad de búsqueda como antes.

Recientemente he cambiado de una Activityaplicación basada en "normal" a unaFragment aplicación basada y la funcionalidad de búsqueda funcionó igual para mí.

¿Has intentado trabajar en ello y no has tenido éxito? Si es así, brinde más detalles en su pregunta.

EDITAR:

Si usted quiere tener una búsqueda fragmento específico, tiene todos sus Fragmentsampliar una interfaz MyFragmentcon un startSearchmétodo, y que su Activity's startSearchmétodo llamado del fragmento actual startSearchmétodo.

marmor
fuente
El requisito era que la búsqueda de Android estuviera limitada al fragmento específico, no a la actividad. Entonces, no, no lo había probado.
Blackbelt
Todavía no lo he probado, pero esto suena EXACTAMENTE como lo que estoy buscando. Tengo un cajón de navegación con fragmentos que contienen funciones de búsqueda no relacionadas. No quiero evitar el sistema de búsqueda de Android por completo, así que necesitaba algo como esto.
Bassinator
5

Creo que lo logré: en realidad puedes usar fragmentos y agregar un ícono de búsqueda a una barra de acción para que sea posible una búsqueda dentro de los fragmentos. El truco consiste en utilizar una barra de acción, una vista de acción, un oyente, un cargador y un adaptador, por supuesto.

Esto funciona bastante bien, aunque omite por completo el mecanismo de búsqueda de la plataforma Android (pero podría completarse con algo de trabajo para encontrar lo que @Alex Lockwood describe y pasar la búsqueda a fragmentos). No reaccionaría a una intención como se esperaba en el caso de una actividad, pero funciona: los usuarios pueden buscar dentro de fragmentos.

Aquí está el código:

SearchInFragmentActivity

package com.sof.test.searchfragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.View;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.ActionBar.TabListener;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.sof.test.searchfragment.SearchFragment;
import com.sof.test.R;


public class SearchInFragmentActivity extends SherlockFragmentActivity implements TabListener {

    private SearchFragment tab1 = new SearchFragment();
    private SearchFragment tab2 = new SearchFragment();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView( R.layout.search_in_fragments );

        getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        createTab( R.string.tab1, R.drawable.ic_menu_search );
        createTab( R.string.tab2, R.drawable.ic_menu_search );
        getSupportActionBar().setSelectedNavigationItem( 0 );
        invalidateOptionsMenu();
    }

    private void createTab(int tabNameResId, int tabIconResId) {
        ActionBar.Tab tab = getSupportActionBar().newTab();
        tab.setText( tabNameResId );
        tab.setTabListener(this);
        getSupportActionBar().addTab(tab);
    }// met

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        if( ft == null ) {
            return;
        }//if
        View fragmentSlot = findViewById( R.id.fragment );
        Fragment newFragment = null;
        if( fragmentSlot != null ) {
            newFragment = (tab.getPosition() == 0) ? tab1 : tab2;
            ft.replace(R.id.fragment, newFragment );
            ft.setTransition( FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        }//if
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }

}//class

La clase de fragmento SearchFragment (uso 2 instancias dentro de la actividad anterior).

package com.sof.test.searchfragment;


import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.SearchView;
import android.widget.TextView;

import com.sof.test.R;
import com.actionbarsherlock.app.SherlockListFragment;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;

public class SearchFragment extends SherlockListFragment {

    private StringLoader loader = null;
    private StringAdapter adapter = null;
    private List<String> listData = new ArrayList<String>();
    private String query;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = super.onCreateView(inflater, container, savedInstanceState);
        createListData();

        loader = new StringLoader( getActivity(), this );
        adapter = new StringAdapter(listData);
        setListAdapter(adapter);

        getLoaderManager().initLoader(0, null,  new LoaderCallBacks() );
        loader.forceLoad();
        setHasOptionsMenu( true );
        return view;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater ) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate( R.menu.menu_search, menu);
        System.out.println( "inflating menu");

        final SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
        final SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextChange(String newText) {
                showFilteredItems( newText );
                return true;
            }

            @Override
            public boolean onQueryTextSubmit(String query) {
                return true;
            }
        };

        searchView.setOnQueryTextListener(queryTextListener);

        return;
    }//met

    private void showFilteredItems( String query ) {
        this.query = query;
        loader.onContentChanged();
    }

    private void createListData() {
        for( int i = 0; i < 100 ; i ++ ) {
          listData.add( "String "+ i ); 
        }
    }

    public List<String> getData() {
        List<String> listFilteredData = new ArrayList<String>();
        for( String string : listData ) {
            if( query == null || string.contains( query ) ) {
                listFilteredData.add( string );
            }
        }
        return listFilteredData;
    }//met

    private class LoaderCallBacks implements LoaderCallbacks< List<String>> {
        @Override
        public void onLoadFinished(Loader<List<String>> loader,
                List<String> listData) {
            adapter.setListData( listData );
        }// met

        @Override
        public void onLoaderReset(Loader<List<String>> listData) {
            adapter.setListData( new ArrayList<String>() );
        }// met

        @Override
        public Loader<List<String>> onCreateLoader(int arg0,
                Bundle arg1) {
            return loader;
        }// met
    }//class

    private class StringAdapter extends ArrayAdapter< String > {

        private List<String> listDataToDisplay = new ArrayList<String>();
        private LayoutInflater mInflater;

        public StringAdapter( List<String> listData ) {
            super( getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1, listData );
            listDataToDisplay = listData;
            mInflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }//cons

        private void setListData( List<String> newListData ) {
            this.listDataToDisplay.clear();
            this.listDataToDisplay.addAll( newListData );
            notifyDataSetChanged();
        }//met

          /**
         * Populate new items in the list.
         */
        @Override public View getView(int position, View convertView, ViewGroup parent) {
            View view;

            if (convertView == null) {
                view = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
            } else {
                view = convertView;
            }

            ((TextView)view.findViewById( android.R.id.text1)).setText( listDataToDisplay.get( position ) );

            return view;
        }
    }//inner class
}//class

class StringLoader extends AsyncTaskLoader<List<String>> {

    SearchFragment fragment = null;

    public StringLoader(Context context, SearchFragment fragment) {
        super(context);
        this.fragment = fragment;
    }// cons

    @Override
    public List<String> loadInBackground() {
        return fragment.getData();
    }// met
}// class

El archivo xml para el menú de los fragmentos de búsqueda res / menu / menu_search.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="horizontal" >
    <FrameLayout
        android:id="@+id/fragment"
        android:layout_width="0px"
        android:layout_height="match_parent"
        android:layout_weight="1" />
</LinearLayout>

Y el archivo de diseño xml res / layout / search_in_fragments.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="horizontal" >
    <FrameLayout
        android:id="@+id/fragment"
        android:layout_width="0px"
        android:layout_height="match_parent"
        android:layout_weight="1" />
</LinearLayout>
Snicolas
fuente
También me gustaría señalar que Jake Wharton decidió no implementar el SearchViewpara su biblioteca ActionBarSherlock debido a su complejidad ( vea su comentario aquí ). Como puede ver (y como describí también en mi respuesta), la implementación de búsqueda de Android es cualquier cosa menos trivial ... está arraigada en el sistema subyacente, y esto hace que incluso las bibliotecas de terceros sean difíciles de escribir (y eso es algo que dice. .. Jake Wharton es como el Chuck Norris de las bibliotecas de terceros: D).
Alex Lockwood
Echa un vistazo al SearchView.javacódigo fuente aquí.
Alex Lockwood
2
Alex, parece que Jake Wharton cambió de opinión: twitter.com/JakeWharton/status/221169921235755009
Jose_GD
¿Ambos archivos xml son iguales?
Clocker
@Clocker, parece que son. Honestamente, después de 2 años no puedo decir
Snicolas
5

Usa el ActionBary SearchView. Podrá manejar búsquedas sin ninguna conexión a Activity. Simplemente configure un OnQueryTextListeneren SearchView.

MenuItem item = menu.add("Search");
SearchView sv = new SearchView(getActionBar().getThemedContext());
item.setActionView(sv);
item.setIcon(R.drawable.ic_search);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
        | MenuItem.SHOW_AS_ACTION_IF_ROOM);
sv.setOnQueryTextListener(new OnQueryTextListener() {
    @Override
    public boolean onQueryTextSubmit(String query) {
        //...
        return false;
    }
    @Override
    public boolean onQueryTextChange(String newText) {
        //...
        return false;
    }
});

Consulte esta publicación para obtener más detalles sobre la búsqueda personalizada.

AlikElzin-kilaka
fuente
3

solución de otros ..... no me gusta eso. Esto es más fácil para mí. Pero es mi idea. Espero tu opinión.

public interface SearchImpl {
    public void searchQuery(String val);
}

Fragmento

public class MyFragment extends Fragment implements SearchImpl {
    View view;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_almanca, container, false);
        return view;
    }

    @Override
    public void searchQuery(String val) {
        Log.e("getted", val);
    }
}

Actividad

 @Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.main, menu);

    SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            Log.e("setted", "" + query);
            try {
                MyFragment myFGM=new MyFragment();
                myFGM.searchQuery(query);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            return false;
        }
    });
    return super.onCreateOptionsMenu(menu);
}
Numan Turkeri
fuente
1

A Fragmentno puede existir fuera de Activity, ni puede Fragmentvincularse a uno android.intent.action.SEARCHu otrointent-filter .

Entonces, sin usar un Activitypara envolver el Fragment, lo que estás preguntando no es posible.

Boca
fuente
1

En el caso de Fragmentos en un ViewPager, podría hacerlo bloqueando el botón de búsqueda cuando no esté en el fragmento donde quiero dar una barra de búsqueda. En la actividad:

@Override
public boolean onSearchRequested() {

    if (mPager.getCurrentItem() == mAdapter.getPosition(FragmentType.VIDEO))
        return super.onSearchRequested();
    else
        return false;
}

Y en caso de que no haya un botón de búsqueda física, agregué un elemento de acción en el fragmento, que activa este código:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (item.getItemId() == R.id.search_item) {

        return getSherlockActivity().onSearchRequested();
    }
    return super.onOptionsItemSelected(item);
}
galex
fuente
1

encontré una solución :) puede anular este método (startActivity (Intent)) en su BaseActivity y luego verificar si la acción es ACTION_SEARCH y luego hacer su trabajo especial: D

@Override
    public void startActivity(Intent intent) {
        try {
            if (intent.getAction().equals(Intent.ACTION_SEARCH))
                toast("hello");
        } catch (Exception e) {

        }
    }
S. Alawadi
fuente
0

si es posible,

implementa la vista de búsqueda en su actividad, 'onQueryTextChange' en Activity también escuchará la búsqueda en fragmentos, puede verificar la visibilidad del fragmento en 'onQueryTextChange', si está visible puede llamar a su método de búsqueda para fragmentos, funciona perfectamente en mi código

Libin Thomas
fuente