如何创建自适应尺寸的多图片网格?需整合RecyclerView与StaggeredGridLayoutManager
实现自适应图片的瀑布流网格(StaggeredGridLayoutManager + RecyclerView)
嘿,这需求我熟!用StaggeredGridLayoutManager搭配RecyclerView完全能搞定这个自适应尺寸的图片网格,我给你一步步拆解具体实现:
1. 准备布局文件
首先是主布局,只需要一个RecyclerView就行:
<?xml version="1.0" encoding="utf-8"?> <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="8dp"/>
然后是图片Item的布局,用ImageView来承载图片,注意设置scaleType为centerCrop保证图片填充,高度设为wrap_content来实现自适应:
<?xml version="1.0" encoding="utf-8"?> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="centerCrop" android:layout_margin="4dp"/>
2. 实现RecyclerView Adapter
Adapter负责加载图片并自适应调整item高度,这里用Glide来处理图片加载(当然你也可以用其他图片加载库),关键是获取图片的原始宽高,然后根据网格列宽计算出对应的item高度,保证图片比例不变:
class ImageAdapter(private val imageUrls: List<String>) : RecyclerView.Adapter<ImageAdapter.ImageViewHolder>() { inner class ImageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val imageView: ImageView = itemView.findViewById(R.id.imageView) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_image, parent, false) return ImageViewHolder(view) } override fun onBindViewHolder(holder: ImageViewHolder, position: Int) { val imageUrl = imageUrls[position] // 用Glide加载图片并计算自适应高度 Glide.with(holder.imageView.context) .load(imageUrl) .listener(object : RequestListener<Drawable> { override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean { return false } override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { resource?.let { val originalWidth = it.intrinsicWidth val originalHeight = it.intrinsicHeight // 获取屏幕宽度,计算单列的宽度(减去padding和margin) val screenWidth = holder.imageView.context.resources.displayMetrics.widthPixels val columnWidth = (screenWidth - (8 * 2) - (4 * 2)) / 2 // 按比例计算item高度 val targetHeight = (columnWidth * originalHeight) / originalWidth // 更新ImageView的布局参数 val params = holder.imageView.layoutParams params.height = targetHeight holder.imageView.layoutParams = params } return false } }) .into(holder.imageView) } override fun getItemCount(): Int = imageUrls.size }
3. 初始化RecyclerView
在Activity或Fragment里,给RecyclerView设置StaggeredGridLayoutManager和Adapter,同时可以添加一些优化设置:
class MainActivity : AppCompatActivity() { private lateinit var recyclerView: RecyclerView // 替换成你的图片链接列表 private val imageUrls = listOf( "https://example.com/image1.jpg", "https://example.com/image2.jpg", "https://example.com/image3.jpg", "https://example.com/image4.jpg" ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerView = findViewById(R.id.recyclerView) // 初始化StaggeredGridLayoutManager,设置为2列垂直布局 val layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL) // 关闭自动补全间隙,避免滚动时item跳动 layoutManager.gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_NONE recyclerView.layoutManager = layoutManager // 设置Adapter recyclerView.adapter = ImageAdapter(imageUrls) // 添加自定义间距(可选) recyclerView.addItemDecoration(SpacesItemDecoration(4)) } // 自定义间距装饰类 class SpacesItemDecoration(private val space: Int) : RecyclerView.ItemDecoration() { override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { outRect.left = space outRect.right = space outRect.top = space outRect.bottom = space } } }
4. 必要依赖(如果用Glide)
记得在Module级别的build.gradle里添加Glide的依赖:
dependencies { implementation 'com.github.bumptech.glide:glide:4.16.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' }
几个小提示
- 如果是本地图片资源,获取宽高的逻辑类似,直接用
Drawable的intrinsicWidth和intrinsicHeight即可 - 如果不想用Glide,也可以用
Picasso或者系统的BitmapFactory来处理图片加载和尺寸计算 - 如果需要支持横向瀑布流,把
StaggeredGridLayoutManager的方向改成HORIZONTAL就行
内容的提问来源于stack exchange,提问作者Yakov Shaikevich
相关产品推荐
相关产品推荐

