Как использовать onQueryTextChange со многими фрагментами
у меня есть много фрагментов, они показаны в разделе 2 макетов с помощью FragmentStatePagerAdapter
в каждом фрагменте есть представление Recycler, и я хочу использовать строку поиска в строке приложения для фильтрации результатов.
сначала я сделал это с помощью onQueryTextChange listener
в onCreateOptionsMenu и он отлично работал с парой фрагментов, но когда я добавил реализацию к другим фрагментам (просто ctrl+c и ctrl+v), он перестал работать, никаких результатов даже на фрагментах, которые раньше работали, я тогда прочитал здесь что лучше вставить onQueryTextChange listener in onPrepareOptionsMenu
в попытке избежать проблемы с invalidateOptionsMenu, но я решил дать эту попытку, которая также сработала, а затем, когда я добавил методы ко всем моим другим фрагментам еще раз, он терпит неудачу, но он работает на горстке фрагментов, как ни странно, все они прикреплены к одному родительскому фрагменту, но код для 4 родительских фрагментов, и для вызова их идентичен.
другой способ обойти это я прочитал creating an interface
и через которое из моей основной деятельности, получив ссылку на текущий фрагмент, но затем id должен получить текущий фрагмент с моего viewpager, который я не знаю, возможно ли кто-нибудь взвесить это для меня,
большое спасибо
и спасибо за большое редактирование lol
редактировать Попробовал подход интерфейса безрезультатно, хотя я все еще новичок, мне нужно найти прикрепленный фрагмент и с помощью fragmentstateviewpager это просто невозможно без использования хаков должна быть какая-то причина, почему он работает в некоторых, а не в других, а иногда и вовсе
Изменить 2
так что я все еще возился с этим, и у меня почти не было ответов, поэтому давайте немного освежим это, поэтому я добавлял макет меню в основной деятельности, как это
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.dashboard, menu);
SearchView searchView =
(SearchView)menu.findItem(R.id.action_search).getActionView();
SearchManager searchManager = (SearchManager)
getSystemService(SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
return true;
}
и затем добавление слушателя на него из фрагмента в onPrepareOptionsMenu, как это
@Override
public void onPrepareOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//in this instance we wont as it will create a duplicate
SearchView searchView = (SearchView)
menu.findItem(R.id.action_search).getActionView();
searchView.setOnQueryTextListener(null);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
showResults(newText);
return false;
}
});
super.onPrepareOptionsMenu(menu);
}
и я назвали setHasOptionsMenu(правда) в onCreateView фрагмента, это работает отлично, но у меня около 20 осколков, чтобы перебрать и, когда я добавить это к другим фрагментам его не удается, он либо ничего не делает, или делает вид пустой или в редких случаях работает, но это для меня говорит, что мой код-это хорошо и, может быть, ее жизненный цикл вещь, я пытался позвонить из onCreateOptionsMenu отломков и достичь тех же результатов, и я старался не называть ничего из основной активности в onCreateOptions кроме раздувания меню и позволяют фрагментам вызывать поисковую активность с помощью
SearchView searchView = (SearchView)menu.findItem
(R.id.action_search).getActionView();
SearchManager searchManager = (SearchManager)
getActivity().getSystemService(getActivity().SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager.getSearchableInfo
(getActivity().getComponentName()));
который снова работает примерно до 8 фрагментов, но мои 20 или около того просто заставляет его падать на свой меч, есть ли что-то, что я не делаю, что могло бы помочь
редактировать 3 Итак, добавив некоторые, проверив его, добавив еще несколько, проверив его, похоже, проблема с моими родительскими фрагментами, поэтому у меня есть основные фрагменты действия 4, которые каждый если я добавлю методы для прослушивателя запросов к первым 7 или около того фрагментам в первом родительском фрагменте, все они работают красиво, если я затем добавлю методы к следующему набору из 7 или около того фрагментов во втором родителе, работают только дочерние фрагменты вторых родителей, если я затем выйду из своего приложения и снова открою его, работают только фрагменты первых родителей, продолжу исследовать любую помощь скоро.
правка 4 Просто собираюсь добавить код, который я использую для родительских фрагментов и fragmentstatepager из моей основной деятельности
Итак, из моей основной деятельности я установил fragmentstatepager следующим образом
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new
ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new sentenceMakers(), "QUICKS");
adapter.addFrag(new tabFragOne(), "NOUNS");
adapter.addFrag(new tabFragTwo(), "VERBS");
adapter.addFrag(new tabFragThree(), "OBJECTS");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
//do nothing here! no call to super.restoreState(arg0, arg1);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
и мои родительские фрагменты выглядят так
public class sentenceMakers extends Fragment{
public ImageView imageView;
private ViewPager viewPager;
public static TabLayout tabLayout;
public sentenceMakers() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate
(R.layout.tab_frag_one, container, false);
// Inflate the layout for this fragment
//setRetainInstance(true);
viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) rootView.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
setupTabIcons();
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
}
private void setupTabIcons() {
TextView tabZero2 = (TextView)
LayoutInflater.from(getActivity()).inflate(R.layout.custom_tab, null);
tabZero2.setText("FAVOURITES");
//tabOne.setGravity(View.TEXT_ALIGNMENT_CENTER);
tabZero2.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.ic_star_white_24dp, 0, 0);
tabLayout.getTabAt(0).setCustomView(tabZero2);
TextView tabZero = (TextView)
LayoutInflater.from(getActivity()).inflate(R.layout.custom_tab, null);
tabZero.setText("FREQUENTS");
//tabOne.setGravity(View.TEXT_ALIGNMENT_CENTER);
tabZero.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.ic_people_outline_white_24dp, 0, 0);
tabLayout.getTabAt(1).setCustomView(tabZero);
TextView tabOne = (TextView)
LayoutInflater.from(getActivity()).inflate(R.layout.custom_tab, null);
tabOne.setText("PRONOUNS");
//tabOne.setGravity(View.TEXT_ALIGNMENT_CENTER);
tabOne.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.ic_accessibility_white_24dp, 0, 0);
tabLayout.getTabAt(2).setCustomView(tabOne);
TextView tabTwo = (TextView)
LayoutInflater.from(getActivity()).inflate(R.layout.custom_tab, null);
tabTwo.setText("CONJUCTIONS");
tabTwo.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.ic_add_white_24dp, 0, 0);
tabLayout.getTabAt(3).setCustomView(tabTwo);
TextView tabThree = (TextView)
LayoutInflater.from(getActivity()).inflate(R.layout.custom_tab, null);
tabThree.setText("ADJECTIVES");
tabThree.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.ic_favorite_border_white_24dp, 0, 0);
tabLayout.getTabAt(4).setCustomView(tabThree);
tabLayout.getTabAt(0).getCustomView().setSelected(true);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new
ViewPagerAdapter(getChildFragmentManager());
adapter.addFrag(new favouriteCards(), "FAVOURITES");
adapter.addFrag(new predictedCards(), "FREQUENTS");
adapter.addFrag(new pronouns(), "PRONOUNS");
adapter.addFrag(new conjuctions(), "CONJUNCTIONS");
adapter.addFrag(new Others(), "ADJECTIVES");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
}
}
все еще борется с этим, и я не могу для жизни меня понять, почему он будет работать в одной партии фрагментов, пока я не добавлю его в следующий набор, его то же самое с тем же кодом, он должен просто инициализировать последние фрагменты, которые просят его, может ли кто-нибудь помочь мне здесь? Спасибо за любую помощь
3 ответов
в принципе, есть вещь, которую вы должны иметь в виду, когда используете фрагменты: Не держите ссылки на ваши фрагменты: просто создайте их и добавьте в свой макет или предоставьте вашему ViewPager, но затем используйте другие методы для их извлечения, например FragmentManager.findFragmentBy...
тем не менее, ваш код должен быть (позвольте мне упростить всего два фрагмента):
Главная активность
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new MyViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
}
class MyViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new sentenceMakers();
case 1:
return new tabFragOne();
// add here fragments for any other position
}
}
@Override
public int getCount() {
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
switch(position) {
case 0:
return "QUICKS";
case 1:
return "NOUNS";
// add here titles for any other position
}
}
}
sentenceMakers
код, который вам придется использовать в вашем фрагменте sentenceMakers, очень похож на предыдущий, но вам придется использовать дочерний fragmentManager (как и в вашем коде), и снова не держите свои фрагменты в списке, пусть система создает их при необходимости.
ок, я исправил это так проблема в том, что родитель fragmentstatepager нагрузок fragmentA + fragmentB в памяти, тогда ребенок fragmentstatepagers нагрузки там своя childfragmentA + childfragmentB так что теперь у нас 2 родителей и 4 детей, onPrepareOptionsMenu называется с детьми фрагменты, так что первым загружается childfragmentA(ребенок fragmentA), а затем childFragmentA(ребенок fragmentB) загружается и ворует поиска просмотреть, мой "исправить" это, наверное, немного сырой я себя учил, и я не очень знаю, как управлять памятью или если ее плохо держать ссылки и т. д., я отвлекаюсь, в Родительском фрагменте я проверяю, какой фрагмент виден с помощью
setMenuVisibility(final boolean visible)
и там я установил публичное статическое логическое значение и проверил его в своих childfragments, и он работает безупречно для меня, как упоминалось, это, вероятно, ужасная вещь, чтобы сделать, надеюсь, кто-то здесь может дать лучшее решение
проверьте, какой родитель видимый
public static boolean tabFragOneVisible;
@Override
public void setUserVisibleHint(boolean isVisible){
super.setUserVisibleHint(isVisible);
if(!isVisible){
tabFragOneVisible = false;
}else{
tabFragOneVisible = true;
}
}
проверьте, если родитель виден подключить вид поиска
@Override
public void onPrepareOptionsMenu(Menu menu) {
// need to check if fragment is visible
if (tabFragOne.tabFragOneVisible) {
SearchView searchView = (SearchView)
menu.findItem(R.id.action_search).getActionView();
SearchManager searchManager = (SearchManager) getActivity()
.getSystemService(getActivity().SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getActivity().getComponentName()));
// searchView.setOnQueryTextListener(null);
searchView.setOnQueryTextListener(new
SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
showResults(newText);
return false;
}
});
}
else{
}
super.onPrepareOptionsMenu(menu);
}
возможно, это все равно поможет кому-то изо всех сил заставить один SearchView работать для нескольких фрагментов. Я обнаружил, что onQueryTextListener будет работать на фрагменте 1 (где изначально создается SearchView), но не будет работать на фрагменте 2,3 и т. д.
фрагменты 2 работали, когда onPrepareOptionsMenu переопределяется и onViewCreated включает setHasOptionsMenu(true). Например:
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
...the rest of your code goes here...
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) item.getActionView();
searchView.setOnQueryTextListener(this);
super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
Toast.makeText(getActivity(),"It Worked!!",Toast.LENGTH_SHORT).show();
return true;
}