83

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.

Matt Ke
  • 3,599
  • 12
  • 30
  • 49
MJM
  • 5,119
  • 5
  • 27
  • 53
  • 1
    I have the same problem. I had switched from v4 to v13, so that I could use standard fragments in the code (not the support fragments and the support fragment manager). Now it looks like I need to switch back to support fragments. At least half a day editing of code :-( – Einar H. Sep 27 '18 at 21:24
  • Refactored the code for Androidx support libraries, hopefully it remains stable for some time now. – Einar H. Oct 03 '18 at 12:29
  • If you use AndroidX, you may do it in such a way https://stackoverflow.com/questions/51131172/fragmentstatepageradapter-is-deprecated-from-api-27/56542546#56542546 – Denis Dmitrienko Jun 20 '19 at 14:31
  • Have a look: https://stackoverflow.com/q/56208169/1318946 – Pratik Butani Jan 08 '20 at 05:07
  • FragmentStatePagerAdapter(fm,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT). BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, it means offset fragments will be executed on onStart() and the current fragment will be executed onStart() and onResume(). – Erik Jhordan Rey Jul 16 '20 at 04:33
  • although now is deprecated https://developer.android.com/reference/androidx/fragment/app/FragmentStatePagerAdapter – Erik Jhordan Rey Jul 16 '20 at 04:41

12 Answers12

85

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;
eytschkay
  • 961
  • 6
  • 9
  • 2
    Does this affect the functionality in any way? – Mangesh Mar 23 '20 at 14:37
  • BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT it means offset fragments will be executed on onStart() and the current fragment will be executed unto onStart() and onResume(). about how it affects not really, depends your implementation. – Erik Jhordan Rey Jul 16 '20 at 04:27
  • 2
    although now is deprecated https://developer.android.com/reference/androidx/fragment/app/FragmentStatePagerAdapter – Erik Jhordan Rey Jul 16 '20 at 04:40
  • Google has made ```ViewPager2``` as a ```final``` class, We are not allowed to extend and modify its functionalities, which was possible earlier with ```ViewPager``` – yajnesh Aug 10 '21 at 19:04
  • https://stackoverflow.com/a/57888432/14784590 and we can use onPause and onResume – Reejesh Aug 21 '21 at 04:30
67

You may extend

androidx.fragment.app.FragmentStatePagerAdapter;

and call

super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);

in your class's constructor

Denis Dmitrienko
  • 1,532
  • 2
  • 16
  • 26
23

This works for me.

In Kotlin :

class TasksPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT )
Alok Gupta
  • 1,806
  • 22
  • 21
  • 5
    I use your code but i got lint error "must be one of BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)" what should i do? – zihadrizkyef May 14 '20 at 10:09
  • getting error Must be one of: androidx.fragment.app.FragmentStatePagerAdapter.BEHAVIOR_SET_USER_VISIBLE_HINT, androidx.fragment.app.FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT – Abhay Pratap May 10 '21 at 14:26
22

You need to add behavior in your MainPagerAdapter like this:

super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);

Moisoni Ioan
  • 1,370
  • 1
  • 13
  • 24
5

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

Chamlal
  • 156
  • 1
  • 5
3

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()
Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82
2

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

LarsH
  • 27,481
  • 8
  • 94
  • 152
Azay Gupta
  • 281
  • 2
  • 16
  • 4
    FragmentStatePagerAdapter is deprecated also – Ernesto Vega Jun 20 '19 at 09:29
  • I think that despite having had the wrong links (which I just fixed), this answer is correct: v4 FragmentStatePagerAdapter is not deprecated. https://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html @Ernesto I'm not sure which version of FragmentStatePagerAdapter your comment refers to. – LarsH Aug 27 '19 at 14:39
2
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

A Hashemi
  • 289
  • 2
  • 6
2

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

joaoibarra
  • 101
  • 2
1

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.

Mayank Bhatnagar
  • 2,120
  • 1
  • 12
  • 20
0

Both FragmentStatePagerAdapter and FragmentPagerAdapter have been deprecated. We need to use ViewPager2 + FragmentStateAdapter since AndroidX

Here are two ways to implement the above:

  1. This link is a vast solution including the implementation of TabLayout with ViewPager2. This also includes various updates throughout
  1. This tutorial is a relatively simpler implementation to resolve the issue and discusses an approach to ViewPager2 with Fragment

Both the solutions work. Read the documentation too for better understanding.

aQwus jargon
  • 133
  • 3
  • 18
0

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) {

        }
    })
Nimesh Patel
  • 1,394
  • 13
  • 26