Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
198 views
in Technique[技术] by (71.8m points)

android - Use of binding breaks RecyclerView item layout

I am building an Android app with Kotlin and decided to replace the calls to findViewById and use binding. It all works fine but specifically, when I change an Adapter for a RecyclerView it breaks the item layout.

Original code with findViewById:

class WeightListAdapter(val weights: List<WeightWithPictures>, val onWeightItemClickListener: OnWeightItemClickListener) : RecyclerView.Adapter<WeightListAdapter.WeightHolder>()  {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeightListAdapter.WeightHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item_weight, parent, false)
        return WeightHolder(view)
    }

    override fun onBindViewHolder(holder: WeightListAdapter.WeightHolder, position: Int) {
        val weightWithPictures = weights[position]
        holder.bind(weightWithPictures)
    }

    override fun getItemCount() = weights.size

    inner class WeightHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
        private lateinit var weight: Weight
        private val weightValueView: TextView = this.itemView.findViewById(R.id.weightValue)
        private val weightDateView: TextView = this.itemView.findViewById(R.id.weightDate)
        private val weightImageView: ImageView = this.itemView.findViewById(R.id.weightImage) as ImageView

And this is the layout:

enter image description here

But then whenever I use binding:

class WeightListAdapter(val weights: List<WeightWithPictures>, val onWeightItemClickListener: OnWeightItemClickListener) : RecyclerView.Adapter<WeightListAdapter.WeightHolder>()  {

    private var _binding: ListItemWeightBinding? = null
    private val binding get() = _binding!!

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeightListAdapter.WeightHolder {
        _binding = ListItemWeightBinding.inflate(LayoutInflater.from(parent.context))
        val view = binding.root
        return WeightHolder(view)
    }

    override fun onBindViewHolder(holder: WeightListAdapter.WeightHolder, position: Int) {
        val weightWithPictures = weights[position]
        holder.bind(weightWithPictures)
    }

    override fun getItemCount() = weights.size

    inner class WeightHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
        private lateinit var weight: Weight
        private val weightValueView: TextView = binding.weightValue
        private val weightDateView: TextView = binding.weightDate
        private val weightImageView: ImageView = binding.weightImage

The layout breaks:

enter image description here

Any ideas about what am I doing wrong here? Is it a bug?

P.S - For now, I am just adding the annotation to ignore bindings as documented here for the item view but I would really like to understand what's wrong.

question from:https://stackoverflow.com/questions/65865527/use-of-binding-breaks-recyclerview-item-layout

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your binding needs to be inflated in the context of its parent so its root view's layout params will take effect:

binding = ListItemWeightBinding.inflate(LayoutInflater.from(parent.context), parent, false)

I think it will also give you problems that you are creating a binding property for the Adapter if you try to use it long term. Each ViewHolder holds a distinct view with a distinct binding instance. It's working now because you use it only for the ViewHolder instantiation immediately after setting each instance. But if that's all your intent is, you should just pass the binding to the constructor of your ViewHolder and omit the adapter's property.

By the way, this is the sort of pattern I use for ViewHolders. Less code. Note, it doesn't have to be an inner class.

class WeightHolder(binding: ListItemWeightBinding) : RecyclerView.ViewHolder(binding.root), View.OnClickListener {

    fun bind(item: WeightWithPictures) {
        with (binding) {
            // set data for views here
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...