I have 3 tab fragments in viewpager with tabs. All tabs have recyclerview with ListAdapter showing customers list. Each tab represents 1) all customers 2) New ordered customers 3) Paid customers. I want to set search filter only on tab selected fragment . If the Searchview can place on activity which is common for all fragments, will be better in my case. I tried several ways but was failed. My search was resulting always only in last tab (Paid). Please can any one help me with full example of code?
And my 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;
}
}
and my Fragment
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);
}
}
}
About the recyclerview filter data:
like :
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) {
}
};
}
}
About how to do this in selected viewpager fragment , you just need to invoke the search method of the current fragment.
the Searchview can place on activity which is common for all fragments, will be better in my case.
This is right.
I tried several ways but was failed. My search was resulting always only in last tab (Paid).
So, I'm assuming that the issue now isn't in the filtering itself, but that it always returns the results of the last tab; and therefore you probably didn't provide the filtering code for such a reason.
Now we've 3 tabs in the ViewPager
, each represents a fragment; So we need to get the current selected fragment of the ViewPager
in order to allow the activity send it the searched text.
To get the current fragment from ViewPager (Your case):
ViewPagerFragment currentFragment = (ViewPagerFragment) mViewPagerAdapter.instantiateItem(viewPager, viewPager.getCurrentItem());
To get the current fragment from ViewPager2:
The ViewPager has getCurrentItem()
which returns the current page number So, we need to link the each page fragment to the page number.
But we can get a ViewPager fragment by its id (item id), so the first step is to have page Ids that equals to the corresponding position, to do so override getItemId
in the ViewPager adapter.
@Override
public long getItemId(int position) {
return position;
}
Then in the activity filtering part assuming you are searching for a String that is in a var named seachString
:
int pageId = viewpager.getCurrentItem();
Fragment currentFragment = (ViewPagerFragment) getChildFragmentManager()
.findFragmentByTag("f" + pageId);
Then after getting the current fragment, create some method in it that accepts a String parameter for the searched value:
So, in ViewPagerFragment
, create:
public void searchFor(String search) {
// filter the results of the RecyclerView
}
And call that method on the current fragment of the ViewPager in the activity:
currentFragment.searchFor(seachString);
At last I succeeded, I think it is not very professional but it is working fine. To help some one suffering I am sharing that here.
Firstly I added tabScrollingListener to get the selected fragment in 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) {
}
});
}
}
Then I transferred my filter function to Fragment like mentioned in Zain's answer . As I am using ListAdapter for my recycler it's easy to submit my filter list to adapter. I loaded my filter list on loadData function.
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);
}
Yea, Now I got currentSelectedFragment with filter function in MainActivity In searchListener I can call it like 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;
}
});
Follow the below step to find the clicked tab,
First add tab select listener
tabLayout.addOnTabSelectedListener(object:TabLayout.OnTabSelectedListener{
override fun onTabSelected(tab: TabLayout.Tab?) {
selectedFragment= fragmentViewPagerAdapter!!.fragments[tab!!.position]
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
// enter code here
}
override fun onTabReselected(tab: TabLayout.Tab?) {
// enter code here
}
})
and then setupWithViewPager
tabLayout.setupWithViewPager(viewPager)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.