18

I am trying to play around with new ConstraintLayout. And I made the layout for my RecyclerView's row. It has ConstraintLayout as root element which width is set to match_parent and when I run my app it renders just as expected

correct width

It works well until I put data binding section in my XML and the root element henceforth is layout tag which wraps ConstraintLayout and it results in some unpredictable change in behavior of ConstraintLayout - it's width henceforth doesn't renders as match_parent, it only takes small part of display width, though it's still set to match_parent in XML. I also tried to set width to some fixed value and the result was the same

enter image description here

I suspect that Data Binding processor kinda strips attributes from ConstrainLayout when process layouts during the build process. Is there any way to get things work correctly? My layout

<layout xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <import type="android.view.View"/>
        <variable
            name="post"
            type=".entity.Post"/>
        <variable
            name="data"
            type=".entity.LinkPostData"/>
    </data>

    <android.support.constraint.ConstraintLayout
        android:id="@+id/constraintLayout"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="16dp">
        ....
    </android.support.constraint.ConstraintLayout>
</layout>

And adapter:

class PostsAdapter(): RecyclerView.Adapter<PostsAdapter.PostItemViewHolder>() {

    private val posts: MutableList<Post> = ArrayList()

    fun setPosts(domains: List<Post>) {
        this.posts.clear()
        this.posts.addAll(domains)
        notifyDataSetChanged()
    }

    override fun getItemViewType(position: Int): Int {
        return super.getItemViewType(position)
    }

    override fun onBindViewHolder(holder: PostItemViewHolder?, position: Int) {
        val post = posts[position]

        holder?.binding?.post = post
        holder?.binding?.data = post.data as LinkPostData
        holder?.binding?.executePendingBindings()
    }

    override fun getItemCount() = this.posts.size

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): PostItemViewHolder {
        val binding = ItemPostBinding.inflate(LayoutInflater.from(parent?.context))
        return PostItemViewHolder(binding)
    }

    class PostItemViewHolder(val binding: ItemPostBinding): RecyclerView.ViewHolder(binding.root) {

    }
}
Oleg Osipenko
  • 2,409
  • 1
  • 20
  • 28
  • Can you post your layouts `xml`, and also relevant code for your `Adapter` & `RecyclerView`? – yennsarah Jul 11 '16 at 06:28
  • I edited my question, but the cause is found - it's incompatibility of DataBinding and `ConstraintLayout` and question is how to make it work together – Oleg Osipenko Jul 11 '16 at 07:45
  • 1
    I can tell you that databinding is definitely not the problem. I have been using databinding and the constraint layout since its release and never had any problem. And also they're can't really be any problem. Databinding works by generating a new normal layout file from the one you wrote. You can actually look at it in your build folder. Somewhere in generated. – Xaver Kapeller Jul 11 '16 at 07:57
  • 2
    And by the way: you should move all namespace declarations to the layout tag. You are declaring the android namespace on the constraint layout. – Xaver Kapeller Jul 11 '16 at 07:58
  • @XaverKapeller thanks for sharing. Finally I managed to figure out real cause of the problem – Oleg Osipenko Jul 11 '16 at 15:44

2 Answers2

39

Thanks to @Xaver Kapeller I managed to figure out the real cause. And it was my adapter code. To make it work I had to change onCreateViewHolder() method as follows:

override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): PostItemViewHolder {
    val binding = ItemPostBinding.inflate(LayoutInflater.from(parent?.context), parent, false)
    return PostItemViewHolder(binding)
}

Providing ViewGroup gives expected result

Community
  • 1
  • 1
Oleg Osipenko
  • 2,409
  • 1
  • 20
  • 28
-1

Although I am not using databinding, I was having the same issue.

Turns out that it was a bug in the constraint layout and was fixed in beta5, so if your view inflate code is correct, and you still have this issue, upgrading your dependency to com.android.support.constraint:constraint-layout:1.1.0-beta5 or newer should fix it. It's out of beta now, so you should use 1.1.0.

Tim
  • 41,901
  • 18
  • 127
  • 145