Casting in RecyclerView Adapter? - android

May I know which one is better?
The first one we set the textView as TextView and we inflate the view and cast it to TextView type
The second one we set the textView as View type and we inflate it as type View
class MyViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyAdapter.MyViewHolder {
val textView = LayoutInflater.from(parent.context)
.inflate(R.layout.my_text_view, parent, false) as TextView
return MyViewHolder(textView)
}
or
class MyViewHolder(val textView: View) : RecyclerView.ViewHolder(textView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyAdapter.MyViewHolder {
val textView = LayoutInflater.from(parent.context)
.inflate(R.layout.my_text_view, parent, false)
return MyViewHolder(textView)
}

Like everything, it depends on more conditions. If you are using view holder like this, I mean, not using custom XML, it is better to use View, because if in any place you don't need any specific TextView property, then there is no point of using TextView.
But! If you want to use your custom XML file and use this view inside ViewHolder as TextView, then it should TextView since the beginning.

Related

RecyclerViewPool with same viewtype but different view bounds

I'm sharing a RecycledViewPool between different RecyclerViews with same view type. Although the view type has different view bounds. For eg: In RecyclerView1 the width of a single item is 100dp where as in RecyclerView2 the width of a single items is 80dp.
Now whenever i scroll through the elements of either of the RecyclerView the RecycledViewPool returns me ViewHolder of a different RecyclerView. So while scrolling in one RecyclerView i get items with width as 100dp as well as 80dp since the view type for both the RecyclerView are same.
Adapter for RecyclerView1:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<HomeData> {
val viewHolder = super.onCreateViewHolder(parent, viewType)
val view = viewHolder.itemView
view.setWidth(100)
return viewHolder
}
Adapter for RecyclerView2:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<HomeData> {
val viewHolder = super.onCreateViewHolder(parent, viewType)
val view = viewHolder.itemView
view.setWidth(80)
return viewHolder
}
Both the RecyclerView have the same view type and share the same viewpool here.
Am i missing some configuration while setting the viewpool?

Can't access view elements by LayoutInflater in Kotlin

I simply made an adapter for my recyclerview.like this :
class CustomerAdapter(mCtx:Context,val customers:ArrayList<Customer>):RecyclerView.Adapter<CustomerAdapter.ViewHolder>(){
and i have a xml layout file to inflate recycleview items.
But the problem is in onCreateViewHolder ... I can not access inflated elements ...
codes writed in my onCreateViewHolder method :
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomerAdapter.ViewHolder {
val v = LayoutInflater.from(parent.getContext()).inflate(R.layout.lo_customers, parent, false);
var txt = v.id
}
i can not access view elements by id .
Even if you capture the View, you cannot directly access the children's in the View. In-order to get hold of children's you need to use
findViewById(R.id.my_textView_id) on the View object.
Hence replace your v.txt by v.findViewById(R.id.my_text_view_id).
This is completely the wrong way to do it . onCreateViewHolder the function name itself says that it is meant only for inflating the view and doing nothing else. It should only be used for creating the ViewHolder . Even if you inflate your view and assign view from there , it is going to crash in the future . You have to inflate the view there and pass the parent view to another class which should extend RecyclerView.ViewHolder() .
So do it the following way :
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomerAdapter.ViewHolder {
val v = LayoutInflater.from(parent.getContext()).inflate(R.layout.lo_customers, parent, false);
}
Create an ViewHolder Class extending RecyclerView.ViewHolder :
class CustomViewHolder(val view: View) :
RecyclerView.ViewHolder(view) {
fun bind(model : Model) {
//Now here you can access all the components present in your layout in the following way and do the stuff you want with them:
val text = view.findViewById(R.id.viewid)
}
}
At gradle app
plugins {
id 'kotlin-android-extensions'
}
Or
apply plugin: 'kotlin-android-extensions'
Then your Activity Import this
import kotlinx.android.synthetic.main.activity_main.*
Try not to access from android.R, rather try like this:
CategoryAdapterHolder(LayoutInflater.from(parent.context).inflate(com.example.secondhand.R.layout.category_list, parent, false))

How to bind view from constructor in ViewHolder?

Could you please help me to bind views in view holder. I have read existing answer but not sure how to implement it in my case.
My holder looks like this and I don't have onCreateViewHolder
class MyViewHolder(
itemView: View,
private val myListener: MyListener
) : RecyclerView.ViewHolder(itemView) {
private val myLabel: AppCompatTextView = itemView.**findViewById**(R.id.myLabel)//**here need to remove findviewbyId**
fun bindView() {
itemView.background = ContextCompat.getDrawable(itemView.context, R.drawable.image)
myLabel.setOnClickListener {
myListener.myMethod()
}
}
}
Pretty close, what you are missing is the binding in the constructor
class MyViewHolder(
private val binding: YourLayoutBinding, //you can access it because is private val
...
) : RecyclerView.ViewHolder(binding.root) { //You need the view so pass the root view of the binding
//change your view to binding dot view
fun bindView() {
binding.background = ContextCompat.getDrawable(itemView.context, R.drawable.image) //in this case the background seems data binding so I'm treating it as such
binding.myLabel.setOnClickListener {
myListener.myMethod()
} //but here myLabel is a view contained inside the binding
}
}
And you are probably gonna have doubts regarding the onCreateViwHolder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = YourLayoutBinding.inflate(inflater, parent, false)
return MyViewHolder(binding, ...)
}
The trick is the bindings have an static method to inflate them

Why does my code not enter this adapter class?

I'm new to Kotlin and Android studio.
I'm trying to get a recycle view to work properly but I'm running into a problem when trying to use an adapter class.
I tried taking a look with breakpoints. but it seems to trigger on the very first line where the class gets defined. ( so class OrganisationsAdapter...etc ) and after that it skips the whole class, it doesnt even enter it.
I also don't get any exceptions.
Adapter Class
class OrganisationsAdapter(
private val myDataset: Array<String>
) : RecyclerView.Adapter<OrganisationsAdapter.MyViewHolder>() {
class MyViewHolder(
val textView: TextView
) : RecyclerView.ViewHolder(textView) {
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
var cell = LayoutInflater.from(parent.context).inflate(R.layout.example_item, parent, false)
val textView = cell.findViewById<TextView>(R.id.organisation_name)
return MyViewHolder(textView)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.textView.text = myDataset[position]
}
override fun getItemCount() = myDataset.size
}
**The line I use to call the class **
recyclerViewOrganisationFragment.adapter = OrganisationsAdapter(Array(getTopics().size) { i -> getTopics()[i].name })
You need to pass the inflated layout to ViewHolder instead of TextView
ex:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
var cell = LayoutInflater.from(parent.context).inflate(R.layout.example_item, parent, false)
return MyViewHolder(cell)
}
class MyViewHolder(
val itemView: View
) : RecyclerView.ViewHolder(itemView) {
//TODO get textview here itemView.findViewByID
}
Update the viewholder accordingly with textview etc.,
Thank you Lakhwinder.
"You need to pass on ArrayList on the constructor of the adapter, you are passing a size"

RecyclerView item width become wrap_content after migrating to view binding

Recently I move to Android View Binding from ButterKnife. All my layout are working well, but after migrating to View Binding, there is a weird behavior, all RecyclerView item have the layout_width as wrap_content instead of match_parent.
When I look at layout inspector tool, I see that the card view have wrap_content value for it's width.
But, I didn't change the xml file, so the width is actually still match_parent.
Do I miss something?
In your recycler onCreateViewHolder, instead of this
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemBinding.inflate(LayoutInflater.from(parent.context))
return ViewHolder(binding)
}
Use this 👇
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}

Categories

Resources