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)
}
Related
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?
How can I create a sectioned recyclerview in Kotlin based on list, and sections need to be grouped by one of the subtype of Data model?
You can have your ViewHolder be a sealed class with one child for each type of view you wanna display (subtypeA, subtypeB, maybe divider etc)
Then in your adapter you create the correct viewholder based on the viewType
override fun getItemViewType(position: Int): Int = when (getItem(position)) {
is XXXUIModel.SubTypeA -> SUBTYPE_A
is XXXUIModel.SubTypeB -> SUBTYPE_B
is XXXUIModel.Divider -> DIVIDER
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int,
): XXXAdapterViewHolder = when (viewType) {
SUBTYPE_A -> XXXViewHolder.SubYypeA
SUBTYPE_B -> XXXViewHolder.SubYypeB
DIVIDER -> XXXViewHolder.Divider
....
I want to make sure that in a recycler view (horizontal orientation and LinearLayoutManager set) that if I have 2 items to display they both get 50% of the parent layout. So both fit in the screen.
I have tried 2 approaches but neither works properly.
Approach 1:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val itemView = inflater.inflate(R.layout.horizontal_list_item_view, parent, false)
itemView.post(
object : Runnable {
override fun run() {
itemView.layoutParams.width = (parent.width * 0.5).toInt()
}
}
)
return ViewHolder(itemView)
}
This does not work unless I first scroll and then only the first item has its width adapted.
Approach 2:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val itemView = inflater.inflate(R.layout.horizontal_list_item_view, parent, false)
itemView.layoutParams.width = getScreenWidthFromUtils(context).x_width - MAGIC_NUMBER_WHICH_TAKES_PADDING_INTO_ACCOUNT)* 0.5).toInt()
return ViewHolder(itemView)
}
Approach 2 kind of works but obviously it can't be the solution as I doubt it has to be this complicated to achieve this.
What is the proper way to do this?
The GridLayoutManager will take care of giving your item the optimal size and space for the number of column you specify. In your case you want to have 2 items per row so your code should look like :
val gridLayoutManager = GridLayoutManager(context, 2, GridLayoutManager.HORIZONTAL, false)
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.
I want to create a list of views that align horizontally using recyclerview. I want to be split the width of the recyclerview equally so that all those views can fit inside a single line. view count is dynamic
Here is a simple final result, I created this using HTML and CSS.
Can I achieve the same in android using recyclerview?
Following is my recyclerview adapter, holder.root is the container for every view. I was thinking about getting the recyclerview width and divide that by number of views and setting that value as width for every view.
class ThreadsAdapter(
private val threads: ArrayList<ThreadInfo>
): RecyclerView.Adapter<ThreadsAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_progress_thread, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return threads.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.root.layoutParams.width = 40 // just testing
}
class ViewHolder(v: View): RecyclerView.ViewHolder(v) {
val progressBar: ProgressBar = v.findViewById(R.id.progressBar)
var root: ConstraintLayout = v.findViewById(R.id.root)
}
}
Eventually, I found this library on Github, allow me to use Flexbox layout in android
https://github.com/google/flexbox-layout