Wyszukiwanie w systemie Android z fragmentami

161

Czy ktoś zna samouczek lub przykład, jak zaimplementować standardowy interfejs wyszukiwania Androida za pomocą Fragments? Innymi słowy, czy można przeprowadzić standardowe wyszukiwanie z a SearchManagerwe fragmencie?

Czarny pas
źródło
Komu dałbyś premię @blackbelt? Raghav udzielił odpowiedzi, której szukałem. ale Alex LockWood odpowiedział również na pierwszą część twojego pytania.
Snicolas
Akceptuję odpowiedź LockWood. Przyznaj nagrodę, jak chcesz (myślę, że jest lepsza)
Blackbelt
4
Cieszę się, że otrzymaliśmy tak wiele poprawnych odpowiedzi i obejść! :)
Alex Lockwood
Czy ktoś może mi odpowiedzieć na to pytanie ..? Utknąłem tutaj stackoverflow.com/questions/10600660/…
Debiutant
1
Używam tej techniki, aby pozostać we fragmencie po dodaniu SearchView do paska akcji: stackoverflow.com/a/6939735/1068167 . Moja aplikacja nie jest jeszcze ukończona, ale mam nadzieję, że zadziała.
obejmuje

Odpowiedzi:

91

Krótko mówiąc, nie możesz. Istnieje kilka powodów, dla których utworzenie interfejsu wyszukiwania w ramach a Fragmentnie jest możliwe.

  1. Tworząc interfejs z możliwością wyszukiwania, w manifeście systemu Android należy określić domyślne „działanie z możliwością wyszukiwania”. Jak na pewno wiesz, Fragmentnie może istnieć bez rodzica, Activitya zatem ta separacja nie jest możliwa.

  2. Jeśli już wymyśliłeś numer 1, zakładam, że zadałeś to pytanie w nadziei, że istnieje jakiś magiczny „hack”, który może wykonać zadanie. Jednak dokumentacja stwierdza, że

    Gdy użytkownik przeprowadza wyszukiwanie w oknie dialogowym wyszukiwania lub w widgecie, system rozpoczyna działanie z możliwością wyszukiwania i dostarcza zapytanie wyszukiwania w intencji z akcją ACTION_SEARCH. Twoja aktywność z możliwością wyszukiwania pobiera zapytanie z dodatkowego QUERY intencji, a następnie przeszukuje dane i przedstawia wyniki.

    Podstawowy, wewnętrzny system odpowiedzialny za dostarczanie wyników wyszukiwania oczekuje Activity, a nie Fragment; w związku z tym wdrożenie interfejsu wyszukiwania, który jest całkowicie niezależny od systemu, Activitynie jest możliwe, ponieważ wymagałoby zmian w samym systemie bazowym . Sprawdź kod źródłowy SearchableInfozajęć, jeśli mi nie wierzysz :).

Biorąc to pod uwagę, nie wydaje się, że osiągnięcie czegoś podobnego do tego, co opisujesz, nie byłoby zbyt trudne. Na przykład możesz rozważyć zaimplementowanie swojego działania, które można przeszukiwać, tak aby zaakceptowało android.intent.action.SEARCHzamiar i (zamiast na przykład natychmiast wyświetlać wyniki w a ListView) przekaże zapytanie wyszukiwania do twojego Fragments. Na przykład rozważ następujące działanie z możliwością wyszukiwania:

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

Po wysłaniu żądania wyszukiwania system uruchomi Twoją możliwą do przeszukiwania aktywność, wykona zapytanie i przekaże wyniki do pewnego kontenera Działania (na podstawie Twojej implementacji doMySearch). Działanie kontenera przekaże następnie te wyniki do zawartego przeszukiwania Fragment, w którym zostaną wyświetlone wyniki. Wdrożenie wymaga trochę więcej pracy niż to, na co prawdopodobnie liczyłeś, ale jestem pewien, że istnieją sposoby na uczynienie jej bardziej modułową i wydaje się, że może to być najlepsze, co możesz zrobić.

ps Jeśli używasz tego podejścia, być może będziesz musiał zwrócić szczególną uwagę na to, które Aktywności są dodawane / usuwane z zaplecza. Zobacz ten post, aby uzyskać więcej informacji o tym, jak można to zrobić.

pps Możesz także całkowicie zapomnieć o standardowym interfejsie wyszukiwania i po prostu zaimplementować proste wyszukiwanie w ramach, Fragmentjak opisano w poście Raghava poniżej .

Alex Lockwood
źródło
@Alex, Zdecydowanie możliwe jest zaimplementowanie standardowego interfejsu wyszukiwania Androida przy użyciu fragmentów. Ale to wymaga dużo pracy ... :-)
Vinay S Shenoy
@VinaySShenoy yeah, mam na myśli, że musiałbyś ponownie zaimplementować cały SearchManagerfor Fragments, prawda? (lub coś w tym stylu)
Alex Lockwood
1
W celu dostarczania wyników wyszukiwania zaimplementowałem coś podobnego do tego, co zasugerowałeś, przekazując intencję do działania, która dostarcza ją do właściwego fragmentu, jeśli jest widoczny. Najtrudniejszą częścią było ponowne wypełnienie tabeli sugestii przy ładowaniu fragmentów odpowiednimi danymi, które pozwoliły mi obsłużyć wyświetlanie sugestii, a także obsługę wyszukiwania i klikania sugestii. Ale mam już fajny framework dla przyszłych aplikacji .. :-)
Vinay S Shenoy,
Uważam, że jest to lepsza odpowiedź: stackoverflow.com/questions/6938952/… To pozwoli na „wyszukiwanie” z poziomu Fragmentów. To prawda, że ​​nie jest to oficjalny mechanizm wyszukiwania udostępniany przez Google, ale działa dobrze.
Kyle Falconer,
76

Oto przykład wyszukiwania czegoś za pomocą fragmentów. Mam nadzieję, że to pomoże i właśnie tego szukasz:

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);
        }
    }
}
Rekrut
źródło
OP poprosił o „standardowy interfejs wyszukiwania”, ale w ten sposób można uzyskać proste „wyszukiwanie” w ramach, Fragmentwięc nie narzekałbym. Gratulacje! : P
Alex Lockwood
30
Następnym razem możesz zacytować swoje źródła .
Adrian Monk
Zobacz tworzenie interfejsu wyszukiwania w witrynie programisty. OP zapytał, czy jest możliwe utworzenie „przeszukiwalnego fragmentu”, który działa ze standardową wyszukiwarką systemu Android, jak opisano w dokumentacji.
Alex Lockwood
Niektóre pułapki: 1-Używanie niestandardowej ikony wyszukiwania nie działa. 2-SearchView musi mieć kod zarządzający, na przykład do wyłączania treści, obsługi z powrotem itp.
AlikElzin-kilaka
W moim przypadku onQueryTextChangemetoda nie jest wywoływana.
Shajeel Afzal
57

Wyszukiwanie w fragmencie jest całkiem możliwe przy użyciu standardowego interfejsu API ActionBar SearchView ActionView. Będzie to działać również z powrotem do systemu Android 2.1 (poziom interfejsu API 7) przy użyciu klas obsługi AppCompat v7.

W twoim fragmencie:

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

W swoim 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" />
David
źródło
Działa to świetnie z nowym ActionBarActivity appcompat v7, dzięki
Pelanes Kwietnia
1
czytając zaakceptowaną odpowiedź, straciłem nadzieję ... inne odpowiedzi są złożone, przeczytałem Twoją odpowiedź !!! Tak prosty! to wszystko ... dziękuję bardzo
MBH
2
Myślę, że musimy dodać setHasOptionsMenu (true) w onActivityCreated. Jak zauważył @MBH.
Raymond Lukanta
2
@GowthamanM Po prostu użyj MenuItem.SHOW_AS_ACTION .... jeśli możesz, AppCompat jest przestarzała w późniejszych interfejsach API
David,
1
Hej @GowthamanM, używaj w ten sposób:item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM); item.setActionView(searchView);
Rod Lima,
15

Korzystanie z klas obsługi AppCompat v7. Wystarczy dodać coś do @David roztworu „s od @Rookie rozwiązanie, aby uzyskać to działa prawidłowo w prosty sposób, oto mój fragment kodu:

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

Dodałem onActivityCreated, bo bez wywołania setHasOptionsMenu(true);systemu nie będzie wiedział, że ten fragment musi wejść w interakcję z menu.

następnie usunąłem linię, inflater.inflate(R.menu.main, menu);ponieważ podwoiła pozycje menu, ponieważ Aktywność zawyżała menu, a następnie Fragment zawęziło inne menu

Dzięki @David i @Rookie

MBH
źródło
7

Podczas pracy Fragmentsnadal musisz używać Activitydo kontrolowania i przypisywania plików Fragments. Może Activityto mieć funkcjonalność wyszukiwania, jak poprzednio.

Niedawno przerzuciłem się z „normalnej” Activityaplikacji na Fragmentaplikację opartą na aplikacji i funkcja wyszukiwania działała u mnie tak samo.

Czy próbowałeś nad tym pracować i nie udało się? Jeśli tak, podaj więcej szczegółów w swoim pytaniu.

EDYTOWAĆ:

Jeśli chcesz mieć wyszukać konkretny fragment, mieć wszystkie swoje Fragmentsrozszerzyć interfejs MyFragmentz startSearchmetodą i mają swoje Activity„s startSearchwywołanie metody bieżącego fragmentu jest startSearchmetoda.

marmor
źródło
Wymagano, aby wyszukiwanie Androida było ograniczone do określonego fragmentu, a nie do działania. Więc nie, nie próbowałem tego.
Blackbelt
Jeszcze tego nie próbowałem, ale brzmi to DOKŁADNIE to, czego szukam. Mam szufladę nawigacji z fragmentami, z których każdy zawiera niepowiązane funkcje wyszukiwania. Nie chcę całkowicie ominąć systemu wyszukiwania Androida, więc potrzebowałem czegoś takiego.
Bassinator
5

Myślę, że udało mi się to osiągnąć: faktycznie można użyć fragmentów i dodać ikonę wyszukiwania do paska akcji, aby wyszukiwanie było możliwe wewnątrz fragmentów. Sztuczka polega na użyciu paska akcji, widoku akcji, nasłuchiwania, programu ładującego i oczywiście adaptera.

Działa to całkiem nieźle, chociaż całkowicie omija mechanizm wyszukiwania platformy androida (ale można go uzupełnić trochę pracy, aby znaleźć to, co opisuje @Alex Lockwood i przekazać wyszukiwanie do fragmentów). Nie zareagowałoby na intencję zgodnie z oczekiwaniami w przypadku działania, ale działa: użytkownicy mogą przeszukiwać fragmenty.

Oto kod:

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

Klasa fragmentu SearchFragment (używam 2 instancji w ramach powyższej czynności).

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

Plik xml z menu fragmentów wyszukiwania 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>

Oraz plik układu xml res / layout / search_in_fragments.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="horizontal" >
    <FrameLayout
        android:id="@+id/fragment"
        android:layout_width="0px"
        android:layout_height="match_parent"
        android:layout_weight="1" />
</LinearLayout>
Snicolas
źródło
Chciałbym również zaznaczyć, że Jake Wharton zdecydował się nie implementować SearchViewbiblioteki ActionBarSherlock ze względu na jej złożoność ( zobacz jego komentarz tutaj ). Jak widać (i jak opisałem również w mojej odpowiedzi), implementacja wyszukiwania w Androidzie nie jest trywialna ... jest zakorzeniona w podstawowym systemie, co sprawia, że ​​nawet biblioteki innych firm są trudne do napisania (i to coś mówi. .. Jake Wharton jest jak Chuck Norris z bibliotek zewnętrznych!: D).
Alex Lockwood
Spójrz na SearchView.javakod źródłowy tutaj.
Alex Lockwood
2
Alex, wygląda na to, że Jake Wharton zmienił zdanie: twitter.com/JakeWharton/status/221169921235755009
Jose_GD
Czy oba te pliki XML są takie same?
Clocker
@Clocker, wygląda na to, że są. Szczerze mówiąc, po 2 latach nie mogę powiedzieć
Snicolas
5

Użyj ActionBari SearchView. Będziesz mógł obsługiwać wyszukiwania bez połączenia z działaniem. Wystarczy ustawić OnQueryTextListenerna 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;
    }
});

Więcej informacji na temat wyszukiwania niestandardowego można znaleźć w tym poście.

AlikElzin-kilaka
źródło
3

inne rozwiązania ..... nie podoba mi się to. To dla mnie łatwiejsze, ale to mój pomysł, czekam na twoją opinię

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

Aktywność

 @Override
public boolean onCreateOptionsMenu(Menu menu) {

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

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

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

        @Override
        public boolean onQueryTextChange(String newText) {
            return false;
        }
    });
    return super.onCreateOptionsMenu(menu);
}
Numan Turkeri
źródło
1

A Fragmentnie może istnieć poza Activityani ani nie może Fragmentbyć połączone z android.intent.action.SEARCHżadnym innym intent-filter.

Więc bez użycia znaku Activitydo owinięcia Fragment, to, o co prosisz, nie jest możliwe.

Louth
źródło
1

W przypadku fragmentów do ViewPager mógłbym to zrobić blokując przycisk wyszukiwania, gdy nie jestem na fragmencie, w którym chcę nadać pasek wyszukiwania. Do działania:

@Override
public boolean onSearchRequested() {

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

A w przypadku braku fizycznego przycisku wyszukiwania, dodałem do fragmentu element akcji, który wyzwala ten kod:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

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

        return getSherlockActivity().onSearchRequested();
    }
    return super.onOptionsItemSelected(item);
}
galex
źródło
1

znalazłem obejście :) możesz zastąpić tę metodę (startActivity (Intent)) w swojej BaseActivity, a następnie sprawdzić, czy akcja to ACTION_SEARCH, a następnie wykonaj swoją specjalną pracę: D

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

        }
    }
S. Alawadi
źródło
0

tak, to możliwe,

proszę zaimplementować widok wyszukiwania na swojej aktywności, 'onQueryTextChange' w Activity również nasłuchuje wyszukiwania we fragmencie, możesz sprawdzić widoczność fragmentu w 'onQueryTextChange', jeśli jest widoczny, możesz wywołać swoją metodę wyszukiwania dla fragmentu, działa idealnie w moim kodzie

Libin Thomas
źródło