3

Expect

The RecyclerView's cell layout of type ConstraintLayout to expand to the display's width and rendered content's height.

post_cell.xml

<androidx.cardview.widget.CardView 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/card"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/postImage"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:contentDescription="@string/post_image_alt"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="@string/feed_image_ratio"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:srcCompat="@tools:sample/backgrounds/scenic" />
...

This layout implementation works as expected for the post_cell.xml in the CameraXFeed open-source app.

CameraXFeed image

Observe

Using the same RecyclerView cell layout above, does not expand to the parent view display's width and rendered content's height in the code outlined below. The RecyclerView displays as empty despite the data being bound in the ViewHolder.

The issue is isolated to the layout, as the log below in FeedAdapter.kt displays the expected photo image URLs in bind of the ViewHolder.

Implement

build.gradle

dependencies {
    implementation "androidx.constraintlayout:constraintlayout:1.1.3"
    implementation "androidx.cardview:cardview:1.0.0"
}

The layout design is the same as in the Expect section.

photo_cell.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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/card"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:elevation="@dimen/card_elevation"
    android:focusable="true">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/selectableItemBackgroundBorderless"
        android:translationZ="0dp">

        <ImageView
            android:id="@+id/postImage"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:contentDescription="@string/photo_image_alt"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="@string/feed_image_ratio"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:srcCompat="@tools:sample/backgrounds/scenic" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

The Android Studio Design preview confirms the layout should work as described in the Expect section.

Android Studio Design view

fragment_feed.xml

<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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".view.FeedFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

FeedAdapter.kt

val DIFF_UTIL = object : DiffUtil.ItemCallback<Photo>() {
    override fun areItemsTheSame(oldItem: Photo, newItem: Photo) = oldItem.id == newItem.id
    override fun areContentsTheSame(oldItem: Photo, newItem: Photo) = oldItem == newItem
}

class FeedAdapter : PagedListAdapter<Photo, FeedAdapter.ViewHolder>(DIFF_UTIL) {

    inner class ViewHolder(private val binding: PhotoCellBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(photo: Photo) {
            // Logs valid valid URLs as expected from 'photo.largeImageURL'.
            Log.v(LOG_TAG, "Debug photo ${photo.largeImageURL}")
            binding.postImage.setPostImage(photo.largeImageURL)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        return ViewHolder(PhotoCellBinding.inflate(inflater, parent, false))
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        getItem(position)?.let { holder.bind(it) }
    }
}

Glide.kt

fun ImageView.setPostImage(image: String) {
    Glide.with(context)
        .load(image)
        .placeholder(R.drawable.ic_content_placeholder)
        .error(R.drawable.ic_error)
        .into(this)
}

Attempt Solution

  1. Hard code the parent root CardView layout_height in the photo_cell.xml RecyclerView item layout and set ConstraintLayout to android:layout_height="match_parent" instead of android:layout_height="wrap_content".

This is not ideal as it requires specifying the dimensions for different devices as opposed to the layout rendering based upon the image height dynamically with wrap_content.

photo_cell.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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/card"
    android:layout_width="match_parent"
    android:layout_height="500dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:translationZ="0dp">


        <ImageView
            android:id="@+id/postImage"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:contentDescription="@string/photo_image_alt"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="@string/feed_image_ratio"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:srcCompat="@tools:sample/backgrounds/scenic" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
  1. Programmatically set the layout width and height.

This is not ideal because all of the attributes defined in the XML layout are overwritten.

FeedAdapter.kt

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val binding = PhotoCellBinding.inflate(inflater, parent, false)
        binding.card.layoutParams = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            // Sets the height to the display width to create a 1:1 aspect ratio.
            Resources.getSystem().displayMetrics.widthPixels
        )
        return ViewHolder(binding)
    }

Related Posts

AdamHurwitz
  • 9,758
  • 10
  • 72
  • 134
  • Follow This Link - https://stackoverflow.com/questions/55211279/recyclerview-in-constraintlayout-is-not-showing-properly – Android Developer Aug 20 '20 at 13:04
  • Thank you for the note @AndroidDeveloper. However, adding `app:layout_constrainedHeight="true"` per the linked post, did not fix the ImageView height rendering issue. – AdamHurwitz Aug 20 '20 at 18:56
  • Why don't you use `wrap_content` for height for the ImageView ? – Nongthonbam Tonthoi Aug 22 '20 at 12:36
  • Great suggestion @NongthonbamTonthoi. I've tried `wrap_content` in the code in question above without success. Programmatically or hard-coding the layout size is still the only workaround despite implementing ConstraintLayout's dynamic sizing successfully in other applications like the [sample](https://github.com/AdamSHurwitz/CameraXFeed#-cameraxfeed) above. – AdamHurwitz Sep 04 '20 at 16:34

0 Answers0