Поиск в Android с помощью fragmentов

Кто-нибудь знает учебник или пример того, как реализовать стандартный интерфейс поиска Android с помощью Fragment s? Другими словами, можно ли разместить стандартный поиск с помощью SearchManager во fragmentе?

12 Solutions collect form web for “Поиск в Android с помощью fragmentов”

Короче говоря, вы не можете. Существует несколько причин, по которым создание интерфейса поиска внутри Fragment невозможно.

  1. При создании интерфейса, доступного для поиска, вы должны указать стандартную «поисковую активность» в манифесте Android. Как я уверен, вы знаете, Fragment не может существовать без родительской Activity и, таким образом, это разделение невозможно.

  2. Если вы уже уже выяснили № 1, я предполагаю, что вы задали этот вопрос в надежде на то, что там есть какой-то волшебный «хак», который может выполнить свою работу. Однако в документации указывается, что,

    Когда пользователь выполняет поиск в диалоговом окне поиска или виджетах, система запускает вашу операцию поиска и доставляет ее поисковый запрос в намерении с действием ACTION_SEARCH. Ваша поисковая активность извлекает запрос из запроса QUERY, затем выполняет поиск ваших данных и представляет результаты.

    Основная, внутренняя система, которая отвечает за предоставление результатов поиска, ожидает Activity , а не Fragment ; таким образом, реализация интерфейса поиска, который полностью не зависит от Activity невозможен, так как это потребует изменений самой базовой системы . Проверьте исходный код для classа SearchableInfo если вы мне не верите :).

При этом не кажется, что было бы слишком сложно достичь чего-то похожего на то, что вы описываете. Например, вы можете рассмотреть возможность реализации своей поисковой активности, чтобы она приняла намерение android.intent.action.SEARCH и (вместо того, чтобы сразу отображать результаты в ListView , например) передаст поисковый запрос вашему Fragment s. Например, рассмотрите следующую операцию поиска:

 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 как описано в сообщении Рагхава ниже .

Вот пример, чтобы найти что-то, используя fragmentы. Надеюсь, это поможет, и это то, что вы ищете:

 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 { // 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 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 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 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 с использованием стандартного API ActionView ActionView API ActionView. Это также вернется к Android 2.1 (API-уровень 7), также используя classы поддержки AppCompat v7.

В вашем fragmentе:

 @Override public void onCreateOptionsMenu (Menu menu, MenuInflater inflater){ inflater.inflate(R.menu.search, menu); MenuItem item = menu.findItem(R.id.action_search); SearchView sv = new SearchView(((YourActivity) getActivity()).getSupportActionBar().getThemedContext()); MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); MenuItemCompat.setActionView(item, sv); sv.setOnQueryTextListener(new OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { System.out.println("search query submit"); return false; } @Override public boolean onQueryTextChange(String newText) { System.out.println("tap"); return false; } }); } 

В вашем меню XML

  

Использование classов поддержки AppCompat v7. Просто добавив что-то к решению @David из решения @Rookie, чтобы он работал правильно простым способом, вот мой fragment кода:

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 , cuz без вызова setHasOptionsMenu(true); система не будет знать, что этот fragment должен взаимодействовать с меню.

затем я удалил линию inflater.inflate(R.menu.main, menu); потому что он удвоил пункты меню, так как Activity раздул меню, затем Fragment раздул другое меню

Благодаря @David и @Rookie

При работе с Fragments вам все равно необходимо использовать Activity для управления и назначения Fragments . Эта Activity может иметь функцию поиска по-прежнему.

Недавно я переключился с «нормального» приложения на основе Activity на приложение, основанное на Fragment , и функция поиска работала одинаково для меня.

Вы пробовали работать над этим, и не получилось? Если да, то дайте более подробную информацию в своем вопросе.

РЕДАКТИРОВАТЬ:

Если вы хотите иметь определенный fragment поиска, все ваши Fragments расширяют интерфейс MyFragment с помощью метода startSearch и startSearch метод startSearch вашего Activity для startSearch метода startSearch текущего fragmentа.

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

Это работает довольно хорошо, хотя он полностью обходит механизм поиска платформы Android (но его можно было бы завершить с некоторой работой, чтобы найти то, что описывает @Alex Lockwood и передает поиск fragmentам). Он не реагирует на намерение, как ожидалось, в случае активности, но он работает: пользователи могут выполнять поиск внутри fragmentов.

Вот код:

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 

Класс fragmentа SearchFragment (я использую 2 экземпляра внутри указанного выше действия).

 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 listData = new ArrayList(); 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 getData() { List listFilteredData = new ArrayList(); for( String string : listData ) { if( query == null || string.contains( query ) ) { listFilteredData.add( string ); } } return listFilteredData; }//met private class LoaderCallBacks implements LoaderCallbacks< List> { @Override public void onLoadFinished(Loader> loader, List listData) { adapter.setListData( listData ); }// met @Override public void onLoaderReset(Loader> listData) { adapter.setListData( new ArrayList() ); }// met @Override public Loader> onCreateLoader(int arg0, Bundle arg1) { return loader; }// met }//class private class StringAdapter extends ArrayAdapter< String > { private List listDataToDisplay = new ArrayList(); private LayoutInflater mInflater; public StringAdapter( List 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 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> { SearchFragment fragment = null; public StringLoader(Context context, SearchFragment fragment) { super(context); this.fragment = fragment; }// cons @Override public List loadInBackground() { return fragment.getData(); }// met }// class 

Файл xml для меню fragmentов поиска res / menu / menu_search.xml:

    

И файл макета xml res / layout / search_in_fragments.xml

    

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

См. Это сообщение для получения дополнительной информации о пользовательском поиске.

Fragment не может существовать вне Activity , и Fragment не может быть связан с android.intent.action.SEARCH или любым другим intent-filter .

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

В случае fragmentов в ViewPager я мог бы сделать это, заблокировав кнопку поиска, когда я не на fragmentе, где я хочу дать панель поиска. В деятельность:

 @Override public boolean onSearchRequested() { if (mPager.getCurrentItem() == mAdapter.getPosition(FragmentType.VIDEO)) return super.onSearchRequested(); else return false; } 

И в случае отсутствия физической кнопки поиска я добавил элемент действия во fragment, который запускает этот код:

 @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.search_item) { return getSherlockActivity().onSearchRequested(); } return super.onOptionsItemSelected(item); } 

Я нашел работу вокруг: вы можете переопределить этот метод (startActivity (Intent)) в своей BaseActivity, а затем проверить, является ли действие ACTION_SEARCH, а затем выполнить вашу специальную работу: D

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

другие решения ….. мне это не нравится. Это более легко для меня. Но это моя идея. Я жду твоего мнения

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

Acitivty

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

да его возможно,

пожалуйста, реализует поиск в вашей деятельности, «onQueryTextChange» в Activity также будет прослушивать поиск по fragmentу, вы можете проверить видимость fragmentа в «onQueryTextChange», если он отображается, вы можете вызвать ваш метод поиска для fragmentа, его работа отлично работает в моем коде

  • Проверьте, четное или нечетное число
  • Какую библиотеку OCR Java я должен использовать в Android?
  • Ошибка конструктора списка Firebase
  • Как получить частоту от результата fft?
  • Ошибка Java. Фактические и формальные списки аргументов различаются по длине
  • Как анализировать XML с помощью анализатора SAX
  • Почему получение Google Directions для Android с использованием данных KML больше не работает?
  • HashMap с несколькими значениями под одним и тем же ключом
  • ksoap2 org.xmlpull.v1.xmlpullparserexception Ожидаемая ошибка start_tag
  • Android HttpPost: как получить результат
  • Формат Float до n знаков после запятой
  • Interesting Posts

    FCM с Postman – в запросе отсутствовал ключ аутентификации (токен FCM)

    Изменение размера изображения без потери качества

    Очень низкая производительность: lexical_cast

    Как я могу поймать SIGSEGV (segmentation fault) и получить трассировку стека под JNI на Android?

    Какую информацию может видеть мой интернет-провайдер с моего маршрутизатора?

    Качество гарнитуры Bluetooth в качестве микрофона

    JQuery mouseenter () против mouseover ()

    Макрос диаграммы, отображающий неправильные метки из непересекающихся видимых строк на отфильтрованном листе

    Могу ли я навсегда запретить обновлениям безопасности Java от установки панели инструментов Yahoo?

    Можете ли вы переопределить определенные шаблоны в AngularUI Bootstrap?

    Удаление с панели управления отличается от удаления из .msi

    поддержка FragmentPagerAdapter содержит ссылку на старые fragmentы

    Как я могу получить виртуальные рабочие столы (например, Mac's Spaces) на моей машине с Windows 7?

    Копировать файлы в другую папку – найти

    Переименование жирового объема

    Давайте будем гением компьютера.