RecyclerView getLayoutParams returns null(有时)

RecyclerView getLayoutParams returns null (sometimes)

我有一个 RecyclerView,为此我有一个自定义适配器,我已将 LayoutManager 设置为 FlexboxLayoutManager。对于每个 child,我想将 FlexGrow 设置为 1。

在 Google 的示例中,demo-cat-gallery (https://github.com/google/flexbox-layout),他们在 ViewHolder 中这样做:

void bindTo(Drawable drawable) {
    mImageView.setImageDrawable(drawable);
    ViewGroup.LayoutParams lp = mImageView.getLayoutParams();
    if (lp instanceof FlexboxLayoutManager.LayoutParams) {
        FlexboxLayoutManager.LayoutParams flexboxLp = (FlexboxLayoutManager.LayoutParams) lp;
        flexboxLp.setFlexGrow(1.0f);
    }
}

然后由 onBindViewHolder 中的 RecyclerView.Adapter 调用。这工作正常,但是当我在我的应用程序中执行相同操作时,它只会为某些项目设置 FlexGrow,而不会为顶部的项目设置 FlexGrow。我意识到对于某些项目(看似随机),getLayoutParams() 返回 null,但对于其他项目,它返回正确的 FlexboxLayoutManager.LayoutParams.

我意识到不同之处在于 Cat-gallery 示例中,onCreateViewHolder 正在做

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.viewholder_cat, parent, false);
    return new CatViewHolder(view);
}

在我的应用程序中我正在做

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
    return new MyViewHolder(new MyCustomView(getContext()));
}

似乎用 parent 的引用膨胀意味着 getLayoutParams() 永远不会为空,所以将我的代码更改为

View v = new MyCustomView(getContext());
parent.addView(v);
return new MyViewHolder(v);

它现在可以正常工作,始终设置 setFlexGrow()。然而,这感觉不对 - 我知道你并不是要明确地将视图添加到 RecyclerView parent.

所以我的问题是:

1 - 为什么 LayoutParams 对于某些项目随机为空,但对于其他项目却没问题?

2 - 我怎样才能让 LayoutParams 始终被设置,而不做像 'parent.addView(v);' 这样可怕的事情,或者这样做真的可以吗?

谢谢:)

这似乎是 FlexboxLayoutManager 的错误。我试过

parent.addView(v);

但这产生了非常奇怪的崩溃。

事实证明,虽然 FlexboxLayoutManager 在 onBindViewHolder 之前可能不会附加 LayoutParams,但它会在 onViewAttachedToWindow 之前附加 LayoutParams。所以你可以像这样设置 LayoutParams:

override fun onViewAttachedToWindow(holder: ViewHolder<View>) {
    super.onViewAttachedToWindow(holder)
    holder.itemView.updateLayoutParams {
        // Whatever
    }
}

旧答案:仍然有效,但比较笨拙。

最后我产生了这个解决方法:

parent.addView(v);
ViewGroup.LayoutParams params = v.getLayoutParams();
parent.removeView(v);
v.setLayoutParams(params);