Issue
So my grocery project required me (with 3 weeks of android knowledge) to make a RecyclerView for the page that contains the category buttons. These buttons should bring the user to the fragment with respective product list.
The way I learned was that I need to create an xml for the item, put the recyclerView into the main.xml, and write an adapter.
I did that with the basic TextView example, in which I can easily put .text in the adapter. But in this case, my item is entirely made of one button. And I don't know how to call it in the adapter, because it's easier to use setText() for TextView.
I don't know how many buttons there will be, because they said they will provide the API for the project, which should also have the category button names.
This is what I have:
cat_unit.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/cat_btn"
android:background="#000000"
android:textColor="#ffffff"
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
This is my adapter:
CatAdapter.kt
package org.mp.chiproject01.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.recyclerview.widget.RecyclerView
import org.mp.chiproject01.R
class CatAdapter(var catList: ArrayList<String>, var context: Context): RecyclerView.Adapter<ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
var v: View = LayoutInflater.from(context).inflate(R.layout.cat_unit, parent, false)
return ViewHolder(v)
}
override fun getItemCount( ): Int {
return catList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// I don't know what to put in the bind
// Button will have different names, and I don't know how to
// Set the text for buttons
}
}
class ViewHolder(view: View): RecyclerView.ViewHolder(view){
var catBtn = view.findViewById<Button>(R.id.cat_btn)
}
And this is the Fragment with the RecyclerView:
class FragmentCategory : Fragment() {
var catList: ArrayList<String>()
//Should I use 'String' or 'Button' here?
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
//View inflater for Fragment
var view = inflater.inflate(R.layout.cat_unit, container, false)
// Layout Manager and Adapter for RecyclerView
view.recyclerViewmeat.layoutManager = LinearLayoutManager(context)
view.recyclerViewmeat.adapter = CatAdapter(catList, this.context!!)
//I don't know how if I can add them as 'String' or 'Button'
//Can I do the setOnClickListener on the button the Button way
//or do I have to write my own onClick to handle this?
return view
}
}
Thank you! And please let me know if there's any tip/good coding practice!
Solution
It seems you are having difficulties In understanding how RecyclerView
works.
Should I use 'String' or 'Button' here?
We usually pass a data list to the adapter class and this list will be used to fill data in RecyclerView views (So we will never pass buttons or anything like), and the RecyclerView takes responsibility of creating the views for us depending on the data list size that we passed in RecyclerView in CatAdapter
class in:
override fun getItemCount( ): Int {
return catList.size
}
Now for each position, RecyclerView will be creating a ViewHolder that will hold our Layout as View and that's what happens in onCreateViewHolder
in CatAdapter
:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
//Inflating our layout (inflaing simple words, it's just a process to convert xml layout to View.
var v: View = LayoutInflater.from(context).inflate(R.layout.cat_unit, parent, false)
//Creating a ViewHolder that holds the view inside it.
return ViewHolder(v)
}
The last thing, onBindViewHolder
is called whenever the ViewHolder is attached to the ReyclerView and this the suitable place to bind data (fill our views with data) and setting the click Listeners on the views (in your case buttons). So how to binds data and setOnClickListener on that Button?
first, take a look onBindViewHolder()
:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
}
In the parameters:
holder: ViewHolder
that holds our views we can use it to binds data and for click listeners.position: Int
of the current view, we will use this position to get data from our list (in your casecatList
).
Now you know, how to use onBindViewHolder
let's write the code (CatAdapter
class):
package org.mp.chiproject01.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.recyclerview.widget.RecyclerView
import org.mp.chiproject01.R
class CatAdapter(var catList: ArrayList<String>, var context: Context): RecyclerView.Adapter<ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
var v: View = LayoutInflater.from(context).inflate(R.layout.cat_unit, parent, false)
return ViewHolder(v)
}
override fun getItemCount( ): Int {
return catList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
//First, get data from catList by position.
val data = catList[position]
//Then, bind this data to the views (the button).
holder.catBtn.text = data
holder.catBtn.setOnClickListener {
//Do something when button clicked
}
}
}
class ViewHolder(view: View): RecyclerView.ViewHolder(view){
//catBtn should be val since it'll never change.
val catBtn = view.findViewById<Button>(R.id.cat_btn)
}
Note:
Make sure you're attaching your FragmentCategory
to your activity and you're passing data to catList
in your FragmentCategory
.
Answered By - Abed
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.