Search code examples
androidarrayskotlinandroid-viewpagerfragmentpageradapter

How to use the FragmentPagerAdapter with unique unrelated fragments?


I am trying to implement a simple swiping action between the three main screens of my app (feed, forum & profile). I've been looking for guides online but they all seem to take the same approach and show how to implement the adapter using fragments that are simple instances of a basic class that for example just inflates a title and a number on the screen.

In my case, the fragments are not all instances of the same class and are completely different.

M problem lays in the FragmentPagerAdapter. I am not sure how to return each fragment in the getItem method.

I have tried the following but it doesn't except it as a valid return statement and is still expecting one:

class PagesPagerAdapter(fragmentManager: FragmentManager) : FragmentPagerAdapter(fragmentManager) {


    override fun getItem(p0: Int): Fragment? {

        return when (p0){

            0 -> FeedFragment.newInstance()
            1 -> BoardFragment.newInstance()
            2 -> ProfileFragment.newInstance()
            else -> FeedFragment.newInstance()
        }

    }



    override fun getCount(): Int {
        return 3
    }
}

This is an example of one of my fragments:

class FeedFragment : Fragment() {

    val galleryAdapter = GroupAdapter<ViewHolder>()


    private fun setUpGalleryAdapter() {

        feed_gallary.adapter = galleryAdapter
        val galleryLayoutManager = GridLayoutManager(this.context, 3)
        feed_gallary.layoutManager = galleryLayoutManager

        val dummyUri =
            "https://firebasestorage.googleapis.com/v0/b/dere-3d530.appspot.com/o/20150923_100950.jpg?alt=media&token=97f4b02c-75d9-4d5d-bc86-a3ffaa3a0011"

        val imageUri = Uri.parse(dummyUri)
        if (imageUri != null) {
            galleryAdapter.add(FeedImage(imageUri))
            galleryAdapter.add(FeedImage(imageUri))
            galleryAdapter.add(FeedImage(imageUri))
            galleryAdapter.add(FeedImage(imageUri))
            galleryAdapter.add(FeedImage(imageUri))


        }
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        setUpGalleryAdapter()

    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
        inflater.inflate(R.layout.fragment_feed, container, false)


    companion object {
        fun newInstance(): FeedFragment = FeedFragment()
    }

}

And this is my main activity:

class MainActivity : AppCompatActivity() {


    private lateinit var viewPager: ViewPager
    private lateinit var pagerAdapter: PagesPagerAdapter


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewPager = findViewById<ViewPager>(R.id.view_pager)

        pagerAdapter = PagesPagerAdapter(supportFragmentManager)
        viewPager.adapter = pagerAdapter

    }
}

I have also tried to define a variable currentFragment, have it reassigned for each of the when statements and have it be the return value, but as all my fragments are unique I am getting a type mismatch when trying to assign them all to one variable.

Is there some Array I can store the fragments in and then return the array position?

I feel like there is probably a simple elegant and common solution here.


Solution

  • Without seeing all of your code I cannot be sure but one thing to note is you must return an instance of your fragment not a reference to the class. Ex: FeedFragment() instead of FeedFragment.

    Also, your when statement does not have a default case resulting in a compile error for the getItem method as you have a code path that doesn't return anything. Try the following code for getItem

    override fun getItem(p0: Int): Fragment {
    
        when(p0){
            0 -> return FeedFragment.newInstance()
            1 -> return BoardFragment.newInstance()
            else -> return ProfileFragment.newInstance()
        }
    }