class Category_recycler_view (var arrayList: ArrayList<Category_Spinner_model>) :
RecyclerView.Adapter<Category_recycler_view.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.category_spinner_item,parent,false)
val spinner_modal : Category_Spinner_model? = arrayList.get(1)
val ico = v.findViewById<ImageView>(R.id.category_ico)
val text = v.findViewById<TextView>(R.id.category_text)
val dropdown_ico = v.findViewById<ImageView>(R.id.category_dropdowm)
ico?.setImageResource(spinner_modal!!.getIco())
text.text = spinner_modal!!.getTextt()
dropdown_ico.setImageResource(spinner_modal.getDropico())
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val itemsView = arrayList[position]
}
override fun getItemCount(): Int {
return arrayList.size
}
class ViewHolder (Itemview : View) : RecyclerView.ViewHolder(Itemview) {
}
}
I need every element of the array to display, but i can give only one index at a time how to display every element of the array modal
onCreateViewHolder() is only for creating a view holder that can be used by any list item. You need to populate it in onBindViewHolder().
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.category_spinner_item,parent,false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val spinner_modal = arrayList[position]
val ico = holder.itemView.findViewById<ImageView>(R.id.category_ico)
val text = holder.itemView.findViewById<TextView>(R.id.category_text)
val dropdown_ico = holder.itemView.findViewById<ImageView>(R.id.category_dropdowm)
ico?.setImageResource(spinner_modal.getIco())
text.text = spinner_modal.getTextt()
dropdown_ico.setImageResource(spinner_modal.getDropico())
}
However, you should avoid using findViewById in onBindViewHolder because then it has to search for the views again every time the view holder is recycled. Instead, you should create properties in your ViewHolder class for this. So a better complete solution is:
class Category_recycler_view (var arrayList: ArrayList<Category_Spinner_model>) :
RecyclerView.Adapter<Category_recycler_view.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.category_spinner_item,parent,false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val spinner_modal = arrayList[position]
holder.ico.setImageResource(spinner_modal.getIco())
holder.text.text = spinner_modal.getTextt()
holder.dropdown_ico.setImageResource(spinner_modal.getDropico())
}
override fun getItemCount(): Int {
return arrayList.size
}
class ViewHolder (Itemview : View) : RecyclerView.ViewHolder(Itemview) {
val ico: ImageView = Itemview.findViewById(R.id.category_ico)
val text: TextView = Itemview.findViewById(R.id.category_text)
val dropdownIco: ImageView = Itemview.findViewById(R.id.category_dropdowm)
}
}
suppose if you want to set text to the text view in recyclerView then you need to do like this , consider it as an example ~
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView.text = arrayList[position].someTextVariable
}
here someTextvariable is the variable under the model class which is of String Type
Related
I'm trying to create a RecycleView of EditText that update on the spot as you add EditText with a Button.
For reference, I'd like to have something that works like a checkbox question editing on a Gform , but only with EditTexts .
Here's my code :
Main Activity Code
class AjoutObjectifActivity : AppCompatActivity() {
//ArrayList used to add items to the RecyclerView
private var etapes: ArrayList<String> = ArrayList()
private lateinit var binding: ActivityAjoutObjectifBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAjoutObjectifBinding.inflate(layoutInflater)
setContentView(binding.root)
setupButtons()
}
//The click listener of my button
private fun setupButtons() {
binding.buttonAddEtape.setOnClickListener{
addEtape()
}
}
//The function that add one element to my ArrayList, and is supposed to reload my RecyclerView to add the corresponding EditText
//I know it is supposed to erase all the EditTexts contents as well, but I'm looking to repair this after I manage to add EditTexts
private fun addEtape() {
etapes.add("")
val adapterEtapes = EtapesAdapter(etapes)
binding.recyclerViewObjectifsEtapes.adapter = adapterEtapes
}
}
My "EtapesAdapter" Code
class EtapesAdapter(private val etapes: ArrayList<String>) : RecyclerView.Adapter<EtapesAdapter.EtapeViewHolder>() {
override fun getItemCount(): Int = etapes.size
override fun onCreateViewHolder(parent: ViewGroup, position: Int): EtapeViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.item_etapes_input, parent, false)
return EtapeViewHolder(view)
}
override fun onBindViewHolder(holder: EtapeViewHolder, position: Int) {
holder.bind(etapes[position])
}
class EtapeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val etape : TextView = itemView.findViewById(R.id.edit_text_etapes_objectif)
fun bind(etapes: String) = with(itemView){
etape.text = etapes
}
}
}
My Main Layout
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_objectifs_etapes"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>
My Item Layout
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/edit_text_etapes_objectif"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp" />
After a quick check of the varaibles with the debbuger, it seems that my ArrayList works perfectly and grows as you press the button, so I guess the error must be somewhere in the adapter.
I tried to do it with an Array first, but since you can't add size to it, I decided to use the ArrayList instead.
Remember that I'm kind of a beginner, so maybe I use the wrong type of variables or view, in that case, feel free to tell me !
Thanks in advance
Thanks Menno, this code sure was helpful.
Your "addEtape" function reinitialised the ArrayList completly, so I replaced it by puting "etapes.add("")", instead of calling "addEtape" in mainActivity
Here is the final code ;).
Main Activity
class AjoutObjectifActivity : AppCompatActivity() {
private var etapes: ArrayList<String> = ArrayList()
private lateinit var binding: ActivityAjoutObjectifBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAjoutObjectifBinding.inflate(layoutInflater)
setContentView(binding.root)
setupButtons()
}
private fun setupButtons() {
binding.buttonAddEtape.setOnClickListener{
addEtape()
}
}
private fun addEtape() {
val adapterEtapes = EtapesAdapter()
etapes.add("")
binding.recyclerViewObjectifsEtapes.adapter = adapterEtapes
binding.recyclerViewObjectifsEtapes.layoutManager =
LinearLayoutManager(this)
adapterEtapes.addEtapes(etapes)
}
}
The adapter
class EtapesAdapter : RecyclerView.Adapter<EtapesAdapter.EtapeViewHolder>() {
private val etapes = ArrayList<String>()
fun addEtapes(etapes: ArrayList<String>) {
this.etapes.addAll(etapes)
notifyDataSetChanged()
}
override fun getItemCount(): Int = etapes.size
override fun onCreateViewHolder(parent: ViewGroup, position: Int): EtapeViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.item_etapes_input, parent, false)
return EtapeViewHolder(view)
}
override fun onBindViewHolder(holder: EtapeViewHolder, position: Int) {
holder.bind(etapes[position])
}
class EtapeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val etape : TextView = itemView.findViewById(R.id.edit_text_etapes_objectif)
fun bind(etapes: String) = with(itemView){
etape.text = etapes
}
}
}
It works better if you keep track of the 'etapes' in the adapter itself, like this.
class EtapesAdapter : RecyclerView.Adapter<EtapesAdapter.EtapeViewHolder>() {
private val etapes = ArrayList<String>()
fun addEtape(etape: String) {
this.etapes.add(etape)
notifyDataSetChanged()
}
fun addEtapes(etapes: ArrayList<String>) {
this.etapes.addAll(etapes)
notifyDataSetChanged()
}
override fun getItemCount(): Int = etapes.size
override fun onCreateViewHolder(parent: ViewGroup, position: Int): EtapeViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.item_etapes_input, parent, false)
return EtapeViewHolder(view)
}
override fun onBindViewHolder(holder: EtapeViewHolder, position: Int) {
holder.bind(etapes[position])
}
class EtapeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val etape : TextView = itemView.findViewById(R.id.edit_text_etapes_objectif)
fun bind(etapes: String) = with(itemView){
etape.text = etapes
}
}
}
So now you can do this:
val adapterEtapes = EtapesAdapter()
binding.recyclerViewObjectifsEtapes.adapter = adapterEtapes
binding.recyclerViewObjectifsEtapes.layoutManager = LinearLayoutManager()
adapterEtapes.addEtapes(etapes)
and it should reload the list.
image
I couldn't find how to do the counter algorithm
here is the adapter i wrote for my viewpager
class ViewPagerAdapter(val images : List,val mContext: Context) :
RecyclerView.Adapter<ViewPagerAdapter.ViewPagerViewHolderClass>() {
inner class ViewPagerViewHolderClass(view: View) : RecyclerView.ViewHolder(view){
val viewPagerFoto : ImageView
init {
viewPagerFoto = view.findViewById(R.id.viewPagerFoto)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewPagerViewHolderClass {
val view = LayoutInflater.from(mContext).inflate(R.layout.item_view_pager,parent,false)
return ViewPagerViewHolderClass(view)
}
override fun onBindViewHolder(holder: ViewPagerViewHolderClass, position: Int) {
val image = images[position]
holder.viewPagerFoto.setImageResource(image)
}
override fun getItemCount(): Int {
return images.size
}
}
My home Fragment
I am performing operations on homefragment
class HomeFragment : Fragment() {
private lateinit var _binding : FragmentHomeBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = FragmentHomeBinding.inflate(inflater,container,false)
val images = listOf(
R.drawable.f1,
R.drawable.f2,
R.drawable.f3,
R.drawable.f4,
R.drawable.f5,
R.drawable.f6,
)
val adapter by lazy { ViewPagerAdapter(images,requireContext()) }
_binding.viewPager.adapter = adapter
return _binding.root
}
}
override fun onBindViewHolder(holder: ViewPagerViewHolderClass, position: Int) {
val image = images[position]
holder.viewPagerFoto.setImageResource(image)
}
You can use position parameter, if you want just use it on there.
But i suggest that use it on ViewPagerViewHolderClass with declaring new parameter named position and pass it over there.
In onBindViewHolder method you have position parameter. You can pass it to viewHolder and use it
I implemented a simple RecyclerView example, with multiple items selection possibility, using the selection library.
Here's my code:
class MainActivity : AppCompatActivity() {
private var listOfItems = ArrayList<Item>()
private var selectionTracker: SelectionTracker<Long>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView = findViewById<RecyclerView>(R.id.rvMainRecyclerView)
for (i in 0..32) {
listOfItems.add(Item(i, "Item $i"))
}
val recyclerViewAdapter = RecyclerViewAdapter(listOfItems)
recyclerView.adapter = recyclerViewAdapter
selectionTracker = SelectionTracker.Builder<Long>(
"Itemselection",
recyclerView,
MyItemKeyProvider(recyclerView),
MyItemDetailsLookup(recyclerView),
StorageStrategy.createLongStorage()
).build()
selectionTracker?.addObserver(
object: SelectionTracker.SelectionObserver<Long>() {
override fun onSelectionChanged() {
super.onSelectionChanged()
val itemsSelected = selectionTracker?.selection?.size()
Log.d("MainActivity", "$itemsSelected items selected")
}
}
)
recyclerViewAdapter.tracker = selectionTracker
}
}
class RecyclerViewAdapter(
val dataSet: ArrayList\<Item\>
): RecyclerView.Adapter\<RecyclerViewAdapter.ViewHolder\>() {
var tracker: SelectionTracker<Long>? = null
init {
setHasStableIds(true)
}
inner class ViewHolder(view: View): RecyclerView.ViewHolder(view) {
val textView: TextView
init {
textView = view.findViewById(R.id.tvRecyclerViewItemTitle)
}
fun getItemDetails(): ItemDetails<Long> {
return object : ItemDetails<Long>() {
override fun getPosition(): Int {
return adapterPosition
}
override fun getSelectionKey(): Long? {
return itemId
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater
.from(parent.context).inflate(R.layout.recycler_view_item, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val currentItem = dataSet[position]
holder.textView.text = currentItem.value
holder.itemView.isActivated = tracker!!.isSelected(position.toLong())
}
override fun getItemCount(): Int {
return dataSet.size
}
override fun getItemId(position: Int): Long {
return dataSet[position].id.toLong()
}
}
I'm curious why the onSelectionChanged (in MainActivity selectionTracker?.addObserver...) is triggered several times while I hold an item to start selection mode?
To be more precise, this is the use case:
Nothing is selected,
Long click on any item => selection mode activated; the item is selected
Here, "1 items selected" is being printed out as long as I hold the first item.
How can I change the background color of the selected item in RecyclerView Kotlin
Thank you from now
How to change the background color of only selected view in my recycle view example?only the background color of clicked itemview needs to be changed
OutTimeActiviyt
val linearLayoutManager = LinearLayoutManager(this)
layoutBnd.outRecylerView.layoutManager = linearLayoutManager
layoutBnd.outRecylerView.setHasFixedSize(false)
//IN RECYCLERVIEW
out_TimeList.clear()
val out_DataBase = this.openOrCreateDatabase("Park", Context.MODE_PRIVATE, null)
val recyclerCursor = out_DataBase.rawQuery("SELECT * FROM Money", null)
val listTimeIndex = recyclerCursor.getColumnIndex("MoneyListName")
while (recyclerCursor.moveToNext()) {
out_TimeList.add(recyclerCursor.getString(listTimeIndex))
}
recyclerCursor.close()
val recyclerMoneyListName = Out_Recyler_Adapter(out_TimeList)
layoutBnd.outRecylerView.adapter = recyclerMoneyListName
recyclerMoneyListName.setOnItemClickListener(object : Out_Recyler_Adapter.onItemClickListener{
override fun onItemClick(position: Int) {
Toast.makeText(this#OutTimeActivity, "Selected item:${position}", Toast.LENGTH_SHORT).show()
}
})
Out_TimeAdapter
class Out_Recyler_Adapter(private val out_TimeList: ArrayList<String>) :
RecyclerView.Adapter<Out_Recyler_Adapter.ViewHolder>() {
private lateinit var out_ClickListener: onItemClickListener
interface onItemClickListener {
fun onItemClick(position: Int)
}
fun setOnItemClickListener(listener: onItemClickListener) {
out_ClickListener = listener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.recyler_style, parent, false)
return ViewHolder(view, out_ClickListener)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val ItemsViewModel = out_TimeList[position]
holder.textView.text = ItemsViewModel
}
override fun getItemCount(): Int {
return out_TimeList.size
}
class ViewHolder(ItemView: View, listener: onItemClickListener) : RecyclerView.ViewHolder(ItemView) {
val textView: TextView = itemView.findViewById(R.id.style_txtParkingInfo)
init {
itemView.setOnClickListener {
listener.onItemClick(adapterPosition)
}
}
}
}
I have code in ListBukpotAdapter, how can I get data listener.OnClick(currentItem) to parse on other UpdateActivity
Error:
kotlin.UnitializedPropertyAccessExeption: lateinit property listener has not been initialized
class ListBukpotAdapter : RecyclerView.Adapter<ListBukpotAdapter.MyViewHolder>() {
private var bukpotList = emptyList<QrResultBukpot>()
private lateinit var listener: OnAdapterListener
interface OnAdapterListener {
fun OnClick(bukpotDataParsing: QrResultBukpot)
}
class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.custom_row_bukpot, parent, false))
}
override fun getItemCount(): Int {
return bukpotList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem = bukpotList[position]
holder.itemView.txtNomorBukpot.text = currentItem.nomorBukpot
holder.itemView.txtNpwpPemotong.text = currentItem.npwpPemotong
holder.itemView.txtMasaPajak.text = currentItem.masaPajak + " / " + currentItem.tahunPajak
holder.itemView.txtMixCode.text = currentItem.mixCode
holder.itemView.rowLayoutBukpot.setOnClickListener {
listener.OnClick(currentItem)
val context = holder.itemView.context
val intent = Intent(context, UpdateBukpotActivity::class.java)
context.startActivity(intent)
}
}
fun setDataBukpot(bukpot: List<QrResultBukpot>){
this.bukpotList = bukpot
notifyDataSetChanged()
}
}
You should initilaze your listener. Your listener variable is lateinit so before you use this, you need to initialize. You can give listener as a constructor parameter from your activity or fragment and can listen interface from your activity or fragment which contains recyclerview.