【问题标题】:How to use onQueryTextChange with many fragments如何将 onQueryTextChange 与许多片段一起使用
【发布时间】:2017-02-17 16:14:05
【问题描述】:

我有很多片段,它们使用FragmentStatePagerAdapter 显示在 2 个选项卡布局中,每个片段都有一个 Recycler 视图,我想使用应用栏中的搜索栏来过滤结果。

首先,我在 onCreateOptionsMenu 中使用onQueryTextChange listener 执行此操作,它在几个片段上工作得很好,但是当我将实现添加到其他片段(只是 ctrl+c 和 ctrl+v)时它停止工作,甚至没有结果在曾经可以工作的片段上,然后我阅读here,最好坚持onQueryTextChange listener in onPrepareOptionsMenu,以避免出现invalidateOptionsMenu问题,但我决定尝试一下,它也有效,然后当我添加方法时我的所有其他片段再次失败,但它确实适用于少数片段,奇怪的是这些片段恰好都附加到同一个父片段,但 4 个父片段的代码和调用它们的代码是相同的。

我读过的另一种解决方法是creating an interface,并通过获取对当前片段的引用从我的主要活动中使用它,但随后 id 必须从我的 viewpager 获取当前显示的片段,我不知道这是可能的谁能帮我权衡一下,

非常感谢

感谢您的精彩编辑,哈哈

编辑 尽管我仍然是初学者,但尝试了界面方法无济于事,但我确实需要找到附加的片段,并且使用 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);
}

并且我在片段的 onCreateView 中调用了 setHasOptionsMenu(true),这很有效,但是我有大约 20 个片段要循环,当我将它添加到其他片段时它失败了,它要么什么都不做,要么使视图空白或在极少数情况下有效,但对我来说,我的代码没问题,也许它是一个生命周期的东西,我尝试从片段的 onCreateOptionsMenu 调用它并取得相同的结果,并且我尝试不从 onCreateOptions 中的 MainActivity 调用任何东西,除了膨胀菜单并允许片段使用

调用搜索活动
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 个左右的片段它们都工作得很好,如果我然后将这些方法添加到第二个父片段中的下一组 7 个左右的片段中,那么只有第二个父片段的子片段起作用,如果我然后退出我的应用程序并再次打开它,只有第一个父片段可以工作,我会继续调查任何帮助,我会很快在此处发布我的父片段的代码。

编辑 4 只是从我的主要活动中添加我用于父片段和片段状态页面的代码

所以从我的主要活动中,我将 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);
    }
}
}

仍在为此苦苦挣扎,我终其一生都无法弄清楚为什么它会在很多片段中工作,直到我将它添加到下一组,它具有相同的代码,它必须只是初始化最后一个要求它的片段有人可以在这里帮助我吗? 感谢您的帮助

【问题讨论】:

  • 您应该展示您的代码以及到目前为止您尝试过的内容。
  • @MaskedMan 我非常同意让我现在编辑这个
  • @MaskedMan 完成

标签: android android-fragments searchview textchanged


【解决方案1】:

基本上,当您使用片段时,您必须记住一件事:不要保留对片段的引用:只需创建它们并添加到您的布局中,或提供给您的 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 Fragment 中使用的代码与前一个非常相似,但您必须使用子 fragmentManager(就像您在代码中所做的那样),并且不要将您的片段保存在列表中,让系统在需要时创建它们。

【讨论】:

  • 谢谢您的回复 我刚刚注意到您的回复,并且正在狂热地测试一件事,我应该让 getItem 和 getTitle 这两种方法返回无效吗?
  • 好吧忘了我问为什么它要求缺少退货声明?
  • 好的,我已经设法实施了您的建议,非常感谢您,但我的问题仍然存在如果有什么遗漏再次感谢
  • 你在哪里搜索?
  • 这是一个主要活动,带有一个视图寻呼机保存片段,因此搜索是从主要活动执行的,并且希望从工作正常的片段中获得结果,当它工作时
【解决方案2】:

好的我修复了它所以问题是父fragmentstatepager将fragmentA + fragmentB加载到内存中,然后子fragmentstatepager加载自己的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);
}

【讨论】:

    【解决方案3】:

    也许,它仍然会帮助那些努力使一个 SearchView 为多个片段工作的人。我发现 onQueryTextListener 可以在 Fragment 1(最初创建 SearchView 的地方)上工作,但不会在 Fragment 2,3 等上触发。

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

    【讨论】:

      猜你喜欢
      • 2011-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-29
      • 1970-01-01
      • 1970-01-01
      • 2013-03-10
      • 1970-01-01
      相关资源
      最近更新 更多