Search code examples
androidandroid-fragmentsandroid-viewpager2

setAdapter expects recycler view adapter but I want viewpager adapter. What am I doing wrong?


I am starting to migrate to fragments and want to swipe between them. I have followed various tutorials, got stuck, got unstuck, got stuck again (the usual).

Currently I am stuck trying to get my viewpager set up. Before starting this I moved part of my view to a fragment, and have successfully loaded the fragment to my activity using the code below which links to a framelayout. So my fragment works (result 1);

val fragment : WonGamesByDiff = WonGamesByDiff.newInstance()
        val ft: FragmentTransaction = supportFragmentManager.beginTransaction()
        ft.replace(R.id.fragment_container,fragment)
        ft.commit()

below my framelayout, I have added

<androidx.viewpager2.widget.ViewPager2
                    android:id="@+id/viewpager_fragments"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

I have created an adapter based on a few different tutorials which had deprecated methods I have got it to this (which I accept could be wrong as can't get far enough to test it yet

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

class viewpager_adapter(fragmentManager: FragmentManager):FragmentPagerAdapter(fragmentManager,FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {


    override fun getItem(position: Int): Fragment {
        return when(position){
            0 -> WonGamesByDiff.newInstance()
            1 -> WonGamesByDiff.newInstance()
            else -> WonGamesByDiff.newInstance()
        }
    }
    override fun getCount() = 2
}

Here is where I am stuck so far. I get an error that a different type of adapter is expected and cannot seem to find people with the same issue on here

ERROR:Type mismatch. Required: (RecyclerView.Adapter<RecyclerView.ViewHolder!>?..RecyclerView.Adapter<*>?) Found: viewpager_adapter

val vpager: ViewPager2
        vpager = findViewById(R.id.viewpager_fragments)
        val adapterviewpager = viewpager_adapter(supportFragmentManager)
        vpager.setAdapter(adapterviewpager);

I wholly accept that the issue might not be what it is telling me if something before it isnt set up correctly.

Ultimately what I am trying to achieve is the ability to swipe through fragments rather than my current approach which is to stack them in a single scroll view.

If other code is needed to assess this please advise

EDIT FOLLOWING RESPONSE:

Although I am not technically migrating (I had managed to cobble a hybrid of viewpager and viewpager2 following different tutorials) I have changed my adapter as follows;

package com.example.sumitup

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

class ViewPagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {


    override fun getItemCount()=2

    override fun createFragment(position: Int): Fragment {
        return when(position){
            0 -> WonGamesByDiff.newInstance()
            1 -> WonGamesByDiff.newInstance()
            else -> WonGamesByDiff.newInstance()
        }
    }
}

And within my activity changed the activity code to

val vpager: ViewPager2
        vpager = findViewById(R.id.viewpager_fragments)
        val adapterviewpager = ViewPagerAdapter(FragmentActivity())
        vpager.adapter = adapterviewpager;

Whilst this no longer errors within the editor (or within build) I now get a fatal error when the activity loads:

java.lang.IllegalStateException: FragmentManager has not been attached to a host.

Final edit

I amended this

val adapterviewpager = ViewPagerAdapter(FragmentActivity())

To this:

val adapterViewPager = ViewPagerAdapter(this)

Which corrected my fatal error and now allows swipeable fragments


Solution

  • Use FragmentStateAdapter instead of FragmentPagerAdapter .

    • When ViewPager used PagerAdapter to page through views, use RecyclerView.Adapter with ViewPager2.
    • When ViewPager used FragmentPagerAdapter to page through a small, fixed number of fragments, use FragmentStateAdapter with ViewPager2.
    • When ViewPager used FragmentStatePagerAdapter to page through a large or unknown number of fragment, use FragmentStateAdapter with ViewPager2

    Pls Read the Migration Doc.