Android 实现双列图片瀑布流式布局

Android 实现双列图片瀑布流式布局

实现双列图片瀑布流布局,关键在于 RecyclerView 的 StaggeredGridLayoutManager 和图片的动态加载。以下是实现步骤:


1. 添加必要依赖

使用 Glide 加载图片。确保在 build.gradle 中添加依赖:

xml 复制代码
implementation 'com.github.bumptech.glide:glide:4.15.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.15.1'

2. 布局文件

主布局文件(activity_main.xml)
XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<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=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />

</androidx.constraintlayout.widget.ConstraintLayout>
子项布局文件(item_staggered_image.xml)
XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="4dp">

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop" />

</LinearLayout>

3. RecyclerView 配置

kotlin 复制代码
package com.check.waterfall

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)

        // 设置 StaggeredGridLayoutManager 为双列
        recyclerView.layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)

        // 模拟图片数据
        val imageUrls = listOf(
            "https://via.placeholder.com/300x200",
            "https://via.placeholder.com/300x300",
            "https://via.placeholder.com/300x400",
            "https://via.placeholder.com/300x500",
            "https://via.placeholder.com/300x600",
            "https://via.placeholder.com/300x700",
            "https://via.placeholder.com/300x800",
            "https://via.placeholder.com/300x900",
            "https://via.placeholder.com/300x1000",
            "https://via.placeholder.com/300x1100",
            "https://via.placeholder.com/300x1200",
            "https://via.placeholder.com/300x1300",
            "https://via.placeholder.com/300x1400",
            "https://via.placeholder.com/400x300",
            "https://via.placeholder.com/400x600",
            "https://via.placeholder.com/400x900",
            "https://via.placeholder.com/400x1200",
        )

        // 设置 Adapter
        recyclerView.adapter = StaggeredImageAdapter(imageUrls)
    }
}

4. 创建 RecyclerView Adapter

kotlin 复制代码
package com.check.waterfall

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide

class StaggeredImageAdapter(private val imageUrls: List<String>) :
    RecyclerView.Adapter<StaggeredImageAdapter.ViewHolder>() {

    private val itemHeights = mutableMapOf<Int, Int>() // 缓存每个位置的高度

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val imageView: ImageView = view.findViewById(R.id.image_view)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_staggered_image, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // 动态设置高度,使用缓存高度
        val params = holder.imageView.layoutParams
        if (!itemHeights.containsKey(position)) {
            itemHeights[position] = (400..800).random() // 仅随机生成一次高度
        }
        params.height = itemHeights[position] ?: 400
        holder.imageView.layoutParams = params

        // 使用 Glide 加载图片
        Glide.with(holder.itemView.context)
            .load(imageUrls[position])
            .placeholder(android.R.drawable.progress_indeterminate_horizontal)
            .error(android.R.drawable.stat_notify_error)
            .into(holder.imageView)
    }

    override fun getItemCount(): Int = imageUrls.size
}

5. 添加网络权限

XML 复制代码
<uses-permission android:name="android.permission.INTERNET" />

6. 效果展示

运行上述代码后,RecyclerView 将展示双列的瀑布流布局,图片加载时的高度随机化。使用 Glide 还可以处理图片的缓存和加载失败的情况。

相关推荐
AIsoft_86896 小时前
职场音频文件怎么整理?录音APP有哪些用法
android·音视频
booboosui6 小时前
第一批个人 Agent 用户正在卸载,问题不在模型,在它住在哪儿
android
洞见前行6 小时前
点击图标到内容出现,你的 App 在这几秒里做了什么:Android 冷启动全链路优化实战
android·性能优化·android studio
凯基迪科技6 小时前
芯片UID绑定修改 加密与逆向修改思路分析
android
Liben7 小时前
Weex开发踩坑记录
android·前端·ios
救救孩子把9 小时前
结构化输出为何“格式正确、答案错误”?JSON Schema 的能力边界
android·java·json·agent·agent服务
张小姐的猫10 小时前
【MySQL】事务
android·mysql·adb
你看我名字10 小时前
数眼智能 Search + Reader 实战:联网问答怎样避免“搜到了,却引用错了”
android·java·开发语言
恋猫de小郭10 小时前
最近 Android 有什么更新:Android Dev Summit 2026 技术解读
android·前端·flutter
Kapaseker11 小时前
删掉 1.1 万行 C 代码,Rust 正式接手 Android Binder
android·rust