Home > Software design >  How to get view binding to work with XML layout heights in RecyclerView.ViewHolder like they did wit
How to get view binding to work with XML layout heights in RecyclerView.ViewHolder like they did wit

Time:11-19

While trying to convert an application from the defunct Kotlin synthetics to the newer/supported view binding method, I ran into this issue where layouts are inflated but layout_height is being ignored in the inflated layouts. The result is a scrunched up view that doesn't look good.

    inner class InfoAdapter(val data: Array<String>) : androidx.recyclerview.widget.RecyclerView.Adapter<androidx.recyclerview.widget.RecyclerView.ViewHolder>() {
        private val header = 0
        private val item = 1
        private var clickListener: RecyclerClickListener? = null

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder {
            when (viewType) {
                item -> return ItemVH(StringRowBinding.inflate(layoutInflater))
                header -> return HeaderVH(InfoHeaderBinding.inflate(layoutInflater))
            }

            return ItemVH(StringRowBinding.inflate(layoutInflater))
        }

...

        inner class ItemVH(private val binding: StringRowBinding): androidx.recyclerview.widget.RecyclerView.ViewHolder(binding.root) {
            init {
                itemView.setOnClickListener { v ->
                    clickListener?.itemClicked(v, adapterPosition)
                }
            }
            fun bind(text: String) {
                binding.title.text = text
            }
        }

...
    }

string_row.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:background="?android:attr/selectableItemBackground">

    <TextView
        android:id="@ id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginEnd="16dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Body2"/>

</RelativeLayout>

The height of the relative layout is supposed to be 48dp but it appears that attribute is being ignored. Data does display and the layout height attribute worked fine with Kotlin synthetics.

I found this SO question related to Activity view binding but nothing specific for ViewHolder view binding. Related to the accepted answer of that question is the rhetorical question: What's the point of using the XYZBinding.inflater() method of view binding as recommended by Google to get rid of findViewById() calls if it is just going to ignore margins, height, and width of the inflated layout and the "fix" is basically to NOT use the inflater() call at all and just use findViewById()? That is, the accepted answer mostly defeats the purpose of inflating views with view binder and reintroduces findViewById(). At any rate, it's not obvious how to adapt that particular answer to this scenario.

CodePudding user response:

The problem is that you're using the overload of inflate() that doesn't specify the parent view. When you do this, any layout_ attributes on the root view are ignored (and replaced by default values). Try this instead:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder {
    when (viewType) {
        item -> return ItemVH(StringRowBinding.inflate(layoutInflater, parent, false))
        header -> return HeaderVH(InfoHeaderBinding.inflate(layoutInflater, parent, false))
    }

    return ItemVH(StringRowBinding.inflate(layoutInflater, parent, false))
}

Make sure that you pass false as the third parameter; RecyclerView itself will manage attaching the child views to the parent.

  • Related