CardView layout_width = "match_parent" non corrisponde alla larghezza di RecyclerView principale


123

Ho un frammento con contiene un RecyclerView con 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'elemento in RecyclerView è un CardView anche con 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>

Gonfio la visualizzazione dell'oggetto come di seguito:

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

Ma quando eseguo l'app, CardView viene visualizzato come wrap_content come mostrato di seguito:

CardsBug

Nota che questo è stato eseguito su un emulatore, non su un dispositivo reale.

Sto facendo qualcosa di sbagliato o è un bug?


Quando gonfi il CardView, stai fornendo alla vista genitore un vero parametro?
nhaarman

Ciao @NiekHaarman, leggi la modifica. Ho aggiunto il codice di gonfiaggio. E sì, ho passato il vero parametro.
ProgrAmmar

Risposte:


291

I documenti per inflate:

Gonfia una nuova gerarchia di visualizzazione dalla risorsa xml specificata. Genera InflateException in caso di errore.

Parametri ID
risorsa per una risorsa di layout XML da caricare (ad esempio, R.layout.main_page)
vista root per essere il genitore della gerarchia generata (se attachToRoot è true), oppure semplicemente un oggetto che fornisce una serie di valori LayoutParams per root della gerarchia restituita (se attachToRoot è falso.)
attachToRoot Se la gerarchia gonfiata deve essere allegata al parametro root? Se false, root viene utilizzato solo per creare la sottoclasse corretta di LayoutParams per la vista root nell'XML. Restituisce La vista principale della gerarchia gonfiata. Se root è stato fornito e attachToRoot è vero, questo è root; altrimenti è la radice del file XML gonfiato.

E 'importante per non fornire vero, ma non fornire il genitore:

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

Fornire la parentvista consente all'inflater di sapere quali parametri di layout utilizzare. Fornire il falseparametro gli dice di non collegarlo al genitore ancora. Questo è ciò RecyclerViewche farà per te.


4
La soluzione non ha funzionato per me, perché il ListView di layout_widthstato wrap_content. È strano perché questo non dovrebbe influire sulla visualizzazione elenco! Quindi la mia comprensione è che quando fornisci false come parametro a layoutinflater, ListView aggiunge gli elementi dell'elenco a ListView con parametri di layout che corrispondono allo stesso ListView! : 0
reubenjohn

1
potresti pubblicare un po 'più di codice, perché penso di fare lo stesso, ma in realtà non funziona
rodi

1
Sto gonfiando il modo in cui suggerisci e match_parent non funziona per me.
Zapnologica

3
Penso che la comprensione corretta sia che quando si imposta attachToRoot su false, è necessario fornire un oggetto con un valore LayoutParams definito. Quell'oggetto non è necessariamente il genitore. "... semplicemente un oggetto che fornisce un insieme di valori LayoutParams per la radice della gerarchia restituita (se attachToRoot è falso.) ..." Ma non capisco perché inflater non possa leggere il LayoutParams definito in CardView ma necessita un altro parametro oggetto per informarlo?
hjchin

1
Se utilizzo la visualizzazione personalizzata, come gestirla? Voglio direViewHolder onCreateViewHolder(...) { View v = new MyItemView(parent.getContext); return new ViewHolder(v); }
Kross

65

Usa RelativeLayout come genitore immediato di CardView.

<RelativeLayout 
    android:layout_width="match_parent" ... >
    <CardView 
        android:layout_width="match_parent" ... >
    </CardView>
</RelativeLayout>

Sì, questo sembrava funzionare anche per me. Stavo usando LinearLayout e il suggerimento sopra non ha funzionato poiché stavo già facendo esattamente quello (cioè non collegandomi a root, ma fornendo un genitore). Devi fare sia RelativeLayout + non allegare genitore, ma fornirne uno.
chubbsondubs

1
Per me funziona, ma non so perché questo può risolvere il problema. Qualcuno può spiegare perché?
Johnny

1
sono passati anni, Android X è in produzione, ancora il bug non è stato risolto!
Muhammad Naderi

la via più facile.
Abdurahman Popal

Ho avuto un problema simile e questo ha funzionato per me per correggere la larghezza della mia visualizzazione della scheda, ma ho un problema simile con l'altezza? Puoi suggerirmi qualcosa anche per questo?

12

Questo ha funzionato per 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);

6

Il modo in cui l'ho fatto è:

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

Spiegazione: Nel tuo onCreateViewHolde una volta ottenuta la visualizzazione a schede, ottieni la larghezza dello schermo e quindi imposta il parametro di layout di conseguenza per la visualizzazione a schede.


1
per favore, miglioralo leggermente. In pratica dice "Prova questo"
Drew

Spiegazione aggiunta. Per favore controlla e se hai bisogno di ulteriore aiuto, commenta qui.
Rahul


4

Basta impostare nuovi parametri di layout

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

Ho trovato questa operazione in onBindViewHolder () utile quando si utilizza una classe di visualizzazione personalizzata che eredita da ConstraintLayout.
Rasmusob

Non è una buona risposta perché il margine che è stato impostato sul layout ne risentirà.
Emi Raz

4

L'implementazione predefinita forza l'uso di wrap_content nel gestore layout predefinito:

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

Tutto quello che devi fare è sovrascrivere questo metodo nel tuo LayoutManager in questo modo:

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

2

Questo funziona per me

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

1

Usa card_view: contentPadding con un valore negativo

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

Ha funzionato per me


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.