Recherche Android avec des fragments


161

Quelqu'un connaît-il un didacticiel ou un exemple de mise en œuvre de l' interface de recherche Android standard avec Fragments? En d'autres termes, est-il possible de mettre une recherche standard avec un SearchManagerdans un fragment?


À qui accorderiez-vous le bonus à @blackbelt? Raghav a donné la réponse que je cherchais. mais Alex LockWood a également répondu à la première partie de votre question.
Snicolas

J'accepte la réponse de LockWood. Attribuez la prime comme vous le souhaitez (je pense que c'est mieux)
Blackbelt

4
Je suis heureux que nous ayons obtenu une telle variété de réponses correctes et de solutions de contournement! :)
Alex Lockwood

Quelqu'un peut-il me donner la réponse à cette question ..? Je suis coincé ici stackoverflow.com/questions/10600660/…
Rookie

1
J'utilise cette technique pour rester dans le fragment après avoir ajouté SearchView à la barre d'action: stackoverflow.com/a/6939735/1068167 . Ma candidature n'est pas encore terminée mais j'espère qu'elle fonctionnera.
durée du

Réponses:


91

En bref, vous ne pouvez pas. Il y a plusieurs raisons pour lesquelles la création d'une interface de recherche dans un Fragmentn'est pas possible.

  1. Lors de la création d'une interface de recherche, vous devez spécifier une "activité de recherche" par défaut dans votre manifeste Android. Comme je suis sûr que vous le savez, un Fragmentne peut exister sans un parent Activityet donc, cette séparation n'est pas possible.

  2. Si vous avez déjà compris le n ° 1, je suppose que vous avez posé cette question dans l'espoir qu'il existe un "hack" magique qui peut faire le travail. Cependant, la documentation indique que,

    Lorsque l'utilisateur exécute une recherche dans la boîte de dialogue ou le widget de recherche, le système démarre votre activité de recherche et lui délivre la requête de recherche dans une intention avec l'action ACTION_SEARCH. Votre activité de recherche récupère la requête à partir du QUERY extra de l'intent, puis recherche vos données et présente les résultats.

    Le système interne sous-jacent chargé de fournir les résultats de la recherche attend un Activity, pas un Fragment; ainsi, la mise en œuvre d'une interface de recherche totalement indépendante de an Activityn'est pas possible, car elle nécessiterait des modifications du système sous - jacent lui-même . Consultez le code source de la SearchableInfoclasse si vous ne me croyez pas :).

Cela étant dit, il ne semble pas qu'il soit trop difficile de réaliser quelque chose de similaire à ce que vous décrivez. Par exemple, vous pouvez envisager d'implémenter votre activité de recherche afin qu'elle accepte l' android.intent.action.SEARCHintention et (au lieu d'afficher immédiatement les résultats dans un ListView, par exemple) transmette la requête de recherche à vos Fragments. Par exemple, considérez l'activité de recherche suivante:

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

Lorsqu'une demande de recherche est effectuée, le système lancera votre activité de recherche, exécutera la requête et transmettra les résultats à une activité de conteneur (en fonction de votre implémentation de doMySearch). L'activité du conteneur transmettra ensuite ces résultats à l'objet de recherche contenu Fragment, dans lequel les résultats seront affichés. La mise en œuvre nécessite un peu plus de travail que ce que vous espériez probablement, mais je suis sûr qu'il existe des moyens de la rendre plus modulaire, et il semble que cela puisse être le mieux que vous puissiez faire.

ps Si vous utilisez cette approche, vous devrez peut-être porter une attention particulière aux activités qui sont ajoutées / supprimées à la backstack. Consultez cet article pour plus d'informations sur la manière de procéder.

pps Vous pouvez également oublier complètement l'interface de recherche standard et implémenter simplement une recherche simple dans un Fragmentcomme décrit dans l'article de Raghav ci-dessous .


@Alex, il est certainement possible d'implémenter l'interface de recherche Android standard à l'aide de fragments. Mais cela prend BEAUCOUP de travail ... :-)
Vinay S Shenoy

@VinaySShenoy ouais, je veux dire que tu devrais réimplémenter le tout SearchManagerpour Fragments, non? (ou quelque chose comme ça)
Alex Lockwood

1
Pour fournir des résultats de recherche, j'ai mis en œuvre quelque chose de similaire à ce que vous avez suggéré, en fournissant l'intention à l'activité qui la livre au bon fragment s'il est visible. La partie la plus difficile a été de remplir à nouveau le tableau des suggestions sur le chargement des fragments avec les bonnes données pour me permettre de gérer l'affichage des suggestions ainsi que de gérer la soumission de recherche et de cliquer sur les suggestions. Mais j'ai maintenant un bon cadre en place pour les futures applications .. :-)
Vinay S Shenoy

J'ai trouvé que c'était une meilleure réponse: stackoverflow.com/questions/6938952/... Cela permettra de "rechercher" à partir de Fragments. Certes, ce n'est pas le mécanisme de recherche officiel fourni par Google, mais cela fonctionne très bien.
Kyle Falconer

76

Voici l'exemple pour rechercher quelque chose à l'aide de fragments. J'espère que cela aide et c'est ce que vous recherchez:

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 a demandé une "interface de recherche standard", mais cela permet d'obtenir une simple "recherche" dans un Fragmentafin que je ne me plains pas. Félicitations! : P
Alex Lockwood

30
La prochaine fois, vous voudrez peut-être citer vos sources .
Adrian Monk

Voir création d'une interface de recherche sur le site du développeur. L'OP a demandé s'il était possible de créer un "fragment de recherche" qui fonctionne avec la recherche Android standard comme décrit dans la documentation.
Alex Lockwood

Quelques pièges: 1-L'utilisation d'une icône de recherche personnalisée ne fonctionne pas. 2-SearchView doit avoir un code de gestion, comme pour désactiver le contenu, gérer le retour, etc.
AlikElzin-kilaka

Dans mon cas, la onQueryTextChangeméthode n'est pas appelée.
Shajeel Afzal

57

Il est tout à fait possible de rechercher dans un fragment à l'aide de l'API ActionBar SearchView ActionView standard. Cela fonctionnera également avec Android 2.1 (niveau d'API 7) en utilisant les classes de support AppCompat v7.

Dans votre fragment:

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

Dans votre 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" />

Cela fonctionne très bien avec la nouvelle application ActionBarActivity v7, merci
Pelanes

1
en lisant la réponse acceptée, j'ai perdu espoir..les autres réponses sont complexes, j'ai lu votre réponse !!! Si simple! thats it ... merci beaucoup
MBH

2
Je pense que nous devons ajouter setHasOptionsMenu (true) dans onActivityCreated. Comme repéré par @MBH.
Raymond Lukanta le

2
@GowthamanM Utilisez simplement MenuItem.SHOW_AS_ACTION .... si vous le pouvez, AppCompat est obsolète sur les API ultérieures
David

1
Hey @GowthamanM, utilisez comme ceci: item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM); item.setActionView(searchView);
Rod Lima

15

Utilisation des classes de support AppCompat v7. Il suffit d' ajouter quelque chose à @ David solution de de @Rookie solution pour le faire fonctionner correctement de manière simple, voici mon code fragment:

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

J'ai ajouté le onActivityCreated, car sans appelersetHasOptionsMenu(true); le système ne saura pas que ce fragment doit interagir avec le menu.

puis j'ai supprimé la ligne inflater.inflate(R.menu.main, menu); car elle doublait les éléments de menu depuis que l'activité a gonflé un menu, puis Fragment a gonflé un autre menu

Merci à @David et @Rookie


7

Lorsque vous travaillez avec, Fragmentsvous devez toujours utiliser un Activitypour contrôler et affecter le fichier Fragments. Cela Activitypeut avoir une fonctionnalité de recherche comme avant.

Je suis récemment passé d'une application `` normale '' Activityà uneFragment application basée et la fonctionnalité de recherche a fonctionné de la même manière pour moi.

Avez-vous essayé de travailler dessus et n'y avez pas réussi? Si tel est le cas, donnez plus de détails dans votre question.

ÉDITER:

Si vous voulez avoir une recherche spécifique de fragment, ont tous vos Fragmentsétendre une interface MyFragmentavec une startSearchméthode, et votre Activityl » startSearchappel de la méthode du fragment courant startSearchde la méthode.


La condition était que la recherche Android soit limitée au fragment spécifique, et non à l'activité. Donc, non je ne l'avais pas essayé.
Blackbelt

Je ne l'ai pas encore essayé, mais cela ressemble exactement à ce que je recherche. J'ai un tiroir de navigation avec des fragments qui contiennent chacun des fonctionnalités de recherche non liées. Je ne veux pas contourner complètement le système de recherche Android, donc j'avais besoin de quelque chose comme ça.
Bassinator

5

Je pense que j'ai réussi: vous pouvez en fait utiliser des fragments et ajouter une icône de recherche à une barre d'action afin qu'une recherche soit possible à l'intérieur des fragments. L'astuce consiste à utiliser une barre d'action, une vue d'action, un écouteur, un chargeur et un adaptateur bien sûr.

Cela fonctionne plutôt bien même si cela contourne complètement le mécanisme de recherche de la plate-forme Android (mais cela pourrait être complété par un peu de travail pour trouver ce que @Alex Lockwood décrit et passer la recherche aux fragments). Il ne réagirait pas à une intention comme prévu dans le cas d'une activité, mais cela fonctionne: les utilisateurs peuvent rechercher à l'intérieur des fragments.

Voici le code:

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 de fragment SearchFragment (j'utilise 2 instances dans l'activité ci-dessus).

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

Le fichier xml pour le menu des fragments de recherche 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>

Et le fichier de mise en page 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>

Je tiens également à souligner que Jake Wharton a décidé de ne pas implémenter le SearchViewpour sa bibliothèque ActionBarSherlock en raison de sa complexité ( voir son commentaire ici ). Comme vous pouvez le voir (et comme je l'ai décrit dans ma réponse également), la mise en œuvre de la recherche d'Android est tout sauf triviale ... elle est enracinée dans le système sous-jacent, et cela rend même les bibliothèques tierces difficiles à écrire (et cela en dit long. .. Jake Wharton est comme le Chuck Norris des bibliothèques tierces!: D).
Alex Lockwood

Jetez un œil au SearchView.javacode source ici.
Alex Lockwood

2
Alex, il semble que Jake Wharton ait changé d'avis: twitter.com/JakeWharton/status/221169921235755009
Jose_GD

Ces deux fichiers xml sont-ils identiques?
Clocker

@Clocker, on dirait qu'ils le sont. Honnêtement, après 2 ans, je ne peux pas dire
Snicolas

5

Utilisez le ActionBaret SearchView. Vous pourrez gérer les recherches sans aucune connexion à l'activité. OnQueryTextListenerDéfinissez simplement un sur 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;
    }
});

Voir cet article pour plus de détails sur la recherche personnalisée.


3

d'autres solution ..... je n'aime pas ça. C'est plus facile pour moi, mais c'est mon idée, j'attends votre opinion

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

Fragment

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

Activité

 @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 Fragmentne peut pas exister en dehors d'un Activity, ni Fragmentêtre lié à un android.intent.action.SEARCHou à un autre intent-filter.

Donc, sans utiliser un Activitypour envelopper le Fragment, ce que vous demandez n'est pas possible.


1

En cas de fragments dans un ViewPager, je pourrais le faire en bloquant le bouton de recherche lorsque je ne suis pas sur le fragment où je veux donner une barre de recherche. Dans l'activité:

@Override
public boolean onSearchRequested() {

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

Et en cas d'absence de bouton de recherche physique, j'ai ajouté un élément d'action dans le fragment, qui déclenche ce code:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

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

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

1

J'ai trouvé une solution :) vous pouvez remplacer cette méthode (startActivity (Intent)) dans votre BaseActivity, puis vérifier si l'action est ACTION_SEARCH puis faire votre travail spécial: D

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

        }
    }

0

Oui c'est possible,

s'il vous plaît implémente la vue Recherche sur votre activité, 'onQueryTextChange' dans Activity écoutera également la recherche dans le fragment, vous pouvez vérifier la visibilité du fragment dans 'onQueryTextChange', s'il est visible, vous pouvez appeler votre méthode de recherche pour fragment, son fonctionnement parfait dans mon code

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.