CardView layout_width="match_parent" does not match parent RecyclerView width
J

10

134

I have a fragment with contains a RecyclerView with layout_width="match_parent":

<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity$PlaceholderFragment" />

The item in the RecyclerView is a CardView also with layout_width="match_parent":

<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_gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    card_view:cardCornerRadius="4dp">

    <TextView
        android:layout_gravity="center"
        android:id="@+id/info_text"
        android:layout_width="match_parent"
        android:gravity="center"
        android:layout_height="match_parent"
        android:textAppearance="?android:textAppearanceLarge"/>
</android.support.v7.widget.CardView>

I inflate the item view as below:

public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        CardView v = (CardView) LayoutInflater.from(parent.getContext())
                .inflate(R.layout.card_listitem, null, true);

        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

But when I run the app, the CardView is rendered as wrap_content as shown below:

CardsBug

Note that this was run on emulator, not a real device.

Am I doing something wrong, or is it a bug?

Jitterbug answered 1/7, 2014 at 6:31 Comment(2)
When inflating the CardView, are you supplying the parent view with a true parameter?Feasible
Hi @NiekHaarman, please see the edit. I added the inflating code. And yes I have passed the true parameter.Jitterbug
F
306

The docs for inflate:

Inflate a new view hierarchy from the specified xml resource. Throws InflateException if there is an error.

Parameters
resource ID for an XML layout resource to load (e.g., R.layout.main_page) root
view to be the parent of the generated hierarchy (if attachToRoot is true), or else simply an object that provides a set of LayoutParams values for root of the returned hierarchy (if attachToRoot is false.)
attachToRoot Whether the inflated hierarchy should be attached to the root parameter? If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML. Returns The root View of the inflated hierarchy. If root was supplied and attachToRoot is true, this is root; otherwise it is the root of the inflated XML file.

It is important here to not supply true, but do supply the parent:

LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_listitem, parent, false);

Supplying the parent View lets the inflater know what layoutparams to use. Supplying the false parameter tells it to not attach it to the parent just yet. That is what the RecyclerView will do for you.

Feasible answered 1/7, 2014 at 6:55 Comment(8)
Could you explain why supplying true would cause it to be wrap_content in the first place?Airlike
The solution didn't work for me because the ListView's layout_width was wrap_content. Its weird because this shouldn't affect the list view! So my understanding is that when you provide false as a parameter to the layoutinflater, the ListView adds the list items to the ListView with layout parameters matching the ListView itself! :0Honduras
could you post a little more code, because I think I'm doing the same, but actually it isn't workingExceeding
I am inflating how you suggestion and match_parent is not working for me.Roots
I think the correct understanding is that when you set attachToRoot to false, you need to supply an object with defined LayoutParams value. That object is not necessarily the parent. "...simply an object that provides a set of LayoutParams values for root of the returned hierarchy (if attachToRoot is false.)..." But I don't understand why inflater cannot read the LayoutParams that defined in the CardView but need another object parameter to inform it?Pyongyang
If I use custom view, how to deal with it? I mean ViewHolder onCreateViewHolder(...) { View v = new MyItemView(parent.getContext); return new ViewHolder(v); }Yearling
@Feasible can you please help me to solve this issue #50066846Margerymarget
@Margerymarget No I cannot.Feasible
M
78

Use RelativeLayout as the immediate parent to CardView.

<RelativeLayout 
    android:layout_width="match_parent" ... >
    <CardView 
        android:layout_width="match_parent" ... >
    </CardView>
</RelativeLayout>
Monotone answered 10/1, 2016 at 10:36 Comment(6)
Yes this seemed to work for me as well. I was using LinearLayout and the suggestion above didn't work since I was already doing exactly that (ie not attaching to root, but providing a parent). You have to do both RelativeLayout + not attaching parent, but providing one.Carson
It works for me, but I don't know why do this can solve the problem. Does anyone can explain why?Opaline
it's been ages, android x is in production, still the bug is not fixed !Cembalo
the easiest way.Mota
I had a similar problem and this worked for me to correct the width of my card view but I am having a similar problem with the height? Can you suggest me something for that as well?Extrovert
Work like charmFenestra
H
14

This worked for me,

 View viewHolder= LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item, null, false);
 viewHolder.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));
 return new ViewOffersHolder(viewHolder);
Hymnody answered 24/9, 2016 at 16:53 Comment(0)
T
6

The way I did it is:

View view = mInflater.inflate(R.layout.row_cardview, null, true);
            WindowManager windowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
            int width = windowManager.getDefaultDisplay().getWidth();
            view.setLayoutParams(new RecyclerView.LayoutParams(width, RecyclerView.LayoutParams.MATCH_PARENT));

Explanation: In your onCreateViewHolde once you get card view, get the screen width and then set the layout param accordingly for card view.

Teel answered 31/12, 2015 at 10:37 Comment(2)
please improve this slightly. It basically says "Try this"Petition
Added Explanation. Please check and if need any further help, comment here.Teel
D
5

This appears to be fixed in 'com.android.support:recyclerview-v7:23.2.1'

See: RecyclerView wrap_content for further discussions.

Doyenne answered 21/3, 2016 at 11:51 Comment(0)
E
4

Default implementation force the use of wrap_content in the default layout manager :

  @Override
public LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
}

All you have to do is to override this method in your LayoutManager like this :

  @Override
public LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
}
Ebullience answered 4/11, 2016 at 20:51 Comment(0)
R
4

Simply set new layout params

view.setLayoutParams(new RecyclerView.LayoutParams(
    RecyclerView.LayoutParams.MATCH_PARENT,
    RecyclerView.LayoutParams.WRAP_CONTENT
));
Retirement answered 9/11, 2016 at 13:16 Comment(2)
I found doing this in onBindViewHolder() useful when using a custom view class that inherits from ConstraintLayout.Adrien
It is not a good answer because the margin that is been set to the layout will be affected.Augustus
K
2

This works for me

View view = inflator.inflate(R.layout.layout_item, ***null***, false);
Kiddush answered 21/7, 2016 at 20:43 Comment(0)
R
1

Use card_view:contentPadding with a negative value

<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:layout_width="match_parent"
    card_view:contentPadding="-4dp"
    card_view:cardElevation="0dp"
    android:layout_height="wrap_content">

It worked for me

Rixdollar answered 14/9, 2016 at 16:16 Comment(0)
T
-1

Wrap CardView in a Layout that has width:match_parent

Thinner answered 26/7, 2016 at 7:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.