Pencarian Android dengan Fragmen

161

Apakah ada yang tahu tutorial atau contoh tentang bagaimana mengimplementasikan antarmuka pencarian Android standar dengan Fragments? Dengan kata lain, apakah mungkin untuk menempatkan pencarian standar dengan SearchManagerdalam Fragmen?

Sabuk hitam
sumber
Siapa yang akan Anda berikan bonus ke @blackbelt? Raghav memberikan jawaban yang saya cari. tetapi Alex LockWood juga menjawab bagian pertama dari pertanyaan Anda.
Snicolas
Saya menerima jawaban LockWood. Berikan hadiah yang Anda inginkan (saya pikir lebih baik)
Blackbelt
4
Saya senang kami akhirnya mendapatkan berbagai jawaban dan solusi yang benar! :)
Alex Lockwood
Adakah yang bisa memberi saya jawaban untuk pertanyaan ini ..? Saya terjebak di sini stackoverflow.com/questions/10600660/…
Rookie
1
Saya menggunakan teknik ini untuk tetap berada dalam fragmen setelah menambahkan SearchView ke actionbar: stackoverflow.com/a/6939735/1068167 . Aplikasi saya belum selesai tetapi semoga akan berhasil.
span

Jawaban:

91

Singkatnya, kamu tidak bisa. Ada beberapa alasan mengapa membuat antarmuka pencarian dalam a Fragmenttidak dimungkinkan.

  1. Saat membuat antarmuka yang dapat ditelusuri, Anda harus menentukan "aktivitas yang dapat dicari" default di manifes Android Anda. Seperti yang saya yakin Anda tahu, suatu Fragmenttidak dapat ada tanpa orangtua Activitydan dengan demikian, pemisahan ini tidak mungkin.

  2. Jika Anda sudah menemukan # 1, saya berasumsi Anda mengajukan pertanyaan ini dengan harapan bahwa ada beberapa "hack" ajaib di luar sana yang dapat menyelesaikan pekerjaan. Namun, dokumentasi menyatakan bahwa,

    Saat pengguna menjalankan pencarian dalam dialog atau widget pencarian, sistem memulai aktivitas yang dapat dicari dan mengirimkannya permintaan pencarian dalam Intent dengan tindakan ACTION_SEARCH. Aktivitas Anda yang dapat ditelusuri mengambil kueri dari maksud QUERY ekstra, lalu mencari data Anda dan menyajikan hasilnya.

    Sistem internal yang mendasarinya yang bertanggung jawab untuk menyediakan hasil pencarian mengharapkan Activity, bukan Fragment; dengan demikian, mengimplementasikan antarmuka pencarian yang sepenuhnya independen dari suatu Activitytidak mungkin, karena akan memerlukan perubahan pada sistem yang mendasarinya itu sendiri . Lihat kode sumber untuk SearchableInfokelas jika Anda tidak percaya saya :).

Meski begitu, sepertinya tidak terlalu sulit untuk mencapai sesuatu yang mirip dengan apa yang Anda gambarkan. Misalnya, Anda dapat mempertimbangkan untuk menerapkan Kegiatan yang dapat ditelusuri sehingga akan menerima android.intent.action.SEARCHmaksud dan (alih-alih segera menampilkan hasil dalam ListView, misalnya) akan meneruskan kueri penelusuran ke milik Anda Fragment. Misalnya, pertimbangkan Aktivitas yang dapat dicari berikut:

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

Ketika permintaan pencarian dibuat, sistem akan meluncurkan aktivitas yang dapat dicari, melakukan kueri, dan akan meneruskan hasilnya ke beberapa aktivitas kontainer (berdasarkan pada implementasi Anda doMySearch). Kegiatan wadah kemudian akan meneruskan hasil ini ke pencarian yang terkandung Fragment, di mana hasilnya akan ditampilkan. Implementasinya membutuhkan kerja yang sedikit lebih banyak daripada yang mungkin Anda harapkan, tapi saya yakin ada cara yang dapat Anda lakukan untuk membuatnya lebih modular, dan sepertinya ini mungkin yang terbaik yang dapat Anda lakukan.

ps Jika Anda menggunakan pendekatan ini, Anda mungkin harus memberi perhatian khusus pada Kegiatan mana yang ditambahkan / dihapus ke backstack. Lihat posting ini untuk informasi lebih lanjut tentang bagaimana hal ini dapat dilakukan.

pps Anda mungkin juga lupa tentang antarmuka pencarian standar sepenuhnya dan hanya menerapkan pencarian sederhana dalam Fragmentseperti yang dijelaskan dalam posting Raghav di bawah ini .

Alex Lockwood
sumber
@Alex, Sangat mungkin untuk mengimplementasikan antarmuka pencarian Android standar menggunakan fragmen. Tapi itu BANYAK pekerjaan ... :-)
Vinay S Shenoy
@VinaySShenoy ya, maksud saya Anda harus menerapkan kembali seluruh SearchManageruntuk Fragmentbenar? (atau semacamnya)
Alex Lockwood
1
Untuk memberikan Hasil Pencarian, saya telah menerapkan sesuatu yang mirip dengan yang Anda sarankan, memberikan maksud untuk Aktivitas yang mengirimkannya ke fragmen yang tepat jika itu terlihat. Bagian tersulit adalah mengisi kembali Tabel Saran pada beban fragmen dengan data yang tepat untuk membiarkan saya menangani menampilkan saran serta menangani pengiriman pencarian dan mengklik saran. Tapi saya punya kerangka kerja yang bagus untuk aplikasi masa depan sekarang .. :-)
Vinay S Shenoy
Saya menemukan ini sebagai jawaban yang lebih baik: stackoverflow.com/questions/6938952/… Ini akan memungkinkan "pencarian" dari dalam Fragmen. Benar, ini bukan mekanisme pencarian resmi yang disediakan oleh Google, tetapi ini berfungsi dengan baik.
Kyle Falconer
76

Ini adalah contoh untuk mencari sesuatu menggunakan fragmen. Semoga ini bisa membantu dan inilah yang Anda cari:

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);
        }
    }
}
Calon
sumber
OP meminta "antarmuka pencarian standar", tetapi ini mencapai "pencarian" sederhana di dalam Fragmentjadi saya tidak akan mengeluh. Selamat! : P
Alex Lockwood
30
Lain kali Anda mungkin ingin mengutip sumber Anda .
Adrian Monk
Lihat membuat antarmuka pencarian di situs pengembang. OP bertanya apakah mungkin untuk membuat "fragmen yang dapat dicari" yang berfungsi dengan pencarian Android standar seperti yang dijelaskan dalam dokumentasi.
Alex Lockwood
Beberapa jebakan: 1-Menggunakan ikon pencarian khusus tidak berfungsi. 2-SearchView perlu memiliki beberapa kode manajemen, seperti untuk menonaktifkan konten, menangani kembali, dll.
AlikElzin-kilaka
Dalam onQueryTextChangemetode kasus saya tidak dipanggil.
Shajeel Afzal
57

Sangat mungkin untuk mencari dalam sebuah fragmen menggunakan API ActionViewar ActionView ActionView standar. Ini akan bekerja kembali ke Android 2.1 (API level 7) juga menggunakan kelas dukungan AppCompat v7.

Dalam fragmen Anda:

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

Dalam XML menu Anda

<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
sumber
Ini berfungsi baik dengan ActionBarActivity appcompat v7 yang baru, terima kasih
Pelanes
1
membaca jawaban yang diterima, saya kehilangan harapan .. jawaban lain yang kompleks, saya membaca jawaban Anda !!! Sangat sederhana! itu saja ... terima kasih banyak
MBH
2
Saya pikir kita harus menambahkan setHasOptionsMenu (true) di onActivityCreated. Seperti yang terlihat oleh @MBH.
Raymond Lukanta
2
@GowthamanM Cukup gunakan MenuItem.SHOW_AS_ACTION .... jika Anda dapat, AppCompat tidak digunakan lagi di API selanjutnya
David
1
Hey @GowthamanM, gunakan seperti ini: item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM); item.setActionView(searchView);
Rod Lima
15

Menggunakan kelas dukungan AppCompat v7. Hanya menambahkan sesuatu untuk @ David solusi 's dari @Rookie solusi untuk mendapatkannya bekerja dengan baik dengan cara yang sederhana, di sini adalah kode fragmen saya:

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

Saya menambahkan onActivityCreated, cuz tanpa memanggil setHasOptionsMenu(true);sistem tidak akan tahu bahwa fragmen ini perlu berinteraksi dengan menu.

kemudian saya menghapus baris inflater.inflate(R.menu.main, menu);karena menggandakan item menu sejak Activity menggembungkan menu, lalu Fragment menggelembungkan menu lain

Terima kasih kepada @David dan @Rookie

MBH
sumber
7

Saat bekerja dengan FragmentsAnda masih perlu menggunakan Activityuntuk mengontrol dan menetapkan Fragments. Ini Activitydapat memiliki fungsi pencarian seperti sebelumnya.

Saya baru-baru ini beralih dari Activityaplikasi berbasis 'normal' , ke Fragmentaplikasi berbasis dan fungsi pencarian bekerja sama untuk saya.

Sudahkah Anda mencoba mengerjakannya, dan tidak berhasil? Jika demikian, berikan lebih banyak detail dalam pertanyaan Anda.

EDIT:

Jika Anda ingin memiliki pencarian fragmen tertentu, memiliki semua Anda Fragmentsmemperpanjang sebuah antarmuka MyFragmentdengan startSearchmetode, dan memiliki Anda Activity's startSearchmetode panggilan fragmen saat ini startSearchmetode.

marmor
sumber
Syaratnya adalah bahwa pencarian android terikat pada fragmen spesifik, bukan pada aktivitas. Jadi, tidak, saya belum mencobanya.
Blackbelt
Saya belum mencobanya, tapi ini kedengarannya PERSIS apa yang saya cari. Saya memiliki laci navigasi dengan fragmen yang masing-masing berisi fitur pencarian yang tidak terkait. Saya tidak ingin mem-bypass sistem pencarian android sepenuhnya, jadi saya perlu sesuatu seperti ini.
Bassinator
5

Saya rasa saya mencapainya: Anda benar-benar dapat menggunakan fragmen dan menambahkan ikon pencarian ke panel tindakan sehingga pencarian dimungkinkan di dalam fragmen. Caranya adalah dengan menggunakan panel tindakan, tampilan tindakan, pendengar untuk itu, loader dan adaptor tentunya.

Ini bekerja cukup baik meskipun sepenuhnya mem-bypass mekanisme pencarian platform android (tetapi bisa diselesaikan dengan beberapa pekerjaan untuk menemukan apa yang dijelaskan oleh @Alex Lockwood dan meneruskan pencarian ke fragmen). Itu tidak akan bereaksi terhadap maksud seperti yang diharapkan dalam kasus suatu kegiatan, tetapi berfungsi: pengguna dapat mencari di dalam fragmen.

Ini kodenya:

CariInFragmentAktivitas

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

SearchFragment kelas fragmen (saya menggunakan 2 contoh di dalam aktivitas di atas).

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

File xml untuk menu res fragmen pencarian / 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>

Dan file tata letak xml res / tata letak / 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
sumber
Saya juga ingin menunjukkan bahwa Jake Wharton memutuskan untuk tidak mengimplementasikan SearchViewperpustakaan ActionBarSherlock karena kerumitannya ( lihat komentarnya di sini ). Seperti yang Anda lihat (dan seperti yang saya jelaskan dalam jawaban saya juga), implementasi pencarian Android sama sekali tidak penting ... itu sudah tertanam dalam sistem yang mendasarinya, dan ini membuat bahkan perpustakaan pihak ke-3 sulit untuk menulis (dan itu mengatakan sesuatu. .. Jake Wharton seperti Chuck Norris dari perpustakaan pihak ke-3!: D).
Alex Lockwood
Lihatlah SearchView.javakode sumber di sini.
Alex Lockwood
2
Alex, sepertinya Jake Wharton berubah pikiran: twitter.com/JakeWharton/status/221169921235755009
Jose_GD
Apakah kedua file xml ini sama?
Clocker
@ Locker, sepertinya mereka. Jujur, setelah 2 tahun saya tidak bisa mengatakan
Snicolas
5

Gunakan ActionBardan SearchView. Anda akan dapat menangani pencarian tanpa koneksi ke Activity. Cukup atur sebuah OnQueryTextListenerke 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;
    }
});

Lihat posting ini untuk detail lebih lanjut tentang pencarian kustom.

AlikElzin-kilaka
sumber
3

solusi lain ..... saya tidak suka itu. Ini lebih mudah bagi saya. Tapi itu ide saya. Saya menunggu pendapat Anda

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

Pecahan

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

Kegiatan

 @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
sumber
1

A Fragmenttidak dapat eksis di luar Activity, juga tidak dapat Fragmentdikaitkan dengan android.intent.action.SEARCHatau yang lain intent-filter.

Jadi tanpa menggunakan Activityuntuk membungkus Fragment, apa yang Anda minta tidak mungkin.

Mulut
sumber
1

Dalam hal Fragmen menjadi ViewPager, saya bisa melakukannya dengan memblokir tombol pencarian ketika saya tidak berada di fragmen tempat saya ingin memberikan bilah pencarian. Ke dalam kegiatan:

@Override
public boolean onSearchRequested() {

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

Dan jika tidak ada tombol pencarian fisik, saya menambahkan item tindakan ke dalam fragmen, yang memicu kode ini:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

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

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

saya menemukan pekerjaan sekitar :) Anda dapat mengganti metode ini (startActivity (Intent)) di BaseActivity Anda dan kemudian memeriksa apakah tindakannya ACTION_SEARCH kemudian lakukan pekerjaan khusus Anda: D

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

        }
    }
S. Alawadi
sumber
0

iya itu mungkin,

tolong terapkan tampilan Pencarian pada Aktivitas Anda, 'onQueryTextChange' di Activity juga akan mendengarkan pencarian dalam fragmen, Anda dapat memeriksa visibilitas fragmen di 'onQueryTextChange', jika terlihat Anda dapat memanggil metode pencarian untuk fragmen, itu berfungsi sempurna dalam kode saya

Libin Thomas
sumber