Right now I have a tablayout with a ViewPager + adapter below it. I want to pause a fragment when a different tab is selected (not destroy/pop it, just pause it) and resume it when the fragment’s tab is selected.
public class PagerFragment extends Fragment {
ViewPagerAdapter pagerAdapter;
ViewPager pager;
TabLayout tabLayout;
int position;
public PagerFragment() {
super();
}
public void setPosition(int position) {
this.position = position;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onStop() {
super.onStop();
}
@Override
public void onPause() {
super.onPause();
pagerAdapter.clear();
pagerAdapter.notifyDataSetChanged();
}
@Override
public void onStart() {
super.onStart();
}
@Override
public void onResume() {
super.onResume();
if (!isAdded()) {
pagerAdapter.instantiateItem(pager, position);
}
}
@SuppressLint("InflateParams")
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_pager, null);
pagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
setPosition(position);
pagerAdapter.setDevicesList(devicesList);
pager = root.findViewById(R.id.pager);
pager.setAdapter(pagerAdapter);
tabLayout = root.findViewById(R.id.tab_layout);
for (int i = 0; i < devicesList.size(); i++) {
tabLayout.addTab(tabLayout.newTab().setText(String.valueOf(devicesList.get(i).getName())));
}
TabLayout.Tab tab = tabLayout.getTabAt(position);
if (tab != null) {
tab.select();
pager.setCurrentItem(position);
tabLayout.setupWithViewPager(pager);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
pager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
int pos = tab.getPosition();
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager));
return root;
}
}
public class ViewPagerAdapter extends FragmentPagerAdapter {
ArrayList<ConnectedBluetoothDevice> devicesList;
ArrayList<DataViewFragment> dataViewFragments;
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
/**
* Initializes the adaptor with the device list and the list of data fragments.
* @param devicesList List of devices to be displayed in their own data fragment.
*/
public void setDevicesList(ArrayList<ConnectedBluetoothDevice> devicesList) {
this.devicesList = devicesList;
dataViewFragments = new ArrayList<>();
for (int i = 0; i < devicesList.size(); i++) {
dataViewFragments.add(new DataViewFragment(devicesList.get(i)));
}
}
/**
* GetItem
* @param position position of item in the viewPager list to be returned
* @return fragment to view
*/
@NonNull
public Fragment getItem(int position) {
if (dataViewFragments != null && position < dataViewFragments.size()) {
return dataViewFragments.get(position);
} else {
return new DataViewFragment(null);
}
}
@Override
public int getCount() {
return devicesList.size();
}
/**
* Updates the tabs in tabLayout while swiping pages
* @param position of the viewPage
* @return title of the tab
*/
public CharSequence getPageTitle(int position) {
super.getPageTitle(position);
return devicesList.get(position).getName();
}
public void clear() {
dataViewFragments.clear();
}
}
Some notes:
- I’m instructed to fix this bug in ViewPager and FragmentPagerAdapter, so please don’t recommend me solutions in ViewPager2 and FragmentStatePagerAdapter 🙂
- I heard that
setOffscreenPageLimit(0);
isn’t the best practice so I want to avoid that situation (especially since I only need to pause the fragment but not destroy it)
2
Answers
This depends on the version of
ViewPager
you are using as it was added later.Your are using a deprecated constructor
So as long as your using a recent version of
Viewpager
you should use the non deprecated constructor:-This constructor with the behaviour
BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
To get to the
STARTED
lifecycle state fromRESUMED
onPause
is called.so change
to
This method is used to for calling functions to run only when the specified tab is selected.