FragmentPagerAdapter deprecated
Asked Answered
A

7

105

Since API 27 FragmentPagerAdapter is deprecated. What's the best alternative to use for this?

In my case, I understand something like super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) would need to be used, but I don't know where within my code this needs to go.

I got these imports in my class:

import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter

but FragmentPagerAdapter in class MyViewPagerAdapter(manager: FragmentManager) : FragmentPagerAdapter(manager){ is crossed out.

class MyViewPagerAdapter(manager: FragmentManager) : FragmentPagerAdapter(manager){
        private val fragmentList : MutableList<androidx.fragment.app.Fragment> = ArrayList()
        private val titleList : MutableList<String> = ArrayList()

        override fun getItem(position: Int): androidx.fragment.app.Fragment {
            return fragmentList[position]
        }

        override fun getCount(): Int {
            return fragmentList.size
        }

        fun addFragment(fragment: androidx.fragment.app.Fragment, title: String){
            fragmentList.add(fragment)
            titleList.add(title)
        }

        override fun getPageTitle(position: Int): CharSequence? {
            return titleList[position]
        }
    }
Alert answered 26/6, 2019 at 17:20 Comment(0)
A
152

UPDATE 2021-06-14: At this point, ViewPager itself is all but deprecated. Technically, ViewPager is not deprecated, but the two concrete PagerAdapter implementations — FragmentPagerAdapter and FragmentStatePagerAdapter — are deprecated. Ideally, switch to something else, such as ViewPager2 or the pager composable in Accompanist.

Replace:

class MyViewPagerAdapter(manager: FragmentManager) : FragmentPagerAdapter(manager)

with:

class MyViewPagerAdapter(manager: FragmentManager) : FragmentPagerAdapter(manager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)

(assuming that MyViewPagerAdapter does not need this value to be configurable)

Aplanospore answered 26/6, 2019 at 17:23 Comment(6)
Why i need this after add this @SuppressLint("WrongConstant") after adding this in constructor FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT?Terminal
@AsadMukhtar: I do not know, sorry. You might consider asking a separate Stack Overflow question, where you can provide a minimal reproducible example showing what you are trying and where you needed to apply that annotation.Aplanospore
We cannot use FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT anymore as FragmentPagerAdapter is also deprecated now.Anemic
@FerozKhan: Yes, I believe that at this point ViewPager itself is deprecated.Aplanospore
Alternately, you can say @SuppressWarnings("deprecation") in cases where ViewPager2 breaks your app behaviors :DHadwin
@EpicPandaForce: Agreed, though eventually Google is going to stop updating androidx.viewpager:viewpager. Even then, you might be able to use the last-shipped version for a while, before some transitive dependency or something breaks the build as you update other stuff. So, we don't have to race and replace ViewPager this week, but I would recommend it sometime in the next year or two.Aplanospore
M
16

Switch to ViewPager2 with FragmentStateAdapter.

Here is the XML view:-

<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>
class AdapterTabPager(activity: FragmentActivity?) : FragmentStateAdapter(activity!!) {
    private val mFragmentList: MutableList<Fragment> = ArrayList()
    private val mFragmentTitleList: MutableList<String> = ArrayList()
    
    public fun getTabTitle(position : Int): String{
        return mFragmentTitleList[position]
    }

    fun addFragment(fragment: Fragment, title: String) {
        mFragmentList.add(fragment)
        mFragmentTitleList.add(title)
    }

    override fun getItemCount(): Int {
        return mFragmentList.size
    }

    override fun createFragment(position: Int): Fragment {
        return mFragmentList[position]
    }
}

Here is the way to instantiate ViewPager:-

val adapter = AdapterTabPager(activity)
        adapter.addFragment(categoryFragment, "Category")
        adapter.addFragment(brandFragment, "Brand")

        rootView.viewpager.adapter = adapter
        rootView.viewpager.currentItem = 0
        TabLayoutMediator(rootView.tabs, rootView.viewpager) { tab, position ->
            tab.text = adapter.getTabTitle(position)
        }.attach()

Maffa answered 6/10, 2021 at 13:44 Comment(0)
P
14

The javadocs actually has the following deprecation notice on FragmentPagerAdapter:


This class is deprecated.

Switch to ViewPager2 and use FragmentStateAdapter instead.


Perchance answered 20/3, 2020 at 23:15 Comment(2)
This solution does not work if you want to extend ViewPager because ViewPager2 is public final.Metaphysics
how do I work this out github.com/android/views-widgets-samples/issues/107Kirov
S
6

Need to switch to ViewPager2, they have a migration guide here.

https://developer.android.com/training/animation/vp2-migration#java

Seaside answered 30/5, 2021 at 6:10 Comment(1)
Henrik Bøgelund Lavstsen, a link to a solution is welcome, but please ensure your answer is useful without it: add context around the link so your fellow users will have some idea what it is and why it is there, then quote the most relevant part of the page you are linking to in case the target page is unavailable. Answers that are little more than a link may be deleted.Sophey
R
5

If you used this path New > Activities > Tabbed Activity so you need some changes:

1- XML

before

<androidx.viewpager.widget.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="@string/pages"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

after

<androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="@string/pages"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

2- New Adapter As @Bharat Lalwani wrote below:

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter

class ScreenSlidePagerAdapter(activity: FragmentActivity?) : FragmentStateAdapter(activity!!) {
    private val mFragmentList: MutableList<Fragment> = ArrayList()
    private val mFragmentTitleList: MutableList<String> = ArrayList()

    fun getTabTitle(position : Int): String{
        return mFragmentTitleList[position]
    }

    fun addFragment(fragment: Fragment, title: String) {
        mFragmentList.add(fragment)
        mFragmentTitleList.add(title)
    }

    override fun getItemCount(): Int {
        return mFragmentList.size
    }

    override fun createFragment(position: Int): Fragment {
        return mFragmentList[position]
    }
}

3- Main Activity

before

val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager)
    val viewPager: ViewPager = binding.viewPager
    viewPager.adapter = sectionsPagerAdapter
    val tabs: TabLayout = binding.tabs
    tabs.setupWithViewPager(viewPager)

after

val adapter = ScreenSlidePagerAdapter(this)

    adapter.addFragment( PlaceholderFragment.newInstance( 1),"Brand")
    adapter.addFragment( PlaceholderFragment.newInstance( 2),"Brand2")
    val viewPager: ViewPager2 = binding.viewPager
    viewPager.adapter = adapter
    viewPager.currentItem = 0
    val tabs: TabLayout = binding.tabs
    TabLayoutMediator(tabs, viewPager) { tab, position ->
        tab.text = adapter.getTabTitle(position)
    }.attach()

4- Then you can delete SectionsPagerAdapter class

Radie answered 19/10, 2022 at 20:42 Comment(0)
R
2

It seems like not only the constructor without behavior, but the class FragmentPagerAdapter (which can consume a good amount of memory by keeping Fragments in memory), and FragmentStatePagerAdapter are both in deprecation stage. I wonder what can be used to extend abstract class PagerAdapter to extend codebase lifespan.

Runagate answered 3/8, 2020 at 13:5 Comment(0)
A
2

You can use FragmentStateAdapter(fragment)

class YourViewPagerAdapter(fragment: Fragment, val mFragmentList: Array<String>, val viewPager: ViewPager2) :  FragmentStateAdapter(fragment){

    override fun getItemCount(): Int {
        return mFragmentList.size
    }

    override fun createFragment(position: Int): Fragment {
        when(position){
            0 -> return YourFirstTabFragment()
            1 -> return YourSecondTabFragment()
            2 -> return YourThirdTabFragment()

        }
        return YourFirstTabFragment()
    }


}
Airglow answered 16/7, 2021 at 12:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.