Home > OS >  Implementing Viewpager2 in a fragment with Recycler view
Implementing Viewpager2 in a fragment with Recycler view

Time:01-12

I'm trying to implement viewpager2 in a fragment which shows a list of notes with Recycler View. I tried different solutions but I'm unable to figure it out.

Here is my fragment_notes_list.xml :

<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@ id/notes_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

list_item_notes.xml used to display recycler view viewholder:

<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@ id/card_pertanyaan"
    android:layout_width="match_parent"
    android:layout_height="96dp"
    android:layout_marginLeft="16dp"
    android:layout_marginTop="12dp"
    android:layout_marginRight="16dp"
    android:clickable="true"
    android:foreground="?selectableItemBackground"
    card_view:cardBackgroundColor="#595959"
    card_view:cardCornerRadius="8dp"
    card_view:contentPadding="10dp">

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@ id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@ id/notes_title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="8dp"
            android:text="Title"
            android:textColor="@color/white"
            app:layout_constraintBottom_toTopOf="@ id/notes_body"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_chainStyle="packed" />

        <TextView
            android:id="@ id/notes_body"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:textColor="@color/white"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@ id/notes_title" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

Relevant snippets from fragment class NotesListFragment.kt :

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

        notesRecyclerView =
            view.findViewById(R.id.notes_recycler_view) as RecyclerView
        registerForContextMenu(notesRecyclerView)
        notesRecyclerView.layoutManager = LinearLayoutManager(context)
        notesRecyclerView.adapter = adapter
        return view
    }

private inner class ScreenSlidePagerAdapter(fa: Fragment) : FragmentStateAdapter(fa) {

        override fun getItemCount(): Int = NUM_PAGES

        override fun createFragment(position: Int): Fragment {
            return if (position == 0) {
                NotesListFragment()
       

 } else {
            CalenderFragment()
        }
    }
}



override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        notesListViewModel.notesListLiveData.observe(
            viewLifecycleOwner,
            Observer { notes ->
                notes?.let {
                    Log.i(TAG, "got notes")
                    updateUI(notes)
                }
            })
    }

private inner class NotesAdapter(var notes: List<Notes>) : RecyclerView.Adapter<NotesHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotesHolder {
            val view = layoutInflater.inflate(R.layout.list_item_notes, parent, false)

           /* viewPager = view.findViewById(R.id.pager)

            val pagerAdapter = ScreenSlidePagerAdapter(this@NotesListFragment)
            viewPager.adapter = pagerAdapter */

            return NotesHolder(view)
        }

        override fun getItemCount() = notes.size

        override fun onBindViewHolder(holder: NotesHolder, position: Int) {
            val note = notes[position]
            holder.bind(note)
     



 }
    }

I'm confused should I add ViewPager2 with FrameLayout in list_item_notes.xml? But then how can I implement ScreenSliderPagerAdapter for it?

CodePudding user response:

I assume you would like to have 2 fragments: list and calendar and thats why you need to implement ViewPager2. Your NotesListFragment looks good. You have recyclerview with notes there, but what you want now is to provide list of NotesListFragment and CalendarFragment which will be scrollable in left/right direction. First, extract ScreenSlidePagerAdapter outside of your fragment code. Next you have to add ViewPager2 to your parent activity/fragment

<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@ id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />

And then in your parent activity/fragment pair it with adapter like this way:

val viewPager = findViewById(R.id.pager)
val pagerAdapter = ScreenSlidePagerAdapter(this)
viewPager.adapter = pagerAdapter

You can read more about this in official docs: https://developer.android.com/training/animation/screen-slide-2

CodePudding user response:

I had tried implementing ViewPager in Main Activity earlier also. But this way i cannot close viewpager fragments since they are always visible. How do I get around this?

here is my main activity after the changes you suggested:

class MainActivity : AppCompatActivity(),
NotesListFragment.Callbacks {
    private lateinit var viewPager: ViewPager2

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

        viewPager = findViewById(R.id.pager)
        val pagerAdapter = ScreenSlidePagerAdapter(this)
        viewPager.adapter = pagerAdapter
}

override fun onNotesSelected(notesId: UUID) {
        val fragment = NotesFragment.newInstance(notesId)
        supportFragmentManager
            .beginTransaction()
            .replace(R.id.fragment_container, fragment)
            .addToBackStack(null)
            .commit()
    }

    fun onNotesDeleted(notes: Notes) {
        val fragment = NotesListFragment()
        supportFragmentManager
            .beginTransaction()
            .replace(R.id.fragment_container, fragment)
            .commit()
        Toast.makeText(this, "Note Deleted", Toast.LENGTH_SHORT).show()
    }

mainactivity.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@ id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

</FrameLayout>

here are some screenshots,

https://drive.google.com/drive/folders/13ITZqcaeDeydCe0tW2Iu7VoSGSZnrlkg?usp=sharing

  •  Tags:  
  • Related