如何在onQueryTextChange上使用许多片段

时间:2016-10-08 22:21:31

标签: android android-fragments searchview textchanged

我有很多片段,他们在2个标签布局中使用FragmentStatePagerAdapter显示每个片段中有一个Recycler视图,我想在应用栏中使用搜索栏来过滤结果。

首先我使用onCreateOptionsMenu中的onQueryTextChange listener做了这个,并且它与一些片段一起正常工作但是当我将实现添加到其他片段(只是ctrl + c和ctrl + v)时它停止工作,没有结果甚至对曾经工作过的片段我读here时最好坚持使用onQueryTextChange listener in onPrepareOptionsMenu以避免与invalidateOptionsMenu的问题,但我决定尝试一下也行之有效当我将方法添加到我所有其他片段时又失败了但它确实对一些片段起作用,奇怪的是这些片段恰好全部附加到同一个父片段但是4个父片段的代码,并且用于调用它们是相同。

这个我读过的另一种方式是creating an interface并使用我的主要活动中的那个来获取对当前片段的引用但是id必须从我的viewpager获取当前显示的片段不知道是否有可能任何人都可以为我做这件事,

非常感谢

感谢伟大的编辑大声笑

修改的 尝试接口方法无济于事,虽然我还是初学者,我确实需要找到附加的片段,并且使用fragmentstateviewpager,如果不使用hacks就不可能有一些理由为什么它在某些部分工作而不在其他部分工作有时根本不是

编辑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

所以从我的主要活动中我设置了像这样的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 个答案:

答案 0 :(得分: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(就像你在代码中所做的那样),并且不要将你的片段保存在List中,让系统在需要时创建它们。

答案 1 :(得分:2)

好吧我修复它所以问题是父fragmentstatepager将fragmentA + fragmentB加载到内存中,然后子fragmentstatepagers加载自己的childfragmentA + childfragmentB所以我们现在有2个父母和4个孩子,onPrepareOptionsMenu从子片段调用第一个是加载的childfragmentA(fragmentA的子级),然后加载了childFragmentA(fragmentB的子级)并窃取了搜索视图,我的修复了#39;因为这可能有点粗糙我自学,我不知道如何管理内存,或者如果不能保持引用等等,我离题,在父片段中我检查哪个片段使用

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

答案 2 :(得分:0)

也许,它仍然可以帮助某人努力使一个SearchView适用于多个碎片。我发现onQueryTextListener可以在Fragment 1(最初创建SearchView的地方)上工作,但不会在Fragment 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;
}