RecyclerView item width layout_width=“match_parent” does not match parent
I fixed the problem:
1- Get the screen size (width).
2- make the ViewHolder width same as screen size.
Below my code if any one need it.
WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
int width = windowManager.getDefaultDisplay().getWidth();
int height = windowManager.getDefaultDisplay().getHeight();
view.setLayoutParams(new RecyclerView.LayoutParams(width, RecyclerView.LayoutParams.MATCH_PARENT));
Note: See update at the very end of this post.
Old Answer:
The following worked for me:
view.getLayoutParams ().width = parentViewGroup.getWidth ();
, right after inflating the view 'view' .
It basically takes the width of the parent and replaces the new view's layout_width with the parent's width.
You can also add a check for MATCH_PARENT, to make sure it appears correctly in case you modify the XML to a different width in the future. So like this:
public ViewHolder onCreateViewHolder (ViewGroup parent, int type) {
View vItem = LayoutInflater.from (parent.getContext ())
.inflate (R.layout.bookmark_card, parent, false);
if (vItem.getLayoutParams ().width == RecyclerView.LayoutParams.MATCH_PARENT)
vItem.getLayoutParams ().width = parent.getWidth ();
return new ViewHolder (vItem);
}
It will only make it the parent width if the width was MATCH_PARENT before this.
EDIT:
Do be careful about excessive use of this fix, as a variation of it has caused me a layout bug. I did this:
public ViewHolder onCreateViewHolder (ViewGroup parent, int type) {
View vItem = LayoutInflater.from (parent.getContext ())
.inflate (R.layout.page_tile, parent, false);
if (vItem.getLayoutParams ().width == RecyclerView.LayoutParams.MATCH_PARENT)
vItem.getLayoutParams ().width = parent.getWidth ();
if (vItem.getLayoutParams ().height == RecyclerView.LayoutParams.MATCH_PARENT)
vItem.getLayoutParams ().height = parent.getHeight ();
return new ViewHolder (vItem);
}
That worked, but it did not update the width and height when the RecyclerView was resized. Therefore, one of two fixes to this fix can be applied:
- Check for RecyclerView adapter orientation, and only do this parent.getHeight (), etc., for the dimensions along which scrolling is allowed.
- Or, somewhere in the ViewHolder, save the original 'width' and 'height', and then redo this step every time in the onBindViewHolder () method.
The following fix seems to work:
public ViewHolder onCreateViewHolder (ViewGroup parent, int type) {
View vItem = LayoutInflater.from (parent.getContext ())
.inflate (R.layout.page_tile, parent, false);
ViewHolder holder = new ViewHolder (vItem); // Create view holder.
holder.vItem = vItem; // Save top-level View.
holder.vParent = parent; // Save its parent.
ViewGroup.LayoutParams lp = vItem.getLayoutParams ();
if (lp != null) { // Save the original width and height from lp:
holder.originalWidth = lp.width;
holder.originalHeight = lp.height;
refreshLayoutParams (holder); // Check for MATCH_PARENT.
} else holder.originalHeight = holder.originalWidth = 0;
return holder;
}
public void onBindViewHolder (ViewHolder holder, int position) {
... do work here ...
refreshLayoutParams (holder); // Check AGAIN for MATCH_PARENT.
}
private void refreshLayoutParams (ViewHolder holder) {
ViewGroup.LayoutParams lp = holder.vItem.getLayoutParams ();
View parent = holder.vParent;
if (parent == null) return; // Is there a parent to check against?
if (lp == null)
holder.vItem.setLayoutParams (lp =
new RecyclerView.LayoutParams (holder.originalWidth, holder.originalHeight));
if (holder.originalWidth == RecyclerView.LayoutParams.MATCH_PARENT)
lp.width = parent.getWidth (); // Check width.
if (holder.originalHeight == RecyclerView.LayoutParams.MATCH_PARENT)
lp.height = parent.getHeight (); // Check height.
}
Note Also: If you use this approach of resizing inside the onBindViewHolder () method, you will also need to getAdapter ().notifyDataSetChanged () inside the Activity.onSizeChanged ()!
In short, the main idea is: check for MATCH_PARENT on every bind, not just on create view holder. This way resizing the RecyclerView works too.
UPDATE: As of RecyclerView v7:23.2.1 at least, it seems they have fixed it so that now these custom fixes are no longer necessary. RecyclerView itself should now recognize both WRAP_CONTENT and MATCH_PARENT settings.