web-dev-qa-db-fra.com

CardView layout_width = "match_parent" ne correspond pas à la largeur de RecyclerView parent

J'ai un fragment avec contient un RecyclerView avec 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" />

L'élément dans le RecyclerView est un CardView également avec 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>

Je gonfle la vue d'article comme ci-dessous:

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;
    }

Mais lorsque je lance l'application, CardView est rendu sous la forme wrap_content comme indiqué ci-dessous:

CardsBug

Notez que ceci a été exécuté sur un émulateur, pas sur un vrai périphérique.

Est-ce que je fais quelque chose de mal, ou est-ce un bug?

116
ProgrAmmar

La documentation pour inflate:

Gonflez une nouvelle hiérarchie de vues à partir de la ressource XML spécifiée. Lève InflateException s'il y a une erreur.

Paramètres
ressource ID pour une ressource de présentation XML à charger (par exemple, R.layout.main_page) root
view être le parent de la hiérarchie générée (si attachToRoot est true), ou simplement un objet fournissant un ensemble de valeurs LayoutParams pour la racine de la hiérarchie renvoyée (si attachToRoot est faux.)
attachToRoot Si la hiérarchie gonflée doit être attachée au paramètre racine? Si la valeur est false, root est uniquement utilisé pour créer la sous-classe correcte de LayoutParams pour la vue racine dans le fichier XML. Renvoie La vue racine de la hiérarchie gonflée. Si root a été fourni et que attachToRoot a la valeur true, il s'agit de root; sinon, il s'agit de la racine du fichier XML gonflé.

Il est important ici de ne pas fournir la valeur true, mais de fournir le parent :

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

Fournir la vue parent permet à l'inflateur de savoir quelle mise en page utiliser. Si vous fournissez le paramètre false, il indique à de ne pas l'attacher au parent pour l'instant. C’est ce que le RecyclerView fera pour vous.

279
nhaarman

Utilisez RelativeLayout comme parent immédiat de CardView.

<RelativeLayout 
    Android:layout_width="match_parent" ... >
    <CardView 
        Android:layout_width="match_parent" ... >
    </CardView>
</RelativeLayout>
57
Ganesh Kanna

Cela a fonctionné pour moi

 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);
11
anurag_dake

La façon dont je l'ai fait est:

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));

Explication: Dans votre onCreateViewHolde, une fois que vous obtenez une vue de carte, obtenez la largeur de l'écran, puis définissez le paramètre de disposition en conséquence pour la vue de carte.

6
Rahul

Cela semble être corrigé dans 'com.Android.support:recyclerview-v7:23.2.1'

Voir: RecyclerView wrap_content pour des discussions ultérieures.

5
speedynomads

Il suffit de définir de nouveaux paramètres de mise en page

view.setLayoutParams(new RecyclerView.LayoutParams(
    RecyclerView.LayoutParams.MATCH_PARENT,
    RecyclerView.LayoutParams.WRAP_CONTENT
));
4
V. Kalyuzhnyu

L'implémentation par défaut force l'utilisation de wrap_content dans le gestionnaire de disposition par défaut:

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

Tout ce que vous avez à faire est de remplacer cette méthode dans votre LayoutManager comme ceci:

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

Ça marche pour moi

View view = inflator.inflate(R.layout.layout_item, ***null***, false);
2
DiRiNoiD

Utilisez card_view: contentPadding avec une valeur négative

<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">

Ça a fonctionné pour moi

1
Vladimir Salguero