RecyclerView item width layout_width=“match_parent” does not match parent
Solution 1
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));
Solution 2
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.
Solution 3
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;
Solution 4
Calling to GridLayoutManager instead of LinearLayoutManager and put one column is most simple
From your xml:
<androidx.recyclerview.widget.RecyclerView
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="1"
...
Or from Kotlin:
recyclerView.layoutManager = GridLayoutManager(this,1)
Or from Java:
recyclerView.setLayoutManager(new GridLayoutManager (this, 1);
![Diyaa](https://i.stack.imgur.com/cLpjE.jpg?s=256&g=1)
Diyaa
Technology Head at Floward; Software Engineer | C# | JavaScript | Python Requeue and Foodiyoo app Co-Founder
Updated on August 23, 2020Comments
-
Diyaa almost 4 years
I'm using RecyclerView and I'm trying to make the width item of RecyclerView match_parent since I'm using
LinearLayoutManager.HORIZONTAL
<android.support.v7.widget.RecyclerView android:id="@+id/listOffersHits" android:layout_width="match_parent" android:layout_height="match_parent" />
custom_layout.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:layout_weight="1" android:layout_margin="2dp" card_view:cardCornerRadius="2dp"> <ImageView android:id="@+id/offerImage" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/item_selector" android:scaleType="fitXY" android:src="@drawable/offer" /> </android.support.v7.widget.CardView>
LayoutManager
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity(),LinearLayoutManager.HORIZONTAL, false); listOffersHits.setLayoutManager(linearLayoutManager);
ViewHolder
View view= LayoutInflater.from(parent.getContext()) .inflate(R.layout.custom_layout, parent, false); ViewOffersHolder viewHolder=new ViewOffersHolder(view); return viewHolder;
-
Diyaa almost 9 yearsI did it but no change.
-
Igor over 8 yearsThis one worked nicely for me. However: instead of using view.getLayoutParams().width = ..., I did view.setLayoutParams(new LinearLayout.LayoutParams(viewGroup.getWidth(), ViewGroup.LayoutParams.WRAP_CONTENT)); instead. The reason is that view.getLayoutParams might be null (which it was in my case for some weird reason).
-
RhetoricalRuvim about 8 years@Igor Thank you. I took this into account when making my edit above.
-
mafortis over 3 yearsor in kotlin you can use
val outMetrics = DisplayMetrics() val display = parent.display display?.getRealMetrics(outMetrics) itemView.layoutParams = RecyclerView.LayoutParams(outMetrics.widthPixels, RecyclerView.LayoutParams.MATCH_PARENT)
inside your adapteronCreateViewHolder
function right beforereturn