CardView layout_width = "match_parent" no coincide con el ancho del RecyclerView padre

123

Tengo un fragmento 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" />

El elemento en RecyclerView es un CardView también 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>

Inflo la vista del elemento de la siguiente manera:

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

Pero cuando ejecuto la aplicación, el CardView se representa como wrap_content como se muestra a continuación:

CardsBug

Tenga en cuenta que esto se ejecutó en el emulador, no en un dispositivo real.

¿Estoy haciendo algo mal o es un error?

ProgrAmmar
fuente
Al inflar CardView, ¿está proporcionando a la vista principal un parámetro verdadero?
nhaarman 01 de
Hola @NiekHaarman, mira la edición. Agregué el código de inflado. Y sí, he pasado el verdadero parámetro.
ProgrAmmar

Respuestas:

291

Los documentos para inflate:

Inflar una nueva jerarquía de vistas desde el recurso xml especificado. Lanza InflateException si hay un error.

Parámetros de ID de
recurso para un recurso de diseño XML para cargar (por ejemplo, R.layout.main_page)
vista raíz para ser el padre de la jerarquía generada (si attachToRoot es verdadero), o simplemente un objeto que proporciona un conjunto de valores de LayoutParams para root de la jerarquía devuelta (si attachToRoot es falso).
attachToRoot ¿ Se debe adjuntar la jerarquía inflada al parámetro raíz? Si es falso, la raíz solo se usa para crear la subclase correcta de LayoutParams para la vista raíz en el XML. Devuelve La vista raíz de la jerarquía inflada. Si se proporcionó root y attachToRoot es verdadero, esto es root; de lo contrario, es la raíz del archivo XML inflado.

Aquí es importante no suministrar verdadero, pero el padre:

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

Al proporcionar la parentvista, el inflador sabe qué parámetros de diseño usar. Proporcionar el falseparámetro le dice que no lo adjunte al padre por el momento. Eso es lo RecyclerViewque hará por ti.

nhaarman
fuente
44
La solución no funcionó para mí porque el ListView de layout_widthera wrap_content. ¡Es extraño porque esto no debería afectar la vista de lista! Entonces, entiendo que cuando proporciona falso como parámetro al layoutinflater, ¡ListView agrega los elementos de lista a ListView con parámetros de diseño que coinciden con ListView! : 0
reubenjohn
1
¿podría publicar un poco más de código, porque creo que estoy haciendo lo mismo, pero en realidad no está funcionando
rodi
1
Estoy inflando cómo su sugerencia y match_parent no funciona para mí.
Zapnologica
3
Creo que la comprensión correcta es que cuando establece attachToRoot en falso, debe proporcionar un objeto con un valor de LayoutParams definido. Ese objeto no es necesariamente el padre. "... simplemente un objeto que proporciona un conjunto de valores de LayoutParams para la raíz de la jerarquía devuelta (si attachToRoot es falso.) ..." Pero no entiendo por qué inflater no puede leer los LayoutParams que se definieron en el CardView pero necesitan otro parámetro de objeto para informarlo?
hjchin
1
Si uso una vista personalizada, ¿cómo lidiar con ella? Quiero decirViewHolder onCreateViewHolder(...) { View v = new MyItemView(parent.getContext); return new ViewHolder(v); }
Kross
65

Utilice RelativeLayout como padre inmediato de CardView.

<RelativeLayout 
    android:layout_width="match_parent" ... >
    <CardView 
        android:layout_width="match_parent" ... >
    </CardView>
</RelativeLayout>
Ganesh Kanna
fuente
Sí, esto parecía funcionar para mí también. Estaba usando LinearLayout y la sugerencia anterior no funcionó ya que ya estaba haciendo exactamente eso (es decir, no adjuntar a la raíz, sino proporcionar un padre). Tienes que hacer tanto RelativeLayout + no adjuntar padre, sino proporcionar uno.
chubbsondubs
1
A mí me funciona, pero no sé por qué esto puede resolver el problema. ¿Alguien puede explicar por qué?
Johnny
1
Han pasado años, Android X está en producción, ¡aún así el error no está solucionado!
Muhammad Naderi
la forma más fácil.
Abdurahman Popal
Tuve un problema similar y esto me funcionó para corregir el ancho de la vista de mi tarjeta, pero ¿tengo un problema similar con la altura? ¿Puedes sugerirme algo para eso también?
12

Esto funcionó para mí

 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
fuente
6

La forma en que lo hice es:

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

Explicación: en su onCreateViewHolde una vez que obtenga la vista de tarjeta, obtenga el ancho de la pantalla y luego configure el parámetro de diseño en consecuencia para la vista de tarjeta.

Rahul
fuente
1
por favor, mejora esto un poco. Básicamente dice "Prueba esto"
Drew
Explicación agregada. Por favor verifique y si necesita más ayuda, comente aquí.
Rahul
4

Simplemente configure nuevos parámetros de diseño

view.setLayoutParams(new RecyclerView.LayoutParams(
    RecyclerView.LayoutParams.MATCH_PARENT,
    RecyclerView.LayoutParams.WRAP_CONTENT
));
Vlad
fuente
Descubrí que hacer esto en onBindViewHolder () es útil cuando utilizo una clase de vista personalizada que hereda de ConstraintLayout.
Rasmusob
No es una buena respuesta porque el margen que se ha establecido en el diseño se verá afectado.
Emi Raz
4

La implementación predeterminada fuerza el uso de wrap_content en el administrador de diseño predeterminado:

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

Todo lo que tiene que hacer es anular este método en su LayoutManager de esta manera:

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

Esto funciona para mi

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

Use card_view: contentPadding con un valor 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">

Funciono para mi

Vladimir Salguero
fuente
-1

Envuelva CardViewen un diseño que tenga ancho:match_parent

Samuel Moshie
fuente