Tìm kiếm trên Android với Fragment


161

Có ai biết về một hướng dẫn hoặc một ví dụ về cách triển khai giao diện tìm kiếm Android tiêu chuẩn với Fragments không? Nói cách khác, có thể đặt một tìm kiếm tiêu chuẩn với SearchManagermột mảnh vỡ không?


Ai là người bạn sẽ trao phần thưởng cho @blackbelt? Raghav đã đưa ra câu trả lời mà tôi đang tìm kiếm. nhưng Alex LockWood cũng đã trả lời phần đầu tiên của câu hỏi của bạn.
Snicolas

Tôi chấp nhận câu trả lời của LockWood. Trao tiền thưởng như bạn muốn (tôi nghĩ là tốt hơn)
Blackbelt

4
Tôi rất vui vì cuối cùng chúng tôi đã nhận được rất nhiều câu trả lời đúng và cách giải quyết khác! :)
Alex Lockwood

Bất cứ ai có thể cho tôi câu trả lời cho câu hỏi này ..? Tôi bị kẹt ở đây stackoverflow.com/questions/10600660/ Mạnh
Rookie

1
Tôi đang sử dụng kỹ thuật này để ở trong phân đoạn sau khi thêm SearchView vào thanh hành động: stackoverflow.com/a/6939735/1068167 . Ứng dụng của tôi chưa được thực hiện nhưng hy vọng nó sẽ hoạt động.
kéo dài

Câu trả lời:


91

Nói tóm lại, bạn không thể. Có một vài lý do tại sao việc tạo giao diện tìm kiếm trong phạm vi Fragmentlà không thể.

  1. Khi tạo giao diện có thể tìm kiếm, bạn phải chỉ định "hoạt động có thể tìm kiếm" mặc định trong bảng kê khai Android của mình. Như tôi chắc chắn bạn biết, Fragmentkhông thể tồn tại mà không có cha mẹ Activityvà do đó, sự tách biệt này là không thể.

  2. Nếu bạn đã tìm ra # 1 rồi, tôi giả sử bạn đã hỏi câu hỏi này với hy vọng rằng có một "hack" kỳ diệu nào đó có thể hoàn thành công việc. Tuy nhiên, tài liệu nói rằng,

    Khi người dùng thực hiện tìm kiếm trong hộp thoại tìm kiếm hoặc tiện ích, hệ thống sẽ bắt đầu hoạt động tìm kiếm của bạn và cung cấp cho nó truy vấn tìm kiếm trong Ý định với hành động ACTION_SEARCH. Hoạt động có thể tìm kiếm của bạn lấy truy vấn từ mục QUẤT thêm của mục đích, sau đó tìm kiếm dữ liệu của bạn và trình bày kết quả.

    Hệ thống nội bộ cơ bản chịu trách nhiệm cung cấp kết quả tìm kiếm mong đợi Activity, chứ không phải a Fragment; do đó, việc thực hiện một giao diện tìm kiếm hoàn toàn độc lập với một giao diện Activitylà không thể, vì nó sẽ yêu cầu thay đổi hệ thống cơ bản . Kiểm tra mã nguồn của SearchableInfolớp nếu bạn không tin tôi :).

Điều đó đang được nói, có vẻ như sẽ không quá khó để đạt được một cái gì đó tương tự như những gì bạn đang mô tả. Chẳng hạn, bạn có thể xem xét triển khai Hoạt động có thể tìm kiếm của mình để nó sẽ chấp nhận android.intent.action.SEARCHý định và (thay vì hiển thị ngay kết quả trong một ListViewví dụ) sẽ chuyển truy vấn tìm kiếm đến Fragments của bạn . Ví dụ, hãy xem xét Hoạt động có thể tìm kiếm sau đây:

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

Khi yêu cầu tìm kiếm được thực hiện, hệ thống sẽ khởi chạy hoạt động tìm kiếm của bạn, thực hiện truy vấn và sẽ chuyển kết quả cho một số Hoạt động chứa (dựa trên việc bạn thực hiện doMySearch). Hoạt động của bộ chứa sau đó sẽ chuyển các kết quả này đến mục có thể tìm kiếm được Fragment, trong đó các kết quả sẽ được hiển thị. Việc triển khai đòi hỏi một chút công việc hơn những gì bạn có thể hy vọng, nhưng tôi chắc chắn có những cách bạn có thể làm cho nó trở nên mô đun hơn, và có vẻ như đây có thể là điều tốt nhất bạn có thể làm.

ps Nếu bạn sử dụng phương pháp này, bạn có thể phải đặc biệt chú ý đến những Hoạt động nào được thêm / xóa vào backstack. Xem bài đăng này để biết thêm thông tin về cách điều này có thể được thực hiện.

pps Bạn cũng có thể quên hoàn toàn giao diện tìm kiếm tiêu chuẩn và chỉ thực hiện tìm kiếm đơn giản trong phạm vi Fragmentnhư được mô tả trong bài đăng của Raghav bên dưới .


@Alex, Chắc chắn có thể triển khai giao diện tìm kiếm Android tiêu chuẩn bằng cách sử dụng các đoạn. Nhưng phải mất rất nhiều công việc ... :-)
Vinay S Shenoy

@VinaySShenoy yeah, ý tôi là bạn phải triển khai lại toàn bộ SearchManagercho Fragmentđúng không? (hoặc đại loại như thế)
Alex Lockwood

1
Để cung cấp Kết quả tìm kiếm, tôi đã triển khai một cái gì đó tương tự như những gì bạn đã đề xuất, phân phối ý định cho Hoạt động mang nó đến đúng đoạn nếu nó hiển thị. Phần khó nhất là lập lại Bảng gợi ý về tải mảnh với dữ liệu phù hợp để cho phép tôi xử lý hiển thị các đề xuất cũng như xử lý gửi tìm kiếm và nhấp vào đề xuất. Nhưng tôi đã có một khung công tác tốt cho các ứng dụng trong tương lai ngay bây giờ .. :-)
Vinay S Shenoy

Tôi thấy đây là một câu trả lời tốt hơn: stackoverflow.com/questions/6938952/ Khăn Điều này sẽ cho phép "tìm kiếm" từ trong Fragment. Đúng, đó không phải là cơ chế tìm kiếm chính thức do Google cung cấp, nhưng nó hoạt động rất tốt.
Kyle Falconer

76

Dưới đây là ví dụ để tìm kiếm một cái gì đó bằng cách sử dụng các đoạn. Hy vọng nó sẽ giúp và đây là những gì bạn đang tìm kiếm:

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

OP đã yêu cầu "giao diện tìm kiếm tiêu chuẩn", nhưng điều này đạt được một "tìm kiếm" đơn giản trong một Fragmentvì vậy tôi sẽ không phàn nàn. Chúc mừng! : P
Alex Lockwood

30
Lần tới bạn có thể muốn trích dẫn nguồn của bạn .
sư Adrian

Xem việc tạo giao diện tìm kiếm trên trang web của nhà phát triển. OP đã hỏi liệu có thể tạo ra một "mảnh có thể tìm kiếm" hoạt động với tìm kiếm Android tiêu chuẩn như được mô tả trong tài liệu hay không.
Alex Lockwood

Một số cạm bẫy: 1-Sử dụng biểu tượng tìm kiếm tùy chỉnh không hoạt động. 2-SearchView cần có một số mã quản lý, như để vô hiệu hóa nội dung, xử lý lại, v.v.
AlikElzin-kilaka

Trong trường hợp của tôi onQueryTextChangephương pháp không được gọi.
Shajeel Afzal

57

Bạn hoàn toàn có thể tìm kiếm trong một đoạn bằng cách sử dụng API ActionViewar ActionViewar tiêu chuẩn. Điều này cũng sẽ hoạt động trở lại Android 2.1 (API cấp 7) khi sử dụng các lớp hỗ trợ AppCompat v7.

Trong đoạn của bạn:

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

Trong menu XML của bạn

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

Điều này hoạt động rất tốt với ứng dụng ActionBarActivity mới v7, cảm ơn
Pelanes

1
đọc câu trả lời được chấp nhận, tôi mất hy vọng..các câu trả lời khác rất phức tạp, tôi đọc câu trả lời của bạn !!! Quá đơn giản! đó là ... cảm ơn bạn rất nhiều
MBH

2
Tôi nghĩ rằng chúng ta phải thêm setHasOptionsMothy (true) trong onActivityCreated. Như được phát hiện bởi @MBH.
Raymond Lukanta

2
@GowthamanM Chỉ cần sử dụng MenuItem.SHOW_AS_ACTION .... nếu bạn có thể AppCompat không dùng nữa trên các API sau
David

1
Xin chào @GowthamanM, sử dụng như thế này: item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM); item.setActionView(searchView);
Rod Lima

15

Sử dụng các lớp hỗ trợ AppCompat v7. Chỉ cần thêm một cái gì đó để @ David giải pháp 's từ @Rookie giải pháp để làm cho nó hoạt động đúng trong một cách đơn giản, đây là đoạn mã của tôi:

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

Tôi đã thêm onActivityCreated, vì không gọi setHasOptionsMenu(true);hệ thống sẽ không biết rằng đoạn này cần tương tác với menu.

sau đó tôi xóa dòng này inflater.inflate(R.menu.main, menu);vì nó nhân đôi các mục menu kể từ khi Activity làm tăng menu, sau đó Fragment làm tăng menu khác

Cảm ơn @David và @Rookie


7

Khi làm việc với Fragmentsbạn vẫn cần sử dụng một Activityđể điều khiển và gán Fragments. Điều này Activitycó thể có chức năng tìm kiếm như trước đây.

Gần đây tôi đã chuyển từ một Activityứng dụng dựa trên 'bình thường' sang một Fragmentứng dụng dựa trên và chức năng tìm kiếm hoạt động giống như tôi.

Bạn đã thử làm việc với nó, và không thành công? Nếu vậy cung cấp thêm một số chi tiết trong câu hỏi của bạn.

BIÊN TẬP:

Nếu bạn muốn có một tìm kiếm cụ thể của đoạn, hãy Fragmentsmở rộng tất cả giao diện của bạn MyFragmentbằng một startSearchphương thức và yêu Activitycầu startSearchphương thức của bạn gọi phương thức của đoạn hiện tại startSearch.


Yêu cầu là tìm kiếm Android bị ràng buộc vào đoạn cụ thể, không phải cho hoạt động. Vì vậy, không tôi đã không thử nó.
Blackbelt

Tôi chưa thử, nhưng điều này nghe có vẻ chính xác những gì tôi đang tìm kiếm. Tôi có một ngăn kéo điều hướng với các mảnh mà mỗi mảnh chứa các tính năng tìm kiếm không liên quan. Tôi không muốn bỏ qua hoàn toàn hệ thống tìm kiếm Android, vì vậy tôi cần một cái gì đó như thế này.
Bassinator

5

Tôi nghĩ rằng tôi đã đạt được nó: bạn thực sự có thể sử dụng các đoạn và thêm biểu tượng tìm kiếm vào một thanh hành động để có thể tìm kiếm bên trong các mảnh. Bí quyết là sử dụng một thanh hành động, một khung nhìn hành động, một người nghe cho nó, một trình tải và một bộ chuyển đổi tất nhiên.

Điều này hoạt động khá tốt mặc dù nó hoàn toàn bỏ qua cơ chế tìm kiếm nền tảng Android (nhưng nó có thể được hoàn thành với một số công việc để tìm những gì @Alex Lockwood mô tả và chuyển tìm kiếm thành các đoạn). Nó sẽ không phản ứng với một ý định như mong đợi trong trường hợp của một hoạt động, nhưng nó hoạt động: người dùng có thể tìm kiếm bên trong các mảnh vỡ.

Đây là mã:

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

Lớp SearchFragment (tôi sử dụng 2 trường hợp bên trong hoạt động ở trên).

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

Tệp xml cho menu của các đoạn tìm kiếm 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>

Và tệp bố cục 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>

Tôi cũng muốn chỉ ra rằng Jake Wharton đã quyết định không triển khai SearchViewthư viện ActionBarSherlock của mình do tính phức tạp của nó ( xem bình luận của anh ấy ở đây ). Như bạn có thể thấy (và như tôi đã mô tả trong câu trả lời của mình), việc triển khai tìm kiếm của Android là bất cứ điều gì ngoài tầm thường ... nó đã ăn sâu vào hệ thống cơ bản và điều này làm cho ngay cả các thư viện bên thứ 3 cũng khó viết (và điều đó nói lên điều gì đó. .. Jake Wharton giống như Chuck Norris của thư viện bên thứ 3 !: D).
Alex Lockwood

Hãy xem SearchView.javamã nguồn ở đây.
Alex Lockwood

2
Alex, có vẻ như Jake Wharton đã thay đổi quyết định: twitter.com/JakeWharton/status/221169921235755009
Jose_GD

Cả hai tập tin xml này có giống nhau không?
clocker

@Clocker, hình như là họ. Thành thật mà nói, sau 2 năm tôi không thể nói
Snicolas

5

Sử dụng ActionBarSearchView. Bạn sẽ có thể xử lý các tìm kiếm mà không có bất kỳ kết nối nào với Activity. Chỉ cần đặt một OnQueryTextListenerSearchView.

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

Xem bài đăng này để biết thêm chi tiết về tìm kiếm tùy chỉnh.


3

giải pháp khác ..... tôi không thích điều đó. Điều này dễ dàng hơn đối với tôi. Nhưng đó là ý tưởng của tôi. Tôi đang chờ ý kiến ​​của bạn

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

Miếng

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

Hoạt động

 @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 Fragmentkhông thể tồn tại bên ngoài một Activity, cũng không thể Fragmentliên kết với một android.intent.action.SEARCHhoặc bất kỳ khác intent-filter.

Vì vậy, không sử dụng một Activityđể bọc Fragment, những gì bạn yêu cầu là không thể.


1

Trong trường hợp Fragment vào ViewPager, tôi có thể làm điều đó bằng cách chặn nút tìm kiếm khi tôi không ở đoạn mà tôi muốn đưa ra thanh tìm kiếm. Vào hoạt động:

@Override
public boolean onSearchRequested() {

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

Và trong trường hợp không có nút tìm kiếm vật lý, tôi đã thêm một mục hành động vào đoạn, kích hoạt mã này:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

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

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

1

tôi đã tìm thấy một công việc xung quanh :) bạn có thể ghi đè phương thức này (startActivity (Intent)) trong BaseActivity của bạn và sau đó kiểm tra xem hành động đó có phải là ACTION_SEARCH không, sau đó thực hiện công việc đặc biệt của bạn: D

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

        }
    }

0

Vâng nó có thể,

vui lòng triển khai Chế độ xem tìm kiếm trên Hoạt động của bạn, 'onQueryTextChange' trong Hoạt động cũng sẽ lắng nghe tìm kiếm theo từng đoạn, bạn có thể kiểm tra mức độ hiển thị của đoạn trong 'onQueryTextChange', nếu nó hiển thị, bạn có thể gọi phương thức tìm kiếm của mình để tìm đoạn mã, nó hoạt động hoàn hảo trong mã của tôi

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.