I have a RecyclerView, for which I have a custom Adapter, and I have set the LayoutManager to be a FlexboxLayoutManager. For every child, I want to set FlexGrow to be 1.
In Google's example, demo-cat-gallery (https://github.com/google/flexbox-layout), they do this in the 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);
}
}
This is then called by the RecyclerView.Adapter in onBindViewHolder. This works fine, but when I did the same in my app, it would only setFlexGrow for some items, and never the ones at the top. I realised that for some items (seemingly randomly), getLayoutParams() was returning null, but for others it was returning the correct FlexboxLayoutManager.LayoutParams.
I realised the difference was that in the Cat-gallery example, onCreateViewHolder was doing
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);
}
while in my app I was doing
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
return new MyViewHolder(new MyCustomView(getContext()));
}
It seems that inflating with a reference to the parent means that getLayoutParams() is never null, so changed my code to
View v = new MyCustomView(getContext());
parent.addView(v);
return new MyViewHolder(v);
And it now works correctly, with setFlexGrow() always being set. However, this feels wrong - I know you're not meant to explicitly add views to the RecyclerView parent.
So my question is:
1 - Why were LayoutParams randomly null for some items, but fine for others?
2 - How can I get LayoutParams to always be set, without doing something horrible like 'parent.addView(v);', or is it actually alright to do this?
Thanks :)
This appears to be a bug with FlexboxLayoutManager. I tried doing
parent.addView(v);
But this produced very strange crashes.
It turns out that while FlexboxLayoutManager may not attach LayoutParams before onBindViewHolder
, it will have done so before onViewAttachedToWindow
. So you can setup the LayoutParams like:
override fun onViewAttachedToWindow(holder: ViewHolder<View>) {
super.onViewAttachedToWindow(holder)
holder.itemView.updateLayoutParams {
// Whatever
}
}
OLD ANSWER: Still valid, but clumsier.
In the end I produced this work-around:
parent.addView(v);
ViewGroup.LayoutParams params = v.getLayoutParams();
parent.removeView(v);
v.setLayoutParams(params);