Android RecyclerView in Fragment (Kotlin)

February 27, 2019

MyQuoteListFragment.kt

class MyQuoteListFragment : Fragment() {

    companion object {

        @JvmStatic
        fun newInstance() =
            MyQuoteListFragment().apply {
                arguments = Bundle().apply {
                    // putInt(ARG_COLUMN_COUNT, columnCount)
                }
            }
    }

    private lateinit var adapter: MyQuoteAdapter

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

        arguments?.let {
            // columnCount = it.getInt(ARG_COLUMN_COUNT)
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.myquote_list, container, false)
    }

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

        val items = listOf(
            Quote("Premature optimization is the root of all evil", null),
            Quote("Any sufficiently advanced technology is indistinguishable from magic.", "Arthur C. Clarke"),
            Quote("Content 01", "Source"),
            Quote("Content 02", "Source"),
            Quote("Content 03", "Source"),
            Quote("Content 04", "Source"),
            Quote("Content 05", "Source")
        )

        adapter = MyQuoteAdapter()
        adapter.replaceItems(items)
        list.adapter = adapter
    }

    class MyQuoteAdapter : RecyclerView.Adapter<MyQuoteAdapter.ViewHolder>() {
        private var items = listOf<Quote>()


        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.myquote_list_item, parent, false)
            return ViewHolder(view)
        }

        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            val item = items[position]

            holder.contentTextView.text = item.content
            holder.sourceTextView.text = item.source
        }

        fun replaceItems(items: List<Quote>) {
            this.items = items
            notifyDataSetChanged()
        }

        override fun getItemCount(): Int = items.size

        inner class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer
    }

}

NOTE: I didn’t use MyQuoteAdapter constructor to pass in list of items as data is usually not available (e.g. database callback) when we initialized the UI. I prefer to initialize the UI first, then call replaceItems when data is available.

NOTE: We use LayoutContainer for ViewHolder to automatically bind views.

res/layout/myquote_list.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
        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:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".view.MyQuoteListFragment"
        >

    <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layoutManager=" LinearLayoutManager"
            tools:context=".view.MyQuoteListFragment"
            tools:listitem="@layout/myquote_list_item"/>
    
    <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@drawable/ic_add_black_24dp" />


</androidx.coordinatorlayout.widget.CoordinatorLayout>

res/layout/myquote_lis_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical">

    <TextView
            android:id="@+id/contentTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/text_margin"
            android:textAppearance="?attr/textAppearanceListItem"/>

    <TextView
            android:id="@+id/sourceTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/text_margin"
            android:textAppearance="?attr/textAppearanceListItem"/>
</LinearLayout>

Quote.kt (Model)

class Quote(val content: String = "",
            val source: String? = null)

NOTE: To handle click event in RecyclerView, refer to Handle RecyclerView Click Event With LiveData.

This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.