132

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?

ProgrAmmar
  • 3,045
  • 4
  • 19
  • 26

10 Answers10

305

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.

nhaarman
  • 98,571
  • 55
  • 246
  • 278
  • Could you explain why supplying true would cause it to be `wrap_content` in the first place? – joeschmidt45 Mar 18 '15 at 21:10
  • 4
    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! :0 – reubenjohn Jun 18 '15 at 15:48
  • 1
    could you post a little more code, because I think I'm doing the same, but actually it isn't working – M4rk Sep 10 '15 at 02:14
  • 1
    I am inflating how you suggestion and match_parent is not working for me. – Zapnologica Oct 07 '15 at 10:00
  • 3
    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? – hjchin Nov 11 '16 at 06:14
  • 1
    If I use custom view, how to deal with it? I mean `ViewHolder onCreateViewHolder(...) { View v = new MyItemView(parent.getContext); return new ViewHolder(v); }` – krosshj May 25 '17 at 02:12
  • @nhaarman can you please help me to solve this issue https://stackoverflow.com/questions/50066346/cardview-gridlayout-with-recyclerview-is-not-fit-for-all-screen-sizes-in-andro – Nikson Apr 27 '18 at 16:30
  • @Nikson No I cannot. – nhaarman Apr 28 '18 at 12:19
78

Use RelativeLayout as the immediate parent to CardView.

<RelativeLayout 
    android:layout_width="match_parent" ... >
    <CardView 
        android:layout_width="match_parent" ... >
    </CardView>
</RelativeLayout>
abhijit.mitkar
  • 246
  • 2
  • 7
Ganesh Kanna
  • 2,269
  • 1
  • 19
  • 29
  • 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. – chubbsondubs May 18 '16 at 20:14
  • 1
    It works for me, but I don't know why do this can solve the problem. Does anyone can explain why? – Johnny Jun 03 '16 at 02:14
  • 2
    it's been ages, android x is in production, still the bug is not fixed ! – Muhammad Naderi Apr 08 '19 at 06:31
  • 2
    the easiest way. – Abdurahman Popal Aug 03 '19 at 10:29
  • 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? –  Mar 04 '20 at 14:27
  • Work like charm – Mrunal Apr 13 '20 at 08:39
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);
anurag_dake
  • 988
  • 13
  • 15
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.

Rahul
  • 739
  • 4
  • 15
  • 31
5

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

See: RecyclerView wrap_content for further discussions.

Community
  • 1
  • 1
speedynomads
  • 2,632
  • 1
  • 26
  • 24
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);
}
issamux
  • 1,336
  • 1
  • 19
  • 35
4

Simply set new layout params

view.setLayoutParams(new RecyclerView.LayoutParams(
    RecyclerView.LayoutParams.MATCH_PARENT,
    RecyclerView.LayoutParams.WRAP_CONTENT
));
Vlad
  • 7,997
  • 3
  • 56
  • 43
2

This works for me

View view = inflator.inflate(R.layout.layout_item, ***null***, false);
DiRiNoiD
  • 1,281
  • 2
  • 18
  • 24
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

Vladimir Salguero
  • 5,609
  • 3
  • 42
  • 47
-1

Wrap CardView in a Layout that has width:match_parent

Samuel Moshie
  • 570
  • 1
  • 5
  • 20