【问题标题】:How can filter recyclerview in selected viewpager fragment on search?如何在搜索时过滤选定的viewpager片段中的recyclerview?
【发布时间】:2021-07-16 01:45:17
【问题描述】:

我在带有标签的 viewpager 中有 3 个标签片段。所有选项卡都有 recyclerview 和 ListAdapter 显示客户列表。每个选项卡代表 1) 所有客户 2) 新订购的客户 3) 付费客户。我只想设置搜索过滤器标签选择片段。如果 Searchview 可以放置在所有片段通用的活动上,那么在我的情况下会更好。我尝试了几种方法,但都失败了。我的搜索结果总是只在最后一个标签(付费)中。请任何人帮助我提供完整的代码示例?

还有我的 MainActivity

private void initializeTab(){

   mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

   viewPager = (MyViewPager) findViewById(R.id.view_pager);
   viewPager.setOffscreenPageLimit(5);
   viewPager.setAdapter(mSectionsPagerAdapter);

   tabLayout = (SmartTabLayout) findViewById(R.id.tabs);
   tabLayout.setViewPager(viewPager);
   viewPager.setPagingEnabled(true);

}

private class SectionsPagerAdapter extends FragmentStatePagerAdapter {

  protected int currentPosition = -1;
  protected Fragment currentFragment;

  public SectionsPagerAdapter(FragmentManager fm) {
     super(fm,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
  }

  @Override
  public Fragment getItem(int position) {

    return ViewPagerFragment.newInstance(getPageTitle(position)+"");
  }

  @Override
  public int getCount() {
    // Show 3 total pages.
    return 3;
  }

  @Override
  public CharSequence getPageTitle(int position) {
    switch (position) {
       case 0:
         return "All";
       case 1:
         return "New";
       case 2:
         return "Paid";
    }
       return null;
 }

 @Override
 public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
   super.setPrimaryItem(container, position, object);
   this.currentPosition = position;
   if (object instanceof Fragment){
      this.currentFragment = (Fragment)object;
   }
 }

 public Fragment getCurrentFragment() {
   return currentFragment;
 }

 public void setCurrentFragment(Fragment currentFragment) {
    this.currentFragment = currentFragment;
 }
}

和我的片段

public class ViewPagerFragment extends AbstractFragment {
  ............
 public static ViewPagerFragment newInstance(String title) {
   ViewPagerFragment fragment = new ViewPagerFragment();
   Bundle args = new Bundle();
   args.putString("TITLE",title);
   fragment.setArguments(args);
   return fragment;
 }
 @Override
 public void onViewCreated(final View view, Bundle savedInstanceState) {
   swipeLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeToRefresh);

   recycler = (RecyclerView) view.findViewById(R.id.recycler);
   adapter = new CustomerAdapter(getContext());
   recycler.setLayoutManager(new LinearLayoutManager(getContext()));
   recycler.setHasFixedSize(true);
   recycler.addItemDecoration(new ItemDecoration(1,false, dpToPx(0),true,2));
   recycler.setItemAnimator(new DefaultItemAnimator());
   recycler.setAdapter(adapter);
   changeFragment(swipeLayout);
 }

 public void changeFragment(final SwipeRefreshLayout swipeLayout){

        final String tab = getArguments().getString("TITLE");

        loadDatas(allRecords,tab);

        swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                swipeLayout.setRefreshing(true);
                utils.getDetails(getContext());
                utils.setOnDataLoaded(new MyUtils.DataLoadingListener() {
                    @Override
                    public void onDataLoaded(ArrayList<Customers> list) {
                        loadDatas(list, tab);
                        swipeLayout.setRefreshing(false);
                    }

                });

            }
        });


        // Scheme colors for animation
        swipeLayout.setColorSchemeColors(
                getResources().getColor(android.R.color.holo_blue_bright),
                getResources().getColor(android.R.color.holo_green_light),
                getResources().getColor(android.R.color.holo_orange_light),
                getResources().getColor(android.R.color.holo_red_light)
        );
  }

  void loadDatas(List<Customers> list, String tab){

        if (list != null && list.size() > 0) {
            List<Customers> tabList = new ArrayList<>();

            if (tab.equals("All")) {
                tabList = list;
            }else {
                for (Customers item : list) {
                    if (item.getStatus().equals(tab)) {
                        tabList.add(item);
                    }else {
                       Log.d(TAG, "loadDatas: "+item.getStatus());
                    }
                }
            }
            adapter.submitList(tabList);
        }
    }

}

【问题讨论】:

    标签: java android android-viewpager


    【解决方案1】:

    Searchview 可以放置在所有片段通用的活动上,在我的情况下会更好。

    这是对的。

    我尝试了几种方法,但都失败了。我的搜索结果总是只在最后一个标签(付费)中。

    所以,我假设现在的问题不在于过滤本身,而是它总是返回最后一个选项卡的结果;因此,您可能没有提供过滤代码。

    现在ViewPager 中有 3 个标签,每个标签代表一个片段;因此,我们需要获取ViewPager 的当前选定片段,以便让活动向其发送搜索到的文本。

    从 ViewPager 获取当前片段(您的情况):

    ViewPagerFragment currentFragment = (ViewPagerFragment) mViewPagerAdapter.instantiateItem(viewPager, viewPager.getCurrentItem());
    

    从 ViewPager2 获取当前片段:

    ViewPager 有getCurrentItem(),它返回当前页码 因此,我们需要将每个页面片段链接到页码。

    但是我们可以通过它的 id(item id)得到一个 ViewPager 片段,所以第一步是让页面 Id 等于相应的位置,这样做覆盖 ViewPager 适配器中的getItemId

    @Override
    public long getItemId(int position) {
        return position;
    }
    

    然后在活动过滤部分,假设您正在搜索一个名为 seachString 的 var 中的字符串:

    int pageId = viewpager.getCurrentItem();
    
    Fragment currentFragment = (ViewPagerFragment) getChildFragmentManager()
                                                  .findFragmentByTag("f" + pageId);
    

    然后在获取当前片段后,在其中创建一些方法,该方法接受一个字符串参数作为搜索值:

    所以,在ViewPagerFragment,创建:

    public void searchFor(String search) {
        // filter the results of the RecyclerView
    }
    

    并在 Activity 中 ViewPager 的当前片段上调用该方法:

    currentFragment.searchFor(seachString);
    

    【讨论】:

    • getItemId(int pos) 在 FragmentStatePagerAdapter 中不可用。连你的回答都不适合我,看了你的后我的逻辑就打开了。
    • @Koyas 那是我的错.. 只是以为你使用ViewPager2 而不是ViewPager .. 我会更新ViewPager.. 但请注意ViewPager 现在已弃用
    • @Koyas 我刚刚更新了答案,请看一下
    • 我可以用你的方法得到没有 tabChangeListener 的 currentFragment 吗?
    • @Koyas 当然可以,只要将ViewPagertabLayout.setViewPager(viewPager) 绑定即可
    【解决方案2】:

    关于recyclerview过滤器数据:

    1. 可以使您的类 CustomerAdapter 实现可过滤

    喜欢:

    class Adapter extends RecyclerView.Adapter implements Filterable {
        ......    
        @Override
        public Filter getFilter() {
            return new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence constraint) {
                    return ...;
                }
    
                @Override
                protected void publishResults(CharSequence constraint, FilterResults results) {
    
                }
            };
        }
    }    
    
    1. 也可以参考这个:https://github.com/xaverkapeller/Searchable-RecyclerView-Demo

    关于如何在选中的 viewpager 片段中执行此操作,您只需要调用当前片段的搜索方法即可。

    【讨论】:

      【解决方案3】:

      最后我成功了,我认为它不是很专业,但它工作正常。为了帮助受苦的人,我在这里分享。

      首先我添加了 tabScrollingListener 来获取 MainActivity 中选择的片段

      public class MainActivity extends AppCompatActivity{
      
      ..........
        private ViewPagerFragment selectedFragment;
      
        private void initializeTab(){
      
          mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
      
          viewPager = (MyViewPager) findViewById(R.id.view_pager);
          viewPager.setOffscreenPageLimit(5);
          viewPager.setAdapter(mSectionsPagerAdapter);
      
          tabLayout = (SmartTabLayout) findViewById(R.id.tabs);
          tabLayout.setViewPager(viewPager);
          viewPager.setPagingEnabled(true);
          viewPager.setCurrentItem(0);
      
          tabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
              @Override
              public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                      selectedFragment = (ViewPagerFragment) mSectionsPagerAdapter.getCurrentFragment();
                  }
      
                  @Override
                  public void onPageSelected(int position) {
      
                  }
      
                  @Override
                  public void onPageScrollStateChanged(int state) {
      
                  }
           });
      
        }
      
      }
      

      然后我将过滤器功能转移到 Zain 的回答中提到的 Fragment。当我将 ListAdapter 用于我的回收器时,很容易将我的过滤器列表提交给适配器。我在 loadData 函数上加载了我的过滤器列表。

      public class ViewPagerFragment extends AbstractFragment {
        ............
       private List<Customers> filterList;
      
       public static ViewPagerFragment newInstance(String title) {
         ViewPagerFragment fragment = new ViewPagerFragment();
         Bundle args = new Bundle();
         args.putString("TITLE",title);
         fragment.setArguments(args);
         return fragment;
       }
       @Override
       public void onViewCreated(final View view, Bundle savedInstanceState) {
         swipeLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeToRefresh);
      
         recycler = (RecyclerView) view.findViewById(R.id.recycler);
         adapter = new CustomerAdapter(getContext());
         recycler.setLayoutManager(new LinearLayoutManager(getContext()));
         recycler.setHasFixedSize(true);
         recycler.addItemDecoration(new ItemDecoration(1,false, dpToPx(0),true,2));
         recycler.setItemAnimator(new DefaultItemAnimator());
         recycler.setAdapter(adapter);
         changeFragment(swipeLayout);
       }
      
       public void changeFragment(final SwipeRefreshLayout swipeLayout){
      
              final String tab = getArguments().getString("TITLE");
      
              loadDatas(allRecords,tab);
      
              swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
                  @Override
                  public void onRefresh() {
                      swipeLayout.setRefreshing(true);
                      utils.getDetails(getContext());
                      utils.setOnDataLoaded(new MyUtils.DataLoadingListener() {
                          @Override
                          public void onDataLoaded(ArrayList<Customers> list) {
                              loadDatas(list, tab);
                              swipeLayout.setRefreshing(false);
                          }
      
                      });
      
                  }
              });
      
      
              // Scheme colors for animation
              swipeLayout.setColorSchemeColors(
                      getResources().getColor(android.R.color.holo_blue_bright),
                      getResources().getColor(android.R.color.holo_green_light),
                      getResources().getColor(android.R.color.holo_orange_light),
                      getResources().getColor(android.R.color.holo_red_light)
              );
        }
      
        void loadDatas(List<Customers> list, String tab){
      
              if (list != null && list.size() > 0) {
                  List<Customers> tabList = new ArrayList<>();
      
                  if (tab.equals("All")) {
                      tabList = list;
                  }else {
                      for (Customers item : list) {
                          if (item.getStatus().equals(tab)) {
                              tabList.add(item);
                          }else {
                             Log.d(TAG, "loadDatas: "+item.getStatus());
                          }
                      }
                  }
                  filterList = tabList; // this fills filter list
                  adapter.submitList(tabList);
              }
          }
      
      }
      
      public void filter(String text, String filter) {
      
              ArrayList<Customers> filteredlist = new ArrayList<>();
      
              // running a for loop to compare elements.
              if (filterList != null && filterList.size() > 0) {
                  if (text.length() > 0) {
                      for (Customers item : filterList) {
                         // here filter options gone
                      }
                  }else {
                      filteredlist.addAll(filterList);
                  }
              }
              adapter.submitList(filteredlist);
      
      }
      

      是的,现在我在 MainActivity 中获得了带有过滤功能的 currentSelectedFragment 在 searchListener 中,我可以将其称为 selectedFragment.filter(query)。

             searchview.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                  @Override
                  public boolean onQueryTextSubmit(String query) {
                      return false;
                  }
      
                  @Override
                  public boolean onQueryTextChange(String newText) {
      
                      selectedFragment.filter(newText); // search filter here
      
                      return true;
                  }
              });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-16
        • 2017-11-11
        相关资源
        最近更新 更多