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.
Remove this in the layout.
android:layout_weight="1"
And set layout params for item in adapter once again.
View view= LayoutInflater.from(parent.getContext()) .inflate(R.layout.custom_layout, parent, false);view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.MATCH_PARENT));ViewOffersHolder viewHolder=new ViewOffersHolder(view);return viewHolder;