CardView layout_width = "match_parent" stimmt nicht mit der übergeordneten RecyclerView-Breite überein

123

Ich habe ein Fragment mit enthält eine RecyclerView mit 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" />

Das Element in der RecyclerView ist eine CardView, ebenfalls mit 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>

Ich blase die Artikelansicht wie folgt auf:

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

Wenn ich die App ausführe, wird CardView wie folgt dargestellt: wrap_content:

CardsBug

Beachten Sie, dass dies auf einem Emulator ausgeführt wurde, nicht auf einem echten Gerät.

Mache ich etwas falsch oder ist es ein Fehler?

ProgrAmmar
quelle
Versorgen Sie die übergeordnete Ansicht beim Aufblasen der CardView mit einem echten Parameter?
Nhaarman
Hallo @NiekHaarman, bitte sehen Sie die Bearbeitung. Ich habe den Aufblascode hinzugefügt. Und ja, ich habe den wahren Parameter übergeben.
ProgrAmmar

Antworten:

291

Die Dokumente für inflate:

Blasen Sie eine neue Ansichtshierarchie aus der angegebenen XML-Ressource auf. Löst InflateException aus, wenn ein Fehler auftritt.

Parameter
Ressource ID für ein XML - Layout Ressource Last (zB R.layout.main_page) root
Ansicht der Elternteil der erzeugten Hierarchie zu sein (wenn attachToRoot wahr ist) oder auch einfach ein Objekt , das eine Reihe von Werten für Wurzel LayoutParams liefert der zurückgegebenen Hierarchie (wenn attachToRoot false ist.)
attachToRoot Ob die aufgeblasene Hierarchie an den Root-Parameter angehängt werden soll? Wenn false, wird root nur verwendet, um die richtige Unterklasse von LayoutParams für die Root-Ansicht in XML zu erstellen. Rückgabe Die Stammansicht der aufgeblasenen Hierarchie. Wenn root angegeben wurde und attachToRoot true ist, ist dies root. Andernfalls ist es das Stammverzeichnis der aufgeblasenen XML-Datei.

Es ist hier wichtig, nicht wahr zu liefern, sondern sie die Eltern liefern:

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

Wenn Sie die parentAnsicht bereitstellen, weiß der Inflater, welche Layoutparameter verwendet werden sollen. Wenn Sie den falseParameter angeben , wird er angewiesen , ihn noch nicht an das übergeordnete Element anzuhängen. Das ist es, was der RecyclerViewWille für Sie tun wird.

Nhaarman
quelle
4
Die Lösung hat bei mir nicht funktioniert, weil die ListViews layout_widthwar wrap_content. Es ist komisch, weil dies die Listenansicht nicht beeinflussen sollte! Mein Verständnis ist also, dass, wenn Sie dem Layoutinflater false als Parameter angeben, die ListView die Listenelemente zur ListView hinzufügt, wobei die Layoutparameter mit der ListView selbst übereinstimmen! : 0
Rubenjohn
1
Könntest du ein bisschen mehr Code posten, weil ich denke, ich mache das Gleiche, aber eigentlich funktioniert es nicht
Rodi
1
Ich blase auf, wie Ihr Vorschlag und match_parent für mich nicht funktioniert.
Zapnologica
3
Ich denke, das richtige Verständnis ist, dass Sie, wenn Sie attachToRoot auf false setzen, ein Objekt mit einem definierten LayoutParams-Wert angeben müssen. Dieses Objekt ist nicht unbedingt das übergeordnete Objekt. "... einfach ein Objekt, das eine Reihe von LayoutParams-Werten für den Stamm der zurückgegebenen Hierarchie bereitstellt (wenn attachToRoot false ist.) ..." Aber ich verstehe nicht, warum inflater die in CardView definierten LayoutParams nicht lesen kann, sondern benötigt ein anderer Objektparameter, um es zu informieren?
Hjchin
1
Wie gehe ich damit um, wenn ich eine benutzerdefinierte Ansicht verwende? Ich meineViewHolder onCreateViewHolder(...) { View v = new MyItemView(parent.getContext); return new ViewHolder(v); }
Kross
64

Verwenden Sie RelativeLayout als unmittelbares übergeordnetes Element von CardView.

<RelativeLayout 
    android:layout_width="match_parent" ... >
    <CardView 
        android:layout_width="match_parent" ... >
    </CardView>
</RelativeLayout>
Ganesh Kanna
quelle
Ja, das schien auch für mich zu funktionieren. Ich habe LinearLayout verwendet und der obige Vorschlag hat nicht funktioniert, da ich genau das bereits getan habe (dh nicht an root angehängt, sondern ein übergeordnetes Element bereitgestellt). Sie müssen beide RelativeLayout + ausführen, ohne übergeordnetes Element anzuhängen, sondern eines bereitzustellen.
Chubbsondubs
1
Es funktioniert für mich, aber ich weiß nicht, warum dies das Problem lösen kann. Kann jemand erklären warum?
Johnny
1
Es ist schon lange her, Android X ist in Produktion, der Fehler ist immer noch nicht behoben!
Muhammad Naderi
der einfachste Weg.
Abdurahman Popal
Ich hatte ein ähnliches Problem und dies hat bei mir funktioniert, um die Breite meiner Kartenansicht zu korrigieren, aber ich habe ein ähnliches Problem mit der Höhe? Können Sie mir auch dafür etwas vorschlagen?
12

Das hat bei mir funktioniert,

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

Ich habe es so gemacht:

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

Erläuterung: Wenn Sie in Ihrer onCreateViewHolde die Kartenansicht erhalten haben, ermitteln Sie die Bildschirmbreite und legen Sie den Layoutparameter für die Kartenansicht entsprechend fest.

Rahul
quelle
1
Bitte verbessern Sie dies leicht. Es heißt im Grunde "Try this"
Drew
Erklärung hinzugefügt. Bitte überprüfen Sie und kommentieren Sie hier, wenn Sie weitere Hilfe benötigen.
Rahul
4

Stellen Sie einfach neue Layoutparameter ein

view.setLayoutParams(new RecyclerView.LayoutParams(
    RecyclerView.LayoutParams.MATCH_PARENT,
    RecyclerView.LayoutParams.WRAP_CONTENT
));
Vlad
quelle
Ich fand es in onBindViewHolder () nützlich, eine benutzerdefinierte Ansichtsklasse zu verwenden, die von ConstraintLayout erbt.
Rasmusob
Dies ist keine gute Antwort, da der für das Layout festgelegte Rand betroffen ist.
Emi Raz
4

Die Standardimplementierung erzwingt die Verwendung von wrap_content im Standardlayoutmanager:

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

Alles, was Sie tun müssen, ist, diese Methode in Ihrem LayoutManager wie folgt zu überschreiben:

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

Das funktioniert bei mir

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

Verwenden Sie card_view: contentPadding mit einem negativen Wert

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

Es hat bei mir funktioniert

Vladimir Salguero
quelle
-1

Wickeln Sie CardViewein Layout mit einer Breite ein:match_parent

Samuel Moshie
quelle