Reputation: 5311
FragmentStatePagerAdapter
is deprecated from API 27. What's the alternative of FragmentStatePagerAdapter
?
private class MainPagerAdapter extends FragmentStatePagerAdapter {
MainPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
Fragment result = new DummyFragment();
return result;
}
@Override
public int getCount() {
return 5;
}
}
Above code shows FragmentStatePagerAdapter
, getItem(...)
and super(...)
as deprecated.
Upvotes: 84
Views: 72087
Reputation: 1496
To load single Fragment at a time you have to use ViewPager2
. Because FragmentStatePagerAdapter
is deprecated after API level 27.
Use Below steps to implement viewPager
with TabLayout
to load single fragment at time.
Step1: add tablayout nad viewpage in your xml file where you want to display multiple tab.
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:id="@+id/tab_layout"/>
<androidx.viewpager2.widget.ViewPager2
android:layout_width="match_parent"
android:saveEnabled="false"
android:layout_height="match_parent"
android:id="@+id/viewpager" />
Step2: Then Create Adapter Class for your viewPager to manage your multiple Fragments.
class MyFragmentsAdapter(fm: FragmentManager,
private val totalTabs: Int,
lifecycle: Lifecycle) :
FragmentStateAdapter(fm, lifecycle) {
override fun getItemCount(): Int = totalTabs
override fun createFragment(position: Int): Fragment {
when (position) {
0 -> {
return NotificationsFragment()
}
1 -> {
return MessagesFragment()
}
2 -> {
return CalendarFragment()
}
else -> return NotificationsFragment()
}
}
}
Step3: Now attached this adapter class with your viewPager Object.
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.notification)))
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.messages)))
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.calendar)))
val adapter = NotificationTabsAdapter(
requireContext(),
childFragmentManager, tabLayout.tabCount,
lifecycle
)
viewPager.adapter = adapter
Step4: Now create ViewPager2.OnPageChangeCallback
method to manage tablayout status on ViewPager state change. Also register this method for viewpager using registerOnPageChangeCallback
val myPageChangeCallback = object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
tabLayout.getTabAt(position)?.select()
}
}
viewPager.registerOnPageChangeCallback(myPageChangeCallback)
Step5: Now Register tablyout to change viewpager on tabItem click.
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
viewPager.currentItem = tab.position
}
override fun onTabUnselected(tab: TabLayout.Tab) {
}
override fun onTabReselected(tab: TabLayout.Tab) {
}
})
Upvotes: 0
Reputation: 14618
Android ViewPager2 with TabLayout to implement Fragments
in the Activity
1. in your XML file inside vertical Linearlayout:
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_50"/>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
2. Create your Adapter to load Fragments
class MyFragmentsAdapter(fm: FragmentManager, lifecycle: Lifecycle) :
FragmentStateAdapter(fm, lifecycle) {
override fun getItemCount(): Int = 2
override fun createFragment(position: Int): Fragment {
return if (position == 0) {
FirstFragment()
} else {
SecondFragment()
}
}
}
3. Paste this code into your Activity class and DONE!
dataBinding.pager.adapter = PropertyDetailFragmentsAdapter(supportFragmentManager, lifecycle)
TabLayoutMediator(dataBinding.tabLayout, dataBinding.pager) { tab, position ->
tab.text = when (position) {
0 -> "First Fragment"
1 -> "Second Fragment"
else -> "First Fragment"
}
}.attach()
Upvotes: 3
Reputation: 1001
Switch to ViewPager2 and use FragmentStateAdapter instead.
From there you can use onPause and onResume callbacks to determine which fragment is currently visible for the user. onResume is called when a fragment became visible and onPause when it stops to be visible. -> read more
Based on the comments of Eric and Reejesh.
Old answer (deprecated too now)
The following constructors do the same
super(@NonNull FragmentManager fm)
super(@NonNull FragmentManager fm, BEHAVIOR_SET_USER_VISIBLE_HINT)
Passing BEHAVIOR_SET_USER_VISIBLE_HINT
got deprecated. You should pass BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
instead.
The difference in passing those is explained in FragmentPagerAdapter
:
/**
* Indicates that Fragment#setUserVisibleHint(boolean) will be
* called when the current fragment changes.
*/
@Deprecated
public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0;
/**
* Indicates that only the current fragment will be
* in the Lifecycle.State#RESUMED state. All other Fragments
* are capped at Lifecycle.State#STARTED.
*/
public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1;
Upvotes: 88
Reputation: 133
Both FragmentStatePagerAdapter
and FragmentPagerAdapter
have been deprecated. We need to use ViewPager2 + FragmentStateAdapter
since AndroidX
Here are two ways to implement the above:
TabLayout
with ViewPager2
. This also includes various updates throughoutViewPager2
with Fragment
Both the solutions work. Read the documentation too for better understanding.
Upvotes: 0
Reputation: 111
I know that is an old question, but now both FragmentStatePagerAdapter constructors are deprecated.
Instead you may extend:
import androidx.viewpager2.adapter.FragmentStateAdapter
The constructor its a bit different:
class DemoCollectionAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
override fun getItemCount(): Int = 3
override fun createFragment(position: Int): Fragment {
return when (position) {
0 -> MyFragment()
1 -> MyFragment2()
2 -> MyFragment3()
}
}
}
So in Fragment:
class CollectionDemoFragment : Fragment() {
private lateinit var demoCollectionAdapter: DemoCollectionAdapter
private lateinit var viewPager: ViewPager2
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.collection_demo, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewPager = view.findViewById(R.id.pager)
val tabLayout = view.findViewById(R.id.tab_layout)
demoCollectionAdapter = DemoCollectionAdapter(this)
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = when (position) {
0 -> "Home"
1 -> "Search"
2 -> "Favorites"
}
}.attach()
viewPager.adapter = demoCollectionAdapter
}
}
And change the xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
Check it the official documentation
Upvotes: 2
Reputation: 339
public static class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
@Override
public int getCount() {
return NUM_ITEMS;
}
@Override
public Fragment getItem(int position) {
return ArrayListFragment.newInstance(position);
}
}
See Reference developer.android.com
Upvotes: 2
Reputation: 156
The constructor with only FragmentManager as a paramaeter is duplicated and changed to
public FragmentStatePagerAdapter(@NonNull FragmentManager fm,
@Behavior int behavior)
but you can achieve the same by using the below constructor, you should also inject your tabsNumber via constructor to avoid using hard codded numbers, and return it via getCount().
public PagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
this.numberOfTabs= NumOfTabs;
}
@Override
public int getCount() {
return numberOfTabs;
}
for more details check the official documentation for AndroidX
Upvotes: 5
Reputation: 1910
This works for me.
In Kotlin :
class TasksPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT )
Upvotes: 23
Reputation: 311
This class was deprecated in API level 27.1.0. which was in support v13 https://developer.android.com/reference/android/support/v13/app/FragmentStatePagerAdapter
Use FragmentStatePagerAdapter from support v4 https://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter
Upvotes: 2
Reputation: 1751
You may extend
androidx.fragment.app.FragmentStatePagerAdapter;
and call
super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
in your class's constructor
Upvotes: 68
Reputation: 1425
You need to add behavior in your MainPagerAdapter
like this:
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
Upvotes: 22
Reputation: 2191
According to Documentation, android.support.v13.app.FragmentPagerAdapter was deprecated.
You may replace it with android.support.v4.app.FragmentPagerAdapter.
Check this out for Official doumentation.
Upvotes: 1