Пошук Android з фрагментами


161

Хтось знає підручник або приклад того, як реалізувати стандартний пошуковий інтерфейс Android за допомогою Fragments? Іншими словами, чи можна поставити стандартний пошук за SearchManagerдопомогою фрагмента?


Хто б вам надав бонус @blackbelt? Рагав дав відповідь, яку я шукав. але Alex LockWood також відповів на першу частину вашого питання.
Snicolas

Я приймаю відповідь LockWood. Присуджуйте виграш, як вам подобається (я думаю, що краще)
Блекбелт

4
Я радий, що ми отримали таку різноманітність правильних відповідей та обходу! :)
Алекс Локвуд

Хтось може дати мені відповідь на це питання ..? Я застряг тут stackoverflow.com/questions/10600660/…
Rookie

1
Я використовую цю техніку , щоб залишитися в межах фрагмента після додавання SearchView до ActionBar: stackoverflow.com/a/6939735/1068167 . Моя заявка ще не зроблена, але, сподіваємось, вона спрацює.
проміжок часу

Відповіді:


91

Словом, ви не можете. Є кілька причин, через які створити інтерфейс пошуку в межах A Fragmentнеможливо.

  1. Створюючи інтерфейс для пошуку, ви повинні вказати за умовчанням "активність пошуку" у своєму маніфесті Android. Як я впевнений, ви знаєте, що Fragmentнеможливо існувати без батьків, Activityі, таким чином, поділ неможливе.

  2. Якщо ви вже розібралися з номером №1, я припускаю, що ви задали це запитання, сподіваючись, що там є якийсь магічний «злом», який зможе виконати роботу. Однак у документації зазначено, що:

    Коли користувач виконує пошук у діалоговому вікні пошуку або віджеті, система запускає пошукову діяльність і доставляє їй пошуковий запит у намірі з дією ACTION_SEARCH. Ваша пошукова діяльність отримує запит із додаткового ЗАПИТУВАННЯ наміру, потім здійснює пошук ваших даних та подає результати.

    Внутрішня система, яка відповідає за надання результатів пошуку, розраховує на Activity, а не на Fragment; таким чином, реалізація інтерфейсу пошуку, який повністю не залежить від даних Activity, неможлива, оскільки це вимагатиме змін у самій базовій системі . Перевірте вихідний код для SearchableInfoкласу, якщо ви мені не вірите :).

Коли це говориться, не здається, що було б занадто складно досягти чогось подібного до того, що ви описуєте. Наприклад, ви можете розглянути можливість здійснення своєї пошукової діяльності, щоб вона прийняла android.intent.action.SEARCHнаміри і (замість негайного відображення результатів у ListView, наприклад) передала пошуковий запит вашим Fragments. Наприклад, врахуйте таку діяльність, яку можна шукати:

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

Коли буде зроблено запит на пошук, система запустить вашу пошукову діяльність, виконає запит і передасть результати деяким контейнерам (на основі вашої реалізації doMySearch). Потім активність контейнера передасть ці результати у вміст пошуку Fragment, в якому результати будуть відображатися. Реалізація вимагає трохи більше роботи, ніж те, на що ви, напевно, сподівалися, але я впевнений, що є способи зробити її більш модульною, і здається, що це може бути найкращим, що ви можете зробити.

ps Якщо ви використовуєте цей підхід, вам, можливо, доведеться звернути особливу увагу на те, які види діяльності додаються / видаляються в запчастини. Дивіться цю публікацію для отримання додаткової інформації про те, як це можна зробити.

pps Ви також можете повністю забути про стандартний пошуковий інтерфейс і просто здійснити простий пошук у межах, Fragmentяк описано у публікації Рагава нижче .


@ Алекс, звичайно можна реалізувати стандартний інтерфейс пошуку Android, використовуючи фрагменти. Але потрібно багато роботи ... :-)
Vinay S Shenoy

@VinaySShenoy Так, я маю на увазі, вам доведеться повторно реалізувати цілі SearchManagerдля Fragmentправа? (чи щось подібне)
Alex Lockwood

1
Для надання результатів пошуку я реалізував щось подібне до того, що ви запропонували, передаючи намір діяльності, яка доставляє його до потрібного фрагмента, якщо він видно. Найскладнішою частиною було перенаселення таблиці пропозицій щодо завантаження фрагментів правильними даними, щоб я міг обробляти відображення пропозицій, а також обробляти подання пошуку та натискання пропозицій. Але в мене зараз є приємна основа для майбутніх додатків .. :-)
Vinay S Shenoy

Я вважаю це кращою відповіддю: stackoverflow.com/questions/6938952/… Це дозволить "здійснити пошук" з "Фрагментів". Щоправда, це не офіційний механізм пошуку, який надає Google, але він працює просто чудово.
Кайл Фальконер

76

Ось приклад пошуку чогось за допомогою фрагментів. Сподіваюся, що це допомагає, і ось що ви шукаєте:

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

ОП попросило "стандартний інтерфейс пошуку", але це досягає простого "пошуку" всередині, Fragmentтому я б не скаржився. Вітаю! : P
Алекс Локвуд

30
Наступного разу ви, можливо, захочете цитувати свої джерела .
Адріан Монк

Дивіться про створення пошукового інтерфейсу на сайті розробника. ОП запитала, чи можна створити "Фрагмент пошуку", який працює зі стандартним пошуком Android, як описано в документації.
Алекс Локвуд

Деякі підводні камені: 1-Використання налаштованого значка пошуку не працює. 2-SearchView повинен мати якийсь код управління, як-от вимкнення вмісту, обробку назад тощо.
AlikElzin-kilaka

У моєму випадку onQueryTextChangeметод не викликається.
Shajeel Afzal

57

Шукати за фрагментом цілком можливо за допомогою стандартного API ActionBar SearchView ActionView. Це також повернеться до Android 2.1 (API рівня 7), також використовуючи класи підтримки AppCompat v7.

У вашому фрагменті:

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

У вашому меню 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" />

Це чудово працює з новою програмою ActionBarActivity v7, спасибі
Pelanes

1
прочитавши прийняту відповідь, я втратив надію ... інші відповіді складні, я читаю вашу відповідь !!! Так просто! ось це ... велике спасибі
MBH

2
Я думаю, що ми повинні додати setHasOptionsMenu (true) в onActivityCreate. Як помітив @MBH.
Реймонд Луканта

2
@GowthamanM Просто використовуйте MenuItem.SHOW_AS_ACTION .... якщо ви зможете, AppCompat застарілий у більш пізніх API
Девід,

1
Привіт @GowthamanM, використовуй так: item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM); item.setActionView(searchView);
Род Ліма

15

Використання класів підтримки AppCompat v7. Просто додати що - то до @David рішення «s з @Rookie розчину , щоб отримати його працювати належним чином в простій формі, ось мій фрагмент коду:

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

Я додав onActivityCreated, тому що без виклику setHasOptionsMenu(true);системи не знаю, що цей фрагмент повинен взаємодіяти з меню.

потім я видалив рядок, inflater.inflate(R.menu.main, menu);оскільки він подвоїв пункти меню, оскільки активність завищила меню, а потім фрагмент надув інше меню

Завдяки @David та @Rookie


7

Під час роботи з Fragmentsвами все одно потрібно використовувати Activityконтрольний та призначаючий Fragments. Це Activityможе мати функцію пошуку, як і раніше.

Нещодавно я перейшов з "звичайного" Activityдодатка на Fragmentбазованого, і функція пошуку для мене працювала так само.

Ви спробували працювати над цим, і вам це не вдалося? Якщо так, дайте детальніше у вашому запитанні.

Редагувати:

Якщо ви хочете , щоб пошук фрагмента конкретного, всі ваші Fragmentsрозширення інтерфейсу MyFragmentз startSearchметодом, і ваш Activity«s startSearchвиклик методу поточного фрагментом startSearchметод.


Вимога полягала в тому, щоб пошук андроїда був обмежений конкретним фрагментом, а не діяльністю. Отже, ні, я цього не пробував.
Блекбелт

Я ще не пробував цього, але це звучить як ТОЧНО те, що я шукаю. У мене є навігаційна скринька з фрагментами, кожен з яких містить непов'язані функції пошуку. Я не хочу повністю обходити пошукову систему Android, тому мені було потрібно щось подібне.
Басинатор

5

Я думаю, що я досяг цього: ви можете фактично використовувати фрагменти та додати значок пошуку до панелі дій, щоб пошук був можливий всередині фрагментів. Хитрість полягає у використанні панелі дій, перегляду дій, слухача для неї, завантажувача та адаптера, звичайно.

Це працює досить добре, хоча повністю обходить механізм пошуку платформи Android (але це може бути доповнено деякою роботою, щоб знайти те, що описує @Alex Lockwood та передати пошук фрагментам). Він би не реагував на наміри, як очікувалося у випадку діяльності, але він працює: користувачі можуть шукати всередині фрагментів.

Ось код:

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

Клас фрагмента SearchFragment (я використовую два екземпляри всередині активності вище).

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

XML-файл для меню фрагментів пошуку 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>

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

Я також хотів би зазначити, що Джейк Уортон вирішив не застосовувати SearchViewсвою бібліотеку ActionBarSherlock через її складність ( дивіться його коментар тут ). Як ви бачите (і як я вже описав у своїй відповіді), реалізація пошуку Android - це не що інше, як банальне ... вона вбудована в основній системі, і це навіть важко записувати навіть сторонні бібліотеки (і це щось говорить. .. Джейк Уортон - це як Чак Норріс з третіх партійних бібліотек!: D).
Алекс Локвуд

Погляньте на SearchView.javaвихідний код тут.
Алекс Локвуд

2
Алекс, здається, Джейк Уортон передумав: twitter.com/JakeWharton/status/221169921235755009
Jose_GD

Чи обидва ці xml файли однакові?
Годинник

@Clocker, схоже, що вони є. Чесно кажучи, через 2 роки я не можу сказати
Snicolas

5

Використовуйте ActionBarі SearchView. Ви зможете обробляти пошукові запити без підключення до Діяльності. Просто встановіть 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;
    }
});

Дивіться цю публікацію, щоб отримати докладнішу інформацію про користувацький пошук.


3

інші рішення ..... я не люблю це. Це більш просто для мене. Але його моя ідея. Я чекаю вашої думки

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

Фрагмент

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

Активність

 @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

Не Fragmentможе існувати за межами Activity, а також не може Fragmentбути пов'язане з тим android.intent.action.SEARCHчи іншим intent-filter.

Тож без використання Activityобертання Fragment, те, що ви просите, неможливо.


1

У випадку з фрагментами у ViewPager, я міг би це зробити, блокуючи кнопку пошуку, коли я не на фрагменті, де я хочу надати панель пошуку. До діяльності:

@Override
public boolean onSearchRequested() {

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

І якщо немає кнопки фізичного пошуку, я додав у фрагмент пункт дії, який запускає цей код:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

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

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

1

я знайшов собі роботу :) Ви можете переосмислити цей метод (startActivity (Намір)) у своїй BaseActivity, а потім перевірити, чи дія ACTION_SEARCH, то виконайте свою спеціальну роботу: D

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

        }
    }

0

так можливо,

будь ласка, реалізує перегляд пошуку щодо вашої активності, "onQueryTextChange" у "Активність" також прослухає пошук у фрагменті, ви можете перевірити видимість фрагмента у "onQueryTextChange", якщо він видно, ви можете назвати спосіб пошуку фрагмента, його працює ідеально в моєму коді

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.