Ricerca Android con frammenti


161

Qualcuno conosce un tutorial o un esempio di come implementare l' interfaccia di ricerca Android standard con Fragments? In altre parole, è possibile inserire una ricerca standard con a SearchManagerin un frammento?


Chi concederesti il ​​bonus a @blackbelt? Raghav ha dato la risposta che stavo cercando. ma Alex LockWood ha anche risposto alla prima parte della tua domanda.
Snicolas,

Accetto la risposta di LockWood. Assegna la taglia come preferisci (penso che sia meglio)
Blackbelt

4
Sono contento che abbiamo finito per ottenere una tale varietà di risposte corrette e soluzioni alternative! :)
Alex Lockwood,

Qualcuno può darmi la risposta a questa domanda ..? Sono bloccato qui stackoverflow.com/questions/10600660/…
Rookie,

1
Sto usando questa tecnica per rimanere all'interno del frammento dopo l'aggiunta della SearchView al ActionBar: stackoverflow.com/a/6939735/1068167 . La mia domanda non è ancora stata completata, ma speriamo che funzioni.
durata

Risposte:


91

In breve, non puoi. Ci sono un paio di ragioni per cui Fragmentnon è possibile creare un'interfaccia di ricerca all'interno di a .

  1. Quando si crea un'interfaccia di ricerca, è necessario specificare un '"attività di ricerca" predefinita nel manifest di Android. Come sono sicuro che sai, a Fragmentnon può esistere senza un genitore Activitye quindi questa separazione non è possibile.

  2. Se hai già capito il n. 1, presumo che tu abbia posto questa domanda nella speranza che ci sia qualche "hack" magico là fuori che possa portare a termine il lavoro. Tuttavia, la documentazione afferma che,

    Quando l'utente esegue una ricerca nella finestra di dialogo o nel widget di ricerca, il sistema avvia l'attività di ricerca e consegna la query di ricerca in un Intento con l'azione ACTION_SEARCH. La tua attività di ricerca recupera la query dal QUERY extra dell'intento, quindi cerca i tuoi dati e presenta i risultati.

    Il sistema interno sottostante che è responsabile della fornitura dei risultati della ricerca prevede un Activity, non un Fragment; pertanto, Activitynon è possibile implementare un'interfaccia di ricerca completamente indipendente da un , poiché richiederebbe modifiche al sistema sottostante stesso . Controlla il codice sorgente per la SearchableInfoclasse se non mi credi :).

Detto questo, non sembra che sarebbe troppo difficile ottenere qualcosa di simile a quello che stai descrivendo. Ad esempio, potresti considerare di implementare la tua attività di ricerca in modo che accetti l' android.intent.action.SEARCHintento e (invece di visualizzare immediatamente i risultati in un ListView, ad esempio) passerà la query di ricerca ai tuoi messaggi Fragment. Ad esempio, considera la seguente attività di ricerca:

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

Quando viene effettuata una richiesta di ricerca, il sistema avvierà la tua attività di ricerca, eseguirà la query e passerà i risultati ad alcune attività del contenitore (in base all'implementazione di doMySearch). Il contenitore Activity passerà quindi questi risultati al contenuto ricercabile Fragment, in cui verranno visualizzati i risultati. L'implementazione richiede un po 'più di lavoro di quello che probabilmente speravi, ma sono sicuro che ci sono modi in cui puoi renderlo più modulare e sembra che questo potrebbe essere il meglio che puoi fare.

ps Se usi questo approccio, potresti dover prestare particolare attenzione a quali attività vengono aggiunte / rimosse nel backstack. Vedi questo post per ulteriori informazioni su come ciò potrebbe essere fatto.

pps Potresti anche dimenticare completamente l'interfaccia di ricerca standard e implementare una semplice ricerca all'interno di un Fragmentcome descritto nel post di Raghav di seguito .


@Alex, È sicuramente possibile implementare l'interfaccia di ricerca Android standard usando frammenti. Ma ci vuole MOLTO lavoro ... :-)
Vinay S Shenoy,

@VinaySShenoy sì, intendo che dovresti implementare nuovamente l'intero SearchManagerper Fragments vero? (o qualcosa del genere)
Alex Lockwood,

1
Per fornire risultati di ricerca, ho implementato qualcosa di simile a quello che hai suggerito, fornendo l'intento all'attività che lo consegna al frammento giusto se è visibile. La parte più difficile è stata ripopolare la tabella dei suggerimenti sul caricamento dei frammenti con i dati giusti per permettermi di gestire la visualizzazione dei suggerimenti e gestire l'invio della ricerca e fare clic sui suggerimenti. Ma ora ho un bel framework per le app future .. :-)
Vinay S Shenoy

Ho trovato che questa è una risposta migliore: stackoverflow.com/questions/6938952/… Questo consentirà la "ricerca" all'interno dei frammenti. È vero, non è il meccanismo di ricerca ufficiale fornito da Google, ma funziona perfettamente.
Kyle Falconer,

76

Ecco l'esempio per cercare qualcosa usando i frammenti. Spero che sia d'aiuto e questo è quello che stai cercando:

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

L'OP ha chiesto "interfaccia di ricerca standard", ma ciò consente di ottenere una semplice "ricerca" all'interno di un Fragmentmodo per non lamentarmi. Congratulazioni! : P
Alex Lockwood,

30
La prossima volta potresti voler citare le tue fonti .
Adrian Monk

Vedere la creazione di un'interfaccia di ricerca sul sito dello sviluppatore. L'OP ha chiesto se fosse possibile creare un "frammento ricercabile" che funzioni con la ricerca Android standard come descritto nella documentazione.
Alex Lockwood,

Alcune insidie: 1-L'uso di un'icona di ricerca personalizzata non funziona. 2-SearchView deve avere un codice di gestione, come per disabilitare il contenuto,
gestirlo

Nel mio caso il onQueryTextChangemetodo non viene chiamato.
Shajeel Afzal,

57

È possibile effettuare una ricerca in un frammento utilizzando l'API ActionView ActionView standard di SearchBar. Questo funzionerà anche con Android 2.1 (livello API 7) utilizzando le classi di supporto AppCompat v7.

Nel tuo frammento:

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

Nel tuo menu 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" />

Funziona alla grande con la nuova app ActionBarActivity v7, grazie
Pelanes

1
leggendo la risposta accettata, ho perso la speranza ... le altre risposte sono complesse, ho letto la tua risposta !!! Così semplice! tutto qui ... grazie mille
MBH

2
Penso che dobbiamo aggiungere setHasOptionsMenu (true) in onActivityCreated. Come notato da @MBH.
Raymond Lukanta, l'

2
@GowthamanM Basta usare MenuItem.SHOW_AS_ACTION .... se sei in grado di rendere AppCompat obsoleto nelle API successive
David

1
Ehi @GowthamanM, usa così: item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM); item.setActionView(searchView);
Rod Lima

15

Utilizzo delle classi di supporto AppCompat v7. Basta aggiungere qualcosa a @ David soluzione s' dal @Rookie soluzione per farlo funzionare correttamente in modo semplice, ecco il mio frammento di codice:

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

Ho aggiunto il onActivityCreated, perché senza chiamare setHasOptionsMenu(true);il sistema non saprà che questo frammento deve interagire con il menu.

poi ho rimosso la linea inflater.inflate(R.menu.main, menu);perché raddoppiava le voci di menu poiché Attività gonfiava un menu, quindi Frammento gonfiava un altro menu

Grazie a @David e @Rookie


7

Quando lavori con Fragmentste devi comunque usare un Activityper controllare e assegnare il Fragments. Questo Activitypuò avere funzionalità di ricerca come prima.

Di recente sono passato da Activityun'app "normale" a un'app Fragmentbasata e la funzionalità di ricerca ha funzionato allo stesso modo per me.

Hai provato a lavorarci su e non ci sei riuscito? Se è così, dai qualche dettaglio in più alla tua domanda.

MODIFICARE:

Se si vuole avere una ricerca frammento preciso, avere tutti i vostri Fragmentsestendere un'interfaccia MyFragmentcon un startSearchmetodo, e avere il vostro Activity's startSearchmetodo di chiamata del frammento corrente startSearchmetodo.


Il requisito era che la ricerca Android fosse limitata al frammento specifico, non all'attività. Quindi no, non l'avevo provato.
Blackbelt,

Non l'ho ancora provato, ma suona ESATTAMENTE quello che sto cercando. Ho un cassetto di navigazione con frammenti che contengono ciascuno funzionalità di ricerca non correlate. Non voglio bypassare del tutto il sistema di ricerca Android, quindi avevo bisogno di qualcosa del genere.
Bassista il

5

Penso di averlo raggiunto: puoi effettivamente usare i frammenti e aggiungere un'icona di ricerca a una barra delle azioni in modo che sia possibile una ricerca all'interno dei frammenti. Il trucco è usare una barra delle azioni, una vista dell'azione, un ascoltatore, un caricatore e un adattatore, ovviamente.

Funziona abbastanza bene anche se ignora completamente il meccanismo di ricerca della piattaforma Android (ma potrebbe essere completato con un po 'di lavoro per trovare ciò che @Alex Lockwood descrive e passare la ricerca ai frammenti). Non reagirebbe a un intento come previsto nel caso di un'attività, ma funziona: gli utenti possono cercare all'interno di frammenti.

Ecco il codice:

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 classe di frammenti SearchFragment (utilizzo 2 istanze all'interno dell'attività sopra).

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

Il file xml per il menu dei frammenti di ricerca 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>

E il file di layout 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>

Vorrei anche sottolineare che Jake Wharton ha deciso di non implementare la SearchViewsua libreria ActionBarSherlock a causa della sua complessità ( vedi il suo commento qui ). Come puoi vedere (e come ho descritto anche nella mia risposta), l'implementazione della ricerca di Android è tutt'altro che banale ... è radicata nel sistema sottostante e questo rende difficile persino scrivere (e ciò sta dicendo qualcosa). .. Jake Wharton è come il Chuck Norris delle biblioteche di terze parti!: D).
Alex Lockwood,

Dai un'occhiata al SearchView.javacodice sorgente qui.
Alex Lockwood,

2
Alex, sembra che Jake Wharton abbia cambiato idea: twitter.com/JakeWharton/status/221169921235755009
Jose_GD

Entrambi questi file XML sono uguali?
Clocker,

@Clocker, sembra che lo siano. Onestamente, dopo 2 anni non posso dire
Snicolas il

5

Utilizzare il ActionBare SearchView. Sarai in grado di gestire le ricerche senza alcuna connessione all'attività. Basta impostare un OnQueryTextListenersu 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;
    }
});

Vedi questo post per maggiori dettagli sulla ricerca personalizzata.


3

altre soluzioni ..... non mi piace. Questo è più facile per me, ma è una mia idea. Sto aspettando la tua opinione

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

Frammento

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

Acitivty

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

1

A Fragmentnon può esistere al di fuori di un Activity, né può Fragmentessere collegato a un android.intent.action.SEARCHo qualsiasi altro intent-filter.

Quindi, senza usare un Activityper avvolgere il Fragment, ciò che stai chiedendo non è possibile.


1

In caso di frammenti in un ViewPager, potrei farlo bloccando il pulsante di ricerca quando non sono sul frammento in cui voglio dare una barra di ricerca. Nell'attività:

@Override
public boolean onSearchRequested() {

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

E in caso di nessun pulsante di ricerca fisica, ho aggiunto un elemento di azione nel frammento, che attiva questo codice:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

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

        return getSherlockActivity().onSearchRequested();
    }
    return super.onOptionsItemSelected(item);
}

1

ho trovato un modo per aggirare :) è possibile ignorare questo metodo (startActivity (Intent)) in BaseActivity e quindi verificare se l'azione è ACTION_SEARCH, quindi eseguire il lavoro speciale: D

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

        }
    }

0

si è possibile,

per favore implementa la vista Ricerca sulla tua Attività, 'onQueryTextChange' in Attività ascolterà anche la ricerca in frammento, puoi controllare la visibilità del frammento in 'onQueryTextChange', se è visibile puoi chiamare il tuo metodo di ricerca per frammento, funziona perfettamente nel mio codice

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.