如何解决RecyclerView单元格wrap_content不适用于ConstraintLayout
期望
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 正常工作。
观察
在下面概述的代码中,使用与上面相同的RecyclerView单元布局,不会扩展到父视图显示的宽度和渲染内容的高度。尽管在ViewHolder中绑定了数据,但RecyclerView仍显示为空。
问题与布局无关,因为 FeedAdapter.kt 中的以下日志在ViewHolder的bind
中显示了预期的照片图像URL。
实施
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设计预览确认布局应按照期望部分中所述进行操作。
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)
}
尝试解决方案
- 在 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>
- 以编程方式设置布局的宽度和高度。
这并不理想,因为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)
}
相关帖子
- match_parent width does not work in RecyclerView
- View in RecyclerView does not match parent width
- RecyclerView children match_parent
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。