RecyclerView搭配GridLayoutManager首次加载子项绘制尺寸异常求助
问题原因
onCreateViewHolder执行时GridLayoutManager还未完成首次布局测量,加上父布局的进入动画会干扰首次测量阶段的父容器可用宽度计算,导致手动修改子项LayoutParams的逻辑未生效,首次加载的子项沿用了XML中配置的固定宽度@dimen/my200dp,出现尺寸异常。- 滚动后新生成的子项是在LayoutManager完成全局测量、列宽已确定之后创建的,修改LayoutParams的逻辑可以正常生效,所以显示符合预期。
解决方案
方案1:调整子项XML配置(推荐)
直接把子项根布局的宽度改为match_parent,删除onCreateViewHolder中手动修改LayoutParams的逻辑,GridLayoutManager会自动平分每列宽度给子项,无需额外动态修改。
修改后的子项代码示例:
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="@dimen/my100dp" android:layout_margin="@dimen/my10dp" android:padding="@dimen/my15dp" app:cardCornerRadius="@dimen/my10dp"> <!-- 子项内部布局 --> </com.google.android.material.card.MaterialCardView>
方案2:延迟修改子项布局参数
如果必须保留动态修改宽高的逻辑,可通过post方法等待子项测量完成后再修改布局参数:
修改后的onCreateViewHolder代码示例:
public ProductViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { ItemProductBinding bind = ItemProductBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); bind.getRoot().post(() -> { ViewGroup.LayoutParams params = bind.getRoot().getLayoutParams(); if (orientation == RecyclerView.VERTICAL) { params.width = GridLayoutManager.LayoutParams.MATCH_PARENT; } else { params.height = GridLayoutManager.LayoutParams.MATCH_PARENT; } bind.getRoot().setLayoutParams(params); }); return new ProductViewHolder(bind.getRoot()); }
方案3:避开动画阶段加载数据
在父布局的进入动画结束监听中再给RecyclerView设置Adapter、加载数据,避免动画过程中的测量异常影响子项绘制。
内容的提问来源于stack exchange,提问作者Monsef Khalfaoui
相关产品推荐
相关产品推荐

