RecyclerView单元格wrap_content不适用于ConstraintLayout

问题描述

@H_502_0@期望

RecyclerView的ConstraintLayout类型的单元格布局可扩展到显示器的宽度和渲染内容的高度。

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" />
...

此布局实现可以对 CameraXFeed 开源应用中的 post_cell.xml 正常工作。

CameraXFeed image

@H_502_0@观察

在下面概述的代码中,使用与上面相同的RecyclerView单元布局,不会扩展到父视图显示的宽度和渲染内容的高度。尽管在ViewHolder中绑定了数据,但RecyclerView仍显示为空。

问题与布局无关,因为 FeedAdapter.kt 中的以下日志在ViewHolder的bind显示了预期的照片图像URL。

@H_502_0@实施

build.gradle

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

布局设计与期望部分中的相同。

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>

Android Studio设计预览确认布局应按照期望部分中所述进行操作。

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)
}
@H_502_0@尝试解决方
  1. photo_cell.xml RecyclerView项目布局中对父根CardView layout_height进行硬编码,并将ConstraintLayout设置为android:layout_height="match_parent"而不是android:layout_height="wrap_content"。 / strong>

这不是理想的选择,因为它需要根据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. 以编程方式设置布局的宽度和高度。

这并不理想,因为XML布局中定义的所有属性都被覆盖。

FeedAdapter.kt

override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val binding = PhotoCellBinding.inflate(inflater,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)
    }
@H_502_0@相关帖子

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)