You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android RecyclerView设置数据后获取高度并重设高度实现方法

实现方案

直接在adapter.notifyDataSetChanged()调用后同步获取RecyclerView高度必然不准——适配器刷新触发的测量、布局流程是加入主线程消息队列异步执行的,同步执行的取高度逻辑跑在布局流程前面,拿到的永远是你初始设置的固定高度值。
根据你的场景选下面两种实现即可:

方式1:布局完成后直接取渲染高度(全LayoutManager兼容)

不需要手动计算item高度,等RecyclerView完成自身排版后直接拿测量值,线性布局、网格布局、瀑布流布局都能用,写法最简单。

// 完成数据更新、刷新适配器
adapter.notifyDataSetChanged();
// post的任务会在RecyclerView布局完成后执行
recyclerView.post(() -> {
    // 此时拿到的是内容渲染后的真实测量高度
    int realHeight = recyclerView.getMeasuredHeight();
    // 重设控件高度
    ViewGroup.LayoutParams params = recyclerView.getLayoutParams();
    params.height = realHeight;
    recyclerView.setLayoutParams(params);
});

注意:如果初始设置的固定高度小于内容总高度,RecyclerView会进入滚动模式,此时getMeasuredHeight()拿到的还是初始固定高度,这种场景请用方式2。


方式2:手动累加计算内容总高度(精度最高,不受初始高度影响)

自己遍历所有item累加高度,算出来的是所有内容完全展开无滚动的总高度,不受初始固定高度、滚动状态影响,适合需要精准展开所有内容的场景。

线性布局(LinearLayoutManager)计算逻辑

adapter.notifyDataSetChanged();
recyclerView.post(() -> {
    LinearLayoutManager lm = (LinearLayoutManager) recyclerView.getLayoutManager();
    int totalHeight = 0;
    int itemCount = adapter.getItemCount();
    for (int i = 0; i < itemCount; i++) {
        View itemView = lm.findViewByPosition(i);
        if (itemView == null) continue;
        // 累加item本身高度+上下margin
        RecyclerView.LayoutParams itemLp = (RecyclerView.LayoutParams) itemView.getLayoutParams();
        totalHeight += itemView.getMeasuredHeight() + itemLp.topMargin + itemLp.bottomMargin;
    }
    // 算上RecyclerView自身的上下内边距
    totalHeight += recyclerView.getPaddingTop() + recyclerView.getPaddingBottom();
    // 如果加了ItemDecoration,还要把对应decoration的高度加上
    // 重设高度
    ViewGroup.LayoutParams lp = recyclerView.getLayoutParams();
    lp.height = totalHeight;
    recyclerView.setLayoutParams(lp);
});

网格布局(GridLayoutManager)计算逻辑

网格布局同一行的item高度一致,不需要逐item累加,按行计算即可:

GridLayoutManager glm = (GridLayoutManager) recyclerView.getLayoutManager();
int spanCount = glm.getSpanCount();
int totalHeight = 0;
// 算总行数
int rowCount = (int) Math.ceil(adapter.getItemCount() * 1.0 / spanCount);
for (int row = 0; row < rowCount; row++) {
    int firstPosOfRow = row * spanCount;
    View itemView = glm.findViewByPosition(firstPosOfRow);
    if (itemView == null) continue;
    RecyclerView.LayoutParams itemLp = (RecyclerView.LayoutParams) itemView.getLayoutParams();
    totalHeight += itemView.getMeasuredHeight() + itemLp.topMargin + itemLp.bottomMargin;
}
totalHeight += recyclerView.getPaddingTop() + recyclerView.getPaddingBottom();
// 重设高度逻辑和线性布局一致

避坑点
  • 不推荐用OnGlobalLayoutListener实现,除非你记得在拿到高度后立刻移除监听,否则会多次触发重复设置高度的逻辑,post()方法会自动在单次布局完成后执行,没有内存泄漏风险。
  • 如果列表有头布局、尾布局、空布局,遍历计算高度的时候要把这些特殊item的高度一起算进去,不要遗漏。
  • 如果给RecyclerView设置了ItemDecoration,总高度要把decoration占用的高度也累加进去,否则最终高度会偏小。

内容的提问来源于stack exchange,提问作者PhongBM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 07:24:24