Android-Suche mit Fragmenten


161

Kennt jemand ein Tutorial oder ein Beispiel für die Implementierung der Standard- Android-Suchoberfläche mit Fragments? Mit anderen Worten, ist es möglich, eine Standardsuche mit a SearchManagerin ein Fragment einzufügen?


Wen würden Sie @blackbelt den Bonus gewähren? Raghav gab die Antwort, die ich suchte. Alex LockWood hat aber auch den ersten Teil Ihrer Frage beantwortet.
Snicolas

Ich akzeptiere die Antwort von LockWood. Vergeben Sie das Kopfgeld, wie Sie möchten (ich denke, es ist besser)
Blackbelt

4
Ich bin froh, dass wir so viele richtige Antworten und Problemumgehungen erhalten haben! :)
Alex Lockwood

Kann mir jemand die Antwort auf diese Frage geben ..? Ich stecke hier fest stackoverflow.com/questions/10600660/…
Rookie

1
Ich verwende diese Technik, um innerhalb des Fragments zu bleiben, nachdem ich die Suchansicht zur Aktionsleiste hinzugefügt habe: stackoverflow.com/a/6939735/1068167 . Meine Bewerbung ist noch nicht fertig, aber hoffentlich funktioniert es.
Spanne

Antworten:


91

Kurz gesagt, Sie können nicht. Es gibt mehrere Gründe, warum das Erstellen einer Suchoberfläche innerhalb von a Fragmentnicht möglich ist.

  1. Wenn Sie eine durchsuchbare Oberfläche erstellen, müssen Sie in Ihrem Android-Manifest eine standardmäßige "durchsuchbare Aktivität" angeben. Wie Sie sicher wissen, Fragmentkann a ohne einen Elternteil nicht existieren Activityund daher ist diese Trennung nicht möglich.

  2. Wenn Sie bereits die Nummer 1 herausgefunden haben, haben Sie diese Frage vermutlich in der Hoffnung gestellt, dass es da draußen einen magischen "Hack" gibt, der die Arbeit erledigen kann. In der Dokumentation heißt es jedoch:

    Wenn der Benutzer eine Suche im Suchdialog oder Widget ausführt, startet das System Ihre durchsuchbare Aktivität und übermittelt ihr die Suchabfrage in einer Absicht mit der Aktion ACTION_SEARCH. Ihre durchsuchbare Aktivität ruft die Abfrage aus der zusätzlichen Abfrage der Absicht ab, durchsucht dann Ihre Daten und zeigt die Ergebnisse an.

    Das zugrunde liegende interne System, das für die Bereitstellung der Suchergebnisse verantwortlich ist, erwartet ein Activity, kein Fragment; Daher ist die Implementierung einer Suchschnittstelle, die völlig unabhängig von einer Activityist, nicht möglich, da Änderungen am zugrunde liegenden System selbst erforderlich wären . Überprüfen Sie den Quellcode für die SearchableInfoKlasse, wenn Sie mir nicht glauben :).

Abgesehen davon scheint es nicht zu schwierig zu sein, etwas Ähnliches wie das zu erreichen, was Sie beschreiben. Sie könnten beispielsweise in Betracht ziehen, Ihre durchsuchbare Aktivität so zu implementieren, dass sie die android.intent.action.SEARCHAbsicht akzeptiert und (anstatt ListViewbeispielsweise die Ergebnisse sofort in a anzuzeigen ) die Suchabfrage an Ihre Fragments weiterleitet. Betrachten Sie beispielsweise die folgende durchsuchbare Aktivität:

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

Wenn eine Suchanforderung gestellt wird, startet das System Ihre durchsuchbare Aktivität, führt die Abfrage durch und leitet die Ergebnisse an eine Containeraktivität weiter (basierend auf Ihrer Implementierung von doMySearch). Die Containeraktivität übergibt diese Ergebnisse dann an die enthaltene durchsuchbare Datei Fragment, in der die Ergebnisse angezeigt werden. Die Implementierung erfordert etwas mehr Arbeit als Sie wahrscheinlich erhofft hatten, aber ich bin sicher, dass es Möglichkeiten gibt, sie modularer zu gestalten, und es scheint, dass dies das Beste ist, was Sie tun können.

ps Wenn Sie diesen Ansatz verwenden, müssen Sie möglicherweise besonders darauf achten, welche Aktivitäten zum Backstack hinzugefügt / daraus entfernt werden. In diesem Beitrag finden Sie weitere Informationen dazu.

pps Sie können auch die Standardsuchoberfläche vollständig vergessen und einfach eine einfache Suche in a implementieren, Fragmentwie in Raghavs Beitrag unten beschrieben .


@Alex, Es ist definitiv möglich, die Standard-Android-Suchoberfläche mithilfe von Fragmenten zu implementieren. Aber es braucht viel Arbeit ... :-)
Vinay S Shenoy

@VinaySShenoy Ja, ich meine, du müsstest das Ganze SearchManagerfür Fragments neu implementieren, oder? (oder so ähnlich)
Alex Lockwood

1
Für die Bereitstellung von Suchergebnissen habe ich etwas Ähnliches implementiert, wie Sie es vorgeschlagen haben, und die Absicht an die Aktivität übergeben, die es an das richtige Fragment liefert, wenn es sichtbar ist. Am schwierigsten war es, die Vorschlags-Tabelle beim Laden von Fragmenten mit den richtigen Daten neu zu füllen, damit ich Vorschläge anzeigen sowie die Suche einreichen und auf Vorschläge klicken kann. Aber ich habe jetzt ein schönes Framework für zukünftige Apps eingerichtet .. :-)
Vinay S Shenoy

Ich fand dies eine bessere Antwort: stackoverflow.com/questions/6938952/… Dies ermöglicht das "Suchen" innerhalb von Fragmenten. Es ist zwar nicht der offizielle Suchmechanismus von Google, aber er funktioniert einwandfrei.
Kyle Falconer

76

Hier ist das Beispiel, um etwas mit Fragmenten zu suchen. Hoffe es hilft und das ist was Sie suchen:

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

Das OP fragte nach "Standard-Suchoberfläche", aber dies führt zu einer einfachen "Suche" innerhalb eines, Fragmentso dass ich mich nicht beschweren würde. Glückwunsch! : P
Alex Lockwood

30
Beim nächsten Mal möchten Sie vielleicht Ihre Quellen zitieren .
Adrian Monk

Siehe Erstellen einer Suchoberfläche auf der Website des Entwicklers. Das OP fragte, ob es möglich sei, ein "durchsuchbares Fragment" zu erstellen, das mit der in der Dokumentation beschriebenen Standard-Android-Suche funktioniert.
Alex Lockwood

Einige Fallstricke: 1-Die Verwendung eines benutzerdefinierten Suchsymbols funktioniert nicht. 2-SearchView benötigt einen Verwaltungscode, z. B. zum Deaktivieren des Inhalts, zum
Zurückverarbeiten

In meinem Fall wird die onQueryTextChangeMethode nicht aufgerufen.
Shajeel Afzal

57

Es ist durchaus möglich, in einem Fragment mit der Standard-ActionBar SearchView ActionView-API zu suchen. Dies funktioniert auch mit Android 2.1 (API-Level 7) unter Verwendung der AppCompat-Unterstützungsklassen v7.

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

In Ihrem 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" />

Dies funktioniert hervorragend mit der neuen ActionBarActivity Appcompat v7, danke
Pelanes

1
Beim Lesen der akzeptierten Antwort habe ich die Hoffnung verloren. Die anderen Antworten sind komplex. Ich habe Ihre Antwort gelesen. So einfach! das ist es ... vielen Dank
MBH

2
Ich denke, wir müssen setHasOptionsMenu (true) in onActivityCreated hinzufügen. Wie von @MBH entdeckt.
Raymond Lukanta

2
@ GowthamanM Verwenden Sie einfach MenuItem.SHOW_AS_ACTION .... wenn Sie in der Lage sind, ist der AppCompat auf späteren APIs veraltet
David

1
Hey @GowthamanM, verwenden Sie wie folgt: item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM); item.setActionView(searchView);
Rod Lima

15

Verwenden von AppCompat-Unterstützungsklassen v7. Fügen Sie einfach etwas zu @Davids Lösung von @Rookie hinzu , damit es auf einfache Weise ordnungsgemäß funktioniert. Hier ist mein Fragmentcode:

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

Ich fügte hinzu onActivityCreated, weil ohne anzurufensetHasOptionsMenu(true); das System , nicht weiß, dass dieses Fragment mit dem Menü interagieren muss.

dann habe ich die Leitung entfernt inflater.inflate(R.menu.main, menu); weil sie die Menüelemente verdoppelt hat, seit Aktivität ein Menü aufgeblasen hat, und Fragment ein anderes Menü aufgeblasen hat

Danke an @David und @Rookie


7

Wenn FragmentsSie mit arbeiten, müssen Sie immer noch ein verwenden Activity, um das zu steuern und zuzuweisen Fragments. Dies Activitykann wie zuvor Suchfunktionen haben.

Ich habe kürzlich von einer "normalen" ActivityApp zu einer Fragmentbasierten App gewechselt und die Suchfunktion hat bei mir genauso funktioniert.

Haben Sie versucht, daran zu arbeiten, und es ist Ihnen nicht gelungen? Wenn ja, geben Sie in Ihrer Frage etwas mehr Details an.

BEARBEITEN:

Wenn Sie eine fragmentspezifische Suche durchführen möchten, lassen Sie alle Fragmentseine Schnittstelle MyFragmentmit einer startSearchMethode erweitern und die Methode Ihres Activity's die startSearchMethode des aktuellen Fragments aufrufen startSearch.


Voraussetzung war, dass die Android-Suche an das spezifische Fragment und nicht an die Aktivität gebunden war. Also nein, ich hatte es nicht versucht.
Blackbelt

Ich habe es noch nicht ausprobiert, aber das klingt genau so, wie ich es suche. Ich habe eine Navigationsschublade mit Fragmenten, die jeweils nicht verwandte Suchfunktionen enthalten. Ich möchte das Android-Suchsystem nicht vollständig umgehen, also brauchte ich so etwas.
Bassinator

5

Ich glaube, ich habe es geschafft: Sie können tatsächlich Fragmente verwenden und einer Aktionsleiste ein Suchsymbol hinzufügen, damit eine Suche innerhalb der Fragmente möglich ist. Der Trick besteht darin, eine Aktionsleiste, eine Aktionsansicht, einen Listener, einen Loader und natürlich einen Adapter zu verwenden.

Dies funktioniert ziemlich gut, obwohl es den Suchmechanismus der Android-Plattform vollständig umgeht (aber es könnte mit einigen Arbeiten abgeschlossen werden, um herauszufinden, was @Alex Lockwood beschreibt, und die Suche an Fragmente weiterzuleiten). Es würde im Falle einer Aktivität nicht wie erwartet auf eine Absicht reagieren, aber es funktioniert: Benutzer können innerhalb von Fragmenten suchen.

Hier ist der 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

Die Fragmentklasse SearchFragment (ich verwende 2 Instanzen innerhalb der obigen Aktivität).

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

Die XML-Datei für das Menü der Suchfragmente 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>

Und die XML-Layoutdatei 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>

Ich möchte auch darauf hinweisen, dass Jake Wharton SearchViewaufgrund seiner Komplexität beschlossen hat, die für seine ActionBarSherlock-Bibliothek nicht zu implementieren ( siehe seinen Kommentar hier ). Wie Sie sehen können (und wie ich auch in meiner Antwort beschrieben habe), ist die Suchimplementierung von Android alles andere als trivial ... sie ist im zugrunde liegenden System verankert, und dies erschwert das Schreiben selbst von Bibliotheken von Drittanbietern (und das sagt etwas aus. .. Jake Wharton ist wie der Chuck Norris von Bibliotheken von Drittanbietern !: D).
Alex Lockwood

Schauen Sie sich hier den SearchView.javaQuellcode an.
Alex Lockwood

2
Alex, es scheint, Jake Wharton hat seine Meinung geändert: twitter.com/JakeWharton/status/221169921235755009
Jose_GD

Sind diese beiden XML-Dateien gleich?
Clocker

@Clocker, sieht aus wie sie sind. Ehrlich gesagt, nach 2 Jahren kann ich nicht sagen
Snicolas

5

Verwenden Sie das ActionBarund SearchView. Sie können Suchvorgänge ohne Verbindung zu Aktivität ausführen. OnQueryTextListenerStellen Sie einfach eine auf die Suchansicht.

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

In diesem Beitrag finden Sie weitere Informationen zur benutzerdefinierten Suche.


3

andere Lösung ..... das gefällt mir nicht. Das ist einfacher für mich. Aber es ist meine Idee. Ich warte auf deine Meinung

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

Aktivität

 @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 Fragmentkann nicht außerhalb eines existiert Activity, noch eine kann Fragmentmit einem verbunden sein , android.intent.action.SEARCHoder jede andere intent-filter.

Ohne ein Activityzum Umwickeln des zu verwenden, ist das Fragment, was Sie fragen, nicht möglich.


1

Bei Fragmenten in einem ViewPager kann ich die Suchschaltfläche blockieren, wenn ich mich nicht in dem Fragment befinde, in dem ich eine Suchleiste angeben möchte. In die Aktivität:

@Override
public boolean onSearchRequested() {

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

Und falls keine physische Suchschaltfläche vorhanden ist, habe ich dem Fragment ein Aktionselement hinzugefügt, das diesen Code auslöst:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

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

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

1

Ich habe eine Problemumgehung gefunden :) Sie können diese Methode (startActivity (Intent)) in Ihrer BaseActivity überschreiben und dann überprüfen, ob die Aktion ACTION_SEARCH ist, und dann Ihren speziellen Job ausführen: D.

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

        }
    }

0

Ja es ist möglich,

Bitte implementiert die Suchansicht für Ihre Aktivität. 'onQueryTextChange' in Aktivität überwacht auch die Suche in Fragmenten. Sie können die Fragmentsichtbarkeit in 'onQueryTextChange' überprüfen. Wenn sie sichtbar ist, können Sie Ihre Suchmethode für Fragment aufrufen. Sie funktioniert perfekt in meinem Code

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.