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.