Abhimanyu
Abhimanyu

Reputation: 14777

0dp layout_width not working as expected for constraint layout child in recyclerview item

Minified working layout code,

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/recyclerview_item_layout_root_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.textview.MaterialTextView
            android:id="@+id/recyclerview_item_layout_textview_fact"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

The above code renders the recycler view as expected.
But as per docs,

You cannot use match_parent for any view in a ConstraintLayout. Instead use "match constraints" (0dp).

So, I replaced this line,

android:layout_width="match_parent"

with this

android:layout_width="0dp"

But, it is not working. The recyclerview is not visible.

Complete repo is open-source, https://github.com/Abhimanyu14/cat-fact

Recyclerview adapter code if required,

class HomeFragmentRecyclerViewAdapter :
    PagingDataAdapter<CatFact, HomeFragmentRecyclerViewAdapter.MainActivityRecyclerViewHolder>(
        CatFactDiffCallback
    ) {
    
    class MainActivityRecyclerViewHolder(private var binding: RecyclerviewItemLayoutBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(catFact: CatFact?) {
            catFact?.let {
                binding.recyclerviewItemLayoutTextviewFact.text = String.format(
                    binding.root.context.resources.getString(R.string.recyclerview_item_layout_fact),
                    catFact.id,
                    catFact.fact
                )
            }
        }
    }
    
    object CatFactDiffCallback : DiffUtil.ItemCallback<CatFact>() {
        override fun areItemsTheSame(oldItem: CatFact, newItem: CatFact): Boolean {
            return oldItem.id == newItem.id
        }
        
        override fun areContentsTheSame(oldItem: CatFact, newItem: CatFact): Boolean {
            return oldItem == newItem
        }
    }
    
    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): MainActivityRecyclerViewHolder {
        return MainActivityRecyclerViewHolder(
            RecyclerviewItemLayoutBinding.inflate(
                LayoutInflater.from(
                    parent.context
                )
            )
        )
    }
    
    override fun onBindViewHolder(holder: MainActivityRecyclerViewHolder, position: Int) {
        holder.bind(getItem(position))
    }
}

Upvotes: 3

Views: 3706

Answers (1)

Cheticamp
Cheticamp

Reputation: 62831

As you stated the docs say:

You cannot use match_parent for any view in a ConstraintLayout. Instead use "match constraints" (0dp).

The docs used to also say that the result would be unpredictable. I guess "unpredictable" means "it works" (sometimes.)

Using 0dp is correct. The problem you are having is that the view you're inflating needs a reference to its parent view to know how big it can be, so you need to give a parent reference (2nd argument in inflate below) but not attach the inflated view to the parent view (3rd argument) since the RecyclerView will take care of that.

return MainActivityRecyclerViewHolder( RecyclerviewItemLayoutBinding
    .inflate( LayoutInflater.from( parent.context ), parent, false )

Upvotes: 9

Related Questions