Wie füge ich Teiler und Leerzeichen zwischen Elementen in RecyclerView hinzu?

938

Dies ist ein Beispiel dafür , wie es in der zuvor hätte getan werden können ListViewKlasse, die mit Teiler und dividerHeight Parameter:

<ListView
    android:id="@+id/activity_home_list_view"
    android:layout_width="match_parent" 
    android:layout_height="match_parent"
    android:divider="@android:color/transparent"
    android:dividerHeight="8dp"/>

Eine solche Möglichkeit sehe ich jedoch in der RecyclerViewKlasse nicht.

<android.support.v7.widget.RecyclerView
    android:id="@+id/activity_home_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical"/>

Ist es in diesem Fall in Ordnung, Ränder zu definieren und / oder eine benutzerdefinierte Teileransicht direkt in das Layout eines Listenelements einzufügen, oder gibt es eine bessere Möglichkeit, mein Ziel zu erreichen?

EyesClear
quelle
Dies hat mir geholfen: stackoverflow.com/questions/26892296/…
Jared Burrows
@EyesClear Fügen Sie Elemente <TextView /> einer anderen XML hinzu und verwenden Sie sie in der Liste Gleiche Aktivität.
Amitsharma
7
Es gibt eine Klasse in Support Lib com.homeretailgroup.argos.android.view.decorators.DividerItemDecorationund verwenden Sie es so:mRecyclerView.addItemDecoration(new DividerItemDecoration(activity, LinearLayoutManager.VERTICAL));
Fada21
Sie können Ihrem Listenelement für vertikale Listen einen unteren Rand hinzufügen und möglicherweise als Teiler verwenden?
resw67
Am einfachsten ist es, um das erste Element in der Adapterzeile einen oberen / unteren Rand hinzuzufügen. android: layout_marginBottom = "4dp". (Beachten Sie, dass das Hinzufügen der Ränder zum übergeordneten Layout es nicht schneidet.)
pstorli

Antworten:

1227

Oktober 2016 Update

Mit der Version 25.0.0 der Android Support Library wurde folgende DividerItemDecorationKlasse eingeführt :

DividerItemDecoration ist eine RecyclerView.ItemDecoration, die als Teiler zwischen Elementen eines verwendet werden kann LinearLayoutManager. Es unterstützt sowohl HORIZONTALals auch VERTICALOrientierungen.

Verwendungszweck:

DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
    layoutManager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);

Vorherige Antwort

Einige Antworten verwenden entweder Methoden, die inzwischen veraltet sind, oder geben keine vollständige Lösung an. Daher habe ich versucht, eine kurze, aktuelle Zusammenfassung zu erstellen.


Im Gegensatz dazu ListViewhat die RecyclerViewKlasse keine teilerbezogenen Parameter. Stattdessen müssen Sie erweitern ItemDecoration, ein RecyclerView‚s innere Klasse:

Mit ItemDecorationermöglicht die Anwendung, bestimmten Elementansichten aus dem Datensatz des Adapters einen speziellen Zeichnungs- und Layoutversatz hinzuzufügen. Dies kann nützlich sein, um Trennlinien zwischen Elementen, Markierungen, visuellen Gruppierungsgrenzen und mehr zu zeichnen.

Alle ItemDecorationswerden in der Reihenfolge gezeichnet sie hinzugefügt wurden, bevor die Artikel Ansichten (in onDraw()) und nach den Punkten (in onDrawOver ( Canvas, RecyclerView, RecyclerView.State).

Vertical Abstand ItemDecoration

Erweitern Sie ItemDecoration, fügen Sie einen benutzerdefinierten Konstruktor hinzu, der Speicherplatz heightals Parameter verwendet, und überschreiben Sie die getItemOffsets()Methode:

public class VerticalSpaceItemDecoration extends RecyclerView.ItemDecoration {

    private final int verticalSpaceHeight;

    public VerticalSpaceItemDecoration(int verticalSpaceHeight) {
        this.verticalSpaceHeight = verticalSpaceHeight;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
            RecyclerView.State state) {
        outRect.bottom = verticalSpaceHeight;
    }
}

Wenn Sie kein Leerzeichen unter dem letzten Element einfügen möchten, fügen Sie die folgende Bedingung hinzu:

if (parent.getChildAdapterPosition(view) != parent.getAdapter().getItemCount() - 1) {
            outRect.bottom = verticalSpaceHeight;
}

Hinweis: Sie können auch ändern outRect.top, outRect.leftund outRect.rightEigenschaften für die gewünschte Wirkung.

Teiler ItemDecoration

Verlängern ItemDecorationund außer Kraft setzen onDraw()Methode:

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};

    private Drawable divider;

    /**
     * Default divider will be used
     */
    public DividerItemDecoration(Context context) {
        final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
        divider = styledAttributes.getDrawable(0);
        styledAttributes.recycle();
    }

    /**
     * Custom divider will be used
     */
    public DividerItemDecoration(Context context, int resId) {
        divider = ContextCompat.getDrawable(context, resId);
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);

            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            int top = child.getBottom() + params.bottomMargin;
            int bottom = top + divider.getIntrinsicHeight();

            divider.setBounds(left, top, right, bottom);
            divider.draw(c);
        }
    }
}

Sie können entweder den ersten Konstruktor aufrufen, der die Standardattribute für Android-Teiler verwendet, oder den zweiten Konstruktor, der Ihr eigenes Zeichenelement verwendet, z. B. drawable / divider.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <size android:height="1dp" />
    <solid android:color="#ff992900" />
</shape>

Hinweis: Wenn Sie möchten, dass der Teiler über Ihre Elemente gezogen wird, überschreiben Sie onDrawOver()stattdessen die Methode.

Verwendungszweck

So verwenden Sie Ihre neue Klasse add VerticalSpaceItemDecorationoder DividerSpaceItemDecorationto RecyclerView, zum Beispiel in der onCreateView()Methode Ihres Fragments :

private static final int VERTICAL_ITEM_SPACE = 48;
private RecyclerView recyclerView;
private LinearLayoutManager linearLayoutManager;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_feed, container, false);

    recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_home_recycler_view);
    linearLayoutManager = new LinearLayoutManager(getActivity());
    recyclerView.setLayoutManager(linearLayoutManager);

    //add ItemDecoration
    recyclerView.addItemDecoration(new VerticalSpaceItemDecoration(VERTICAL_ITEM_SPACE));
    //or
    recyclerView.addItemDecoration(new DividerItemDecoration(getActivity()));
    //or
    recyclerView.addItemDecoration(
            new DividerItemDecoration(getActivity(), R.drawable.divider));

    recyclerView.setAdapter(...);

    return rootView;
}

Es gibt auch die Bibliothek von Lucas Rocha , die den Prozess der Artikeldekoration vereinfachen soll. Ich habe es aber nicht versucht.

Zu seinen Merkmalen gehören:

  • Eine Sammlung von Dekorationen für Lagerartikel, darunter:
  • Artikelabstand Horizontale / vertikale Teiler.
  • Listenpunkt
EyesClear
quelle
3
@droppin_science Korrigiere mich, wenn ich falsch liege, aber keine Objekte in erstelle onDraw(). Ich verweise nur auf bereits vorhandene Instanzen.
EyesClear
1
Ich frage mich, ob es eine gute Idee ist, Paint zu verwenden, anstatt ein Drawable zu erstellen. Dann kann ich rufen Sie canvas.drawLine(startX, startY, stopX, stopY, mPaint)in onDrawOver? Leistungsunterschiede?
Arst
1
Nur ein informativer Kommentar: Fügen Sie immer das Leerzeichen zum letzten Element hinzu, wenn Sie später Elemente in Ihre Liste aufnehmen möchten. Wenn Sie dies nicht tun, hat ein Element beim Hinzufügen keinen Platz. Danke für den VerticalSpace!
Tsuharesu
24
DividerItemDecoration wie oben gezeigt funktioniert nicht, wenn die Elemente vollständig undurchsichtig sind. Teiler werden von den Elementen überzeichnet. In diesem Fall müssen Sie auch getItemOffsets () überschreiben und outRect den unteren Versatz hinzufügen, damit der Teiler außerhalb des Elements endet. Alternativ können Sie onDrawOver () anstelle von onDraw () überschreiben, um den Teiler nach dem Element zu zeichnen.
Jpop
115
Eine ganze Code-Seite zum Hinzufügen eines Teilers zu recyclerView ist die beste Antwort. Schande über dich, Google.
vorsichtig7j
480

Einfach hinzufügen

recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
                DividerItemDecoration.VERTICAL));

Möglicherweise müssen Sie auch die Abhängigkeit hinzufügen
compile 'com.android.support:recyclerview-v7:27.1.0'

BEARBEITEN:

Um es ein wenig anzupassen, können Sie ein benutzerdefiniertes Zeichen hinzufügen:

DividerItemDecoration itemDecorator = new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL);
itemDecorator.setDrawable(ContextCompat.getDrawable(getContext(), R.drawable.divider));

Es steht Ihnen frei, benutzerdefinierte Zeichen zu verwenden, zum Beispiel:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="@color/colorPrimary"/>
    <size android:height="0.5dp"/>
</shape>
Leo Droidcoder
quelle
Aktivität ist nicht erforderlich. Kontext ist genug
mac229
Dies muss die richtige Antwort sein. Bitte ändern Sie getActivity in den Kontext.
Jhon Fredy Trujillo Ortega
Es ist auch besser, sich von Ihrem LayoutManager zu orientieren.
lsrom
Vielen Dank! Sie können auch Configurationfür vertikale Teiler verwenden:if (orientation == Configuration.ORIENTATION_LANDSCAPE) { recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL)); } else { recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));}
AlexS
3
Schöne Antwort, aber es wird auch nach dem letzten Punkt ein Teiler hinzugefügt.
CoolMind
256

Darf ich Ihre Aufmerksamkeit auf diese spezielle Datei auf Github von Alex Fu lenken: https://gist.github.com/alexfu/0f464fc3742f134ccd1e

Es handelt sich um die DividerItemDecoration.java-Beispieldatei "direkt aus den Support-Demos" ( https://plus.google.com/103498612790395592106/posts/VVEB3m7NkSS ).

Nach dem Importieren dieser Datei in mein Projekt konnte ich Trennlinien gut abrufen und als Elementdekoration zur Recycler-Ansicht hinzufügen.

So sieht mein onCreateView in meinem Fragment aus, das das Recyclerview enthält:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_recycler_view, container, false);

    mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
    mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));

    mRecyclerView.setHasFixedSize(true);
    mLayoutManager = new LinearLayoutManager(getActivity());
    mRecyclerView.setLayoutManager(mLayoutManager);
    mRecyclerView.setItemAnimator(new DefaultItemAnimator());

    return rootView;
}

Ich bin sicher, dass zusätzliches Styling durchgeführt werden kann, aber es ist ein Ausgangspunkt. :) :)

Duy Nguyen
quelle
Wie können Sie diese ersetzen: "footerDividersEnabled", "headerDividersEnabled", "listSelector", "fastScrollEnabled", "oothScrollbar "," textFilterEnabled "?
Android-Entwickler
Irgendwelche Eingaben zu Wie man Styling setzt?
Nizam.sp
Um diese Lösung zu gestalten, müssen Sie das Attribut "android: listDivider" in Ihrem Thema überschreiben
Pavel Dudka
1
Divider funktioniert nicht mit RecyclerView. Sie müssen RecyclerView.itemDecoration verwenden. Siehe diese Antwort: stackoverflow.com/a/27664023/2311451
Cocorico
3
Warum erweitert der Teiler die gesamte Breite des Elements? wie man wie in den Spezifikationen anzeigt google.com/design/spec/components/lists.html#lists-specs
Chip
156

Einfache ItemDecorationImplementierung für gleiche Abstände zwischen allen Elementen.

public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
    private int space;

    public SpacesItemDecoration(int space) {
        this.space = space;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.left = space;
        outRect.right = space;
        outRect.bottom = space;

        // Add top margin only for the first item to avoid double space between items
        if(parent.getChildAdapterPosition(view) == 0) {
            outRect.top = space;
        }
    }
}
SergeyA
quelle
Ich bekomme den Raum, aber wie bekomme ich einen Teiler
Pankaj Nimgade
26
getChildPositionist jetzt veraltet, getChildAdapterPositionkann stattdessen verwendet werden.
EyesClear
4
Vergessen Sie nicht (wie ich), den Anruf zu entfernen super.getItemOffsets, sonst werden Ihre Offsets überschrieben.
Jayeffkay
@EyesClear sollte das getChildLayoutPositionnicht verwendet werden?
Avinash R
3
Implementiert dies den Abstand in Pixel?
filthy_wizard
108

Die einfache Möglichkeit besteht darin, die Hintergrundfarbe für RecyclerView und eine andere Hintergrundfarbe für Elemente festzulegen. Hier ist ein Beispiel ...

<android.support.v7.widget.RecyclerView
    android:background="#ECEFF1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scrollbars="vertical"/>

und das TextView- Element (es kann jedoch alles sein) mit dem unteren Rand "x" dp oder px.

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="1dp"
    android:background="#FFFFFF"/>

Die Ausgabe ...

Geben Sie hier die Bildbeschreibung ein

Madan Sapkota
quelle
2
Was für ein Trick! muss nur die Liste beim Laden weiß halten.
Hamzeh Soboh
36
Vorsicht vor Überziehung!
Shem
@shem könntest du das näher erläutern?
RominaV
7
Wenn Sie in Android mehrere Ebenen übereinander zeichnen (Aktivitätshintergrund, Hintergrund der Recyclingansicht und Hintergrund der Elementansicht), zeichnet Android alle Ebenen, auch diejenigen, die für die Benutzer nicht sichtbar sind. Das heißt Überziehen und könnte deine Leistung beeinträchtigen. Mehr dazu hier: youtube.com/watch?v=T52v50r-JfE
shem
41

Ich denke, die Verwendung eines einfachen Teilers wird Ihnen helfen.

So fügen Sie jedem Element einen Teiler hinzu:
1- Fügen Sie diesen zum zeichnbaren Verzeichnis line_divider.xml hinzu

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
    android:width="1dp"
    android:height="1dp" />
<solid android:color="#999999" />
</shape>

2- SimpleDividerItemDecoration-Klasse erstellen
Ich habe dieses Beispiel verwendet, um diese Klasse zu definieren:
https://gist.github.com/polbins/e37206fbc444207c0e92

package com.example.myapp;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import com.example.myapp.R;

public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration{
private Drawable mDivider;

public SimpleDividerItemDecoration(Resources resources) {
    mDivider = resources.getDrawable(R.drawable.line_divider);
}

public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
    int left = parent.getPaddingLeft();
    int right = parent.getWidth() - parent.getPaddingRight();

    int childCount = parent.getChildCount();
    for (int i = 0; i < childCount; i++) {
        View child = parent.getChildAt(i);

        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

        int top = child.getBottom() + params.bottomMargin;
        int bottom = top + mDivider.getIntrinsicHeight();

        mDivider.setBounds(left, top, right, bottom);
        mDivider.draw(c);
    }
  }
}


3- Fügen Sie in Aktivitäten oder Fragmenten, die RecyclerView verwenden, in onCreateView Folgendes hinzu:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
 RecyclerView myRecyclerView = (RecyclerView) layout.findViewById(R.id.my_recycler_view);
 myRecyclerView.addItemDecoration(new SimpleDividerItemDecoration(getResources()));
 ....
 }


4- Um den Abstand zwischen Elementen
zu erhöhen, müssen Sie Ihrer Elementansicht lediglich eine Auffüllungseigenschaft hinzufügen

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:padding="4dp"
>
..... item structure
</RelativeLayout>
Belal Mazlom
quelle
Wie mache ich es für GridLayoutManager, um auch vertikale Teiler zwischen den Zellen anzuzeigen?
Android-Entwickler
2
resources.getDrawable () ist jetzt veraltet. Sie können den Kontext übergeben und ContextCompat.getDrawable (Kontext, R.drawable.line_divider) verwenden
Eric B.
36

Wie ich eingestellt habe ItemAnimators. Sie ItemDecoratortreten nicht zusammen mit der Animation ein oder aus.

Am Ende hatte ich einfach eine Ansichtszeile in meiner Layoutdatei für die Elementansicht jedes Elements. Es hat meinen Fall gelöst. DividerItemDecorationfühlte sich zu viel Zauberei für einen einfachen Teiler.

<View
    android:layout_width="match_parent"
    android:layout_height="1px"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:background="@color/lt_gray"/>
Javanator
quelle
Du hast recht. Animationen funktionieren nicht mit der ItemDecoration. Ich bin mir nicht sicher warum, aber ohne dass ich etwas spezifiziere, bekomme ich Animationen und finde es sehr ablenkend und hässlich, dass die von ItemDecoration erstellten Zeilen nicht folgen. Also werde ich eine Lösung wie deine verwenden.
Michel
Wie sind Sie mit dem letzten Artikel umgegangen?
Älterer Gott
@oldergod. Sie zeigten auf den richtigen Schmerzpunkt. Ich würde mich zuerst darauf einigen, dass ein Design auch beim letzten Artikel einen Teiler hat. Aber wenn du das nicht willst. Weisen Sie dieser Ansicht eine ID zu und verstecken Sie sie in bindView, wenn die Position die letzte ist.
Javanator
@Javanator Ich sehe ok, den gleichen Ansatz, den ich gewählt habe. Vielen Dank.
Älterer Gott
das einfachste ist das beste
hyyou2010
27

Das ist einfach, Sie brauchen keinen so komplizierten Code

DividerItemDecoration divider = new 
DividerItemDecoration(mRVMovieReview.getContext(), 
DividerItemDecoration.VERTICAL);
divider.setDrawable(
    ContextCompat.getDrawable(getBaseContext(), R.drawable.line_divider)
);
mRVMovieReview.addItemDecoration(divider);

Fügen Sie dies in Ihre Zeichnungsdatei ein: line_divider.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
  android:shape="rectangle">
    <size android:height="1dp" />
    <solid android:color="@android:color/black" />
</shape>
Faheem
quelle
21

Da es noch keinen richtigen Weg gibt, dies mit Material Design richtig zu implementieren, habe ich nur den folgenden Trick ausgeführt, um dem Listenelement direkt einen Teiler hinzuzufügen:

<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/dividerColor"/>
Yoann Hercouet
quelle
DividerItemDecoration funktioniert nicht mehr, nachdem ich einige Höheninformationen zum Materialdesign erhalten habe (um den gleichen Effekt wie im Posteingang zu erzielen). es wurde zu kompliziert für eine einfache Sache. Diese Lösung ist einfach und funktioniert.
DenisGL
21

Die Art und Weise, wie ich mit der Teileransicht und auch mit Teilereinsätzen umgehe, besteht darin, eine RecyclerView-Erweiterung hinzuzufügen.

1.

Fügen Sie eine neue Erweiterungsdatei hinzu, indem Sie View oder RecyclerView benennen:

RecyclerViewExtension.kt

und fügen Sie die setDividerErweiterungsmethode in die Datei RecyclerViewExtension.kt ein.

/*
* RecyclerViewExtension.kt
* */
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView


fun RecyclerView.setDivider(@DrawableRes drawableRes: Int) {
    val divider = DividerItemDecoration(
        this.context,
        DividerItemDecoration.VERTICAL
    )
    val drawable = ContextCompat.getDrawable(
        this.context,
        drawableRes
    )
    drawable?.let {
        divider.setDrawable(it)
        addItemDecoration(divider)
    }
}

2.

Erstellen Sie eine Drawable-Ressourcendatei innerhalb des drawablePakets wie folgt recycler_view_divider.xml:

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetLeft="10dp"
    android:insetRight="10dp">

    <shape>
        <size android:height="0.5dp" />
        <solid android:color="@android:color/darker_gray" />
    </shape>

</inset>

Hier können Sie den linken und rechten Rand an android:insetLeftund angeben android:insetRight.

3.

In Ihrer Aktivität oder Ihrem Fragment, in dem die RecyclerView initialisiert ist, können Sie die benutzerdefinierte Zeichnungsfunktion festlegen, indem Sie Folgendes aufrufen:

recyclerView.setDivider(R.drawable.recycler_view_divider)

4.

Prost 🍺

RecyclerView-Zeile mit Teiler.

Gent Berani
quelle
16

Wenn jemand beispielsweise nur einen Abstand von 10 dp zwischen Elementen hinzufügen möchte, können Sie dies tun, indem Sie ein Zeichen auf Folgendes setzen DividerItemDecoration:

DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(
    recyclerView.getContext(),
    layoutManager.getOrientation()
);

dividerItemDecoration.setDrawable(
    ContextCompat.getDrawable(getContext(), R.drawable.divider_10dp)
); 

Wo divider_10dpist eine zeichnbare Ressource, die Folgendes enthält:

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <size android:height="10dp"/>
    <solid android:color="@android:color/transparent"/>
</shape>
Praveen Singh
quelle
11

Für diejenigen , die nur für suchen Räume zwischen den einzelnen Posten in der zu RecyclerViewsehen , mein Ansatz , wo man gleiche Räume zwischen allen Einzelteile erhalten, außer in der ersten und letzten Punkte , in denen ich einen größeren Polster gab. Ich wende die Polsterung nur links / rechts in der Horizontalen LayoutManagerund oben / unten in der Vertikalen an LayoutManager.

public class PaddingItemDecoration extends RecyclerView.ItemDecoration {

    private int mPaddingPx;
    private int mPaddingEdgesPx;

    public PaddingItemDecoration(Activity activity) {
        final Resources resources = activity.getResources();
        mPaddingPx = (int) resources.getDimension(R.dimen.paddingItemDecorationDefault);
        mPaddingEdgesPx = (int) resources.getDimension(R.dimen.paddingItemDecorationEdge);
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);

        final int itemPosition = parent.getChildAdapterPosition(view);
        if (itemPosition == RecyclerView.NO_POSITION) {
            return;
        }
        int orientation = getOrientation(parent);
        final int itemCount = state.getItemCount();

        int left = 0;
        int top = 0;
        int right = 0;
        int bottom = 0;

        /** HORIZONTAL */
        if (orientation == LinearLayoutManager.HORIZONTAL) {
            /** all positions */
            left = mPaddingPx;
            right = mPaddingPx;

            /** first position */
            if (itemPosition == 0) {
                left += mPaddingEdgesPx;
            }
            /** last position */
            else if (itemCount > 0 && itemPosition == itemCount - 1) {
                right += mPaddingEdgesPx;
            }
        }
        /** VERTICAL */
        else {
            /** all positions */
            top = mPaddingPx;
            bottom = mPaddingPx;

            /** first position */
            if (itemPosition == 0) {
                top += mPaddingEdgesPx;
            }
            /** last position */
            else if (itemCount > 0 && itemPosition == itemCount - 1) {
                bottom += mPaddingEdgesPx;
            }
        }

        if (!isReverseLayout(parent)) {
            outRect.set(left, top, right, bottom);
        } else {
            outRect.set(right, bottom, left, top);
        }
    }

    private boolean isReverseLayout(RecyclerView parent) {
        if (parent.getLayoutManager() instanceof LinearLayoutManager) {
            LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
            return layoutManager.getReverseLayout();
        } else {
            throw new IllegalStateException("PaddingItemDecoration can only be used with a LinearLayoutManager.");
        }
    }

    private int getOrientation(RecyclerView parent) {
        if (parent.getLayoutManager() instanceof LinearLayoutManager) {
            LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
            return layoutManager.getOrientation();
        } else {
            throw new IllegalStateException("PaddingItemDecoration can only be used with a LinearLayoutManager.");
        }
    }
}

dimension.xml

<resources>
    <dimen name="paddingItemDecorationDefault">10dp</dimen>
    <dimen name="paddingItemDecorationEdge">20dp</dimen>
</resources>
Ryan Amaral
quelle
11

Fügen Sie Ihrer Ansicht einen Rand hinzu, es hat bei mir funktioniert.

android:layout_marginTop="10dp"

Wenn Sie nur den gleichen Abstand hinzufügen und dies in XML tun möchten, stellen Sie einfach paddingIhren RecyclerViewund den gleichen Betrag für layoutMargindas Element ein, das Sie in Ihren aufblasen RecyclerView, und lassen Sie die Hintergrundfarbe die Abstandsfarbe bestimmen.

Quantum Mattter
quelle
3
Obwohl dies funktioniert, ist dies beispielsweise nicht die richtige Antwort, da dies das Problem nicht löst, ohne zusätzliche Änderungen am Zeilenlayout vorzunehmen. Außerdem wird oben der Rand x1 zwischen den Zeilenrand x2 angezeigt.
Sreekanth Karumanaghat
Dies ist keine gute Idee, da auf den overscrollEffekt beim Ziehen am Ende der Liste eine unnötige Auffüllung angewendet wird, wenn die Auffüllung angewendet wirdRecyclerView
AeroEchelon
Es ist besser, das Layout des Elements in eine Support Library CardView zu packen, damit Sie andere Attribute steuern können, z. B. Höhe / Schatten usw .: <?xml version="1.0" encoding="utf-8"?> <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_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" card_view:cardElevation="4dp" <!-- your item's XML here --> </android.support.v7.widget.CardView>
kip2
11
  • Hier ist ein einfacher Hack, um einen Teiler hinzuzufügen
  • Fügen Sie dem Layout Ihres Recyclingartikels einfach wie folgt einen Hintergrund hinzu

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/shape_border"
        android:gravity="center"
        android:orientation="horizontal"
        android:padding="5dp">
    
    <ImageView
        android:id="@+id/imageViewContactLogo"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_marginRight="10dp"
        android:src="@drawable/ic_user" />
    
    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="0.92"
        android:gravity="center|start"
        android:orientation="vertical">
    
    <TextView
        android:id="@+id/textViewContactName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />
    
    <TextView
        android:id="@+id/textViewStatusOrNumber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:singleLine="true"
        android:text=""
        android:textAppearance="?android:attr/textAppearanceMedium" />
    </LinearLayout>
    
    <TextView
        android:id="@+id/textViewUnreadCount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="10dp"
        android:padding="5dp"
        android:text=""
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="@color/red"
        android:textSize="22sp" />
    
    <Button
        android:id="@+id/buttonInvite"
        android:layout_width="54dp"
        android:layout_height="wrap_content"
        android:background="@drawable/ic_add_friend" />
    </LinearLayout>

Erstellen Sie die folgende shape_border.xml in einem zeichnbaren Ordner

  <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
      android:shape="rectangle" >
       <gradient
        android:angle="270"
        android:centerColor="@android:color/transparent"
        android:centerX="0.01"
        android:startColor="#000" />
    </shape>

Hier ist das Endergebnis - eine RecyclerView mit Teiler.

Hier ist das Endergebnis - eine RecyclerView mit Teiler.

Turbandroid
quelle
1
Dies ist kein bevorzugter Ansatz. Obwohl die Antwort von @EyesClear Ints in onDraw initiiert und parent.getChildAdapterPosition(view) != parent.getAdapter().getItemCount() - 1wahrscheinlich parent.getChildAdapterPosition(view) > 0mit dem outRect.bottom = mVerticalSpaceHeightWerden outRect.top = mVerticalSpaceHeightsein sollte, sollte es die akzeptierte Antwort sein.
Droppin_science
@droppin_science - Sie können es nicht vernachlässigen, indem Sie nur sagen, dass dies kein bevorzugter Ansatz ist. Es liefert mir erwartungsgemäß genaue Ergebnisse. Ich sehe mir auch die Antwort von EyesClear an, aber diese Antwort ist für einen einfachen Teiler zu kompliziert, wenn es jedoch nötig ist Machen Sie eine zusätzliche Dekoration mit dem Gegenstand, dann kann dies die akzeptierte Antwort sein.
Turbandroid
Für die nach unten gerichteten Wähler wurde diese Antwort zu der Zeit gegeben, als es keine offiziellen Klassen für DividerItemDecoration gab. Vergleichen Sie also einfach die Zeitlücke zwischen dieser Antwort und der folgenden Antwort von Leo Droidcoder. :)
Turbandroid
9

Ich habe die DividerItemDecoration aus einem älteren Kern gegabelt und sie an meinen Anwendungsfall angepasst. Außerdem habe ich sie so geändert, dass die Teiler so gezeichnet werden, wie sie in ListView gezeichnet werden, einschließlich eines Teilers nach dem letzten Listenelement. Dies behandelt auch vertikale ItemAnimator-Animationen:

1) Fügen Sie diese Klasse Ihrem Projekt hinzu:

public class DividerItemDecoration extends RecyclerView.ItemDecoration {
    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
    private Drawable divider;

    public DividerItemDecoration(Context context) {
        try {
            final TypedArray a = context.obtainStyledAttributes(ATTRS);
            divider = a.getDrawable(0);
            a.recycle();
        } catch (Resources.NotFoundException e) {
            // TODO Log or handle as necessary.
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if (divider == null) return;
        if (parent.getChildAdapterPosition(view) < 1) return;

        if (getOrientation(parent) == LinearLayoutManager.VERTICAL)
            outRect.top = divider.getIntrinsicHeight();
        else
            throw new IllegalArgumentException("Only usable with vertical lists");
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (divider == null) {
            super.onDrawOver(c, parent, state);
            return;
        }

        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();
        final int childCount = parent.getChildCount();

        for (int i = 0; i < childCount; ++i) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            final int size = divider.getIntrinsicHeight();
            final int top = (int) (child.getTop() - params.topMargin - size + child.getTranslationY());
            final int bottom = top + size;
            divider.setBounds(left, top, right, bottom);
            divider.draw(c);

            if (i == childCount - 1) {
                final int newTop = (int) (child.getBottom() + params.bottomMargin + child.getTranslationY());
                final int newBottom = newTop + size;
                divider.setBounds(left, newTop, right, newBottom);
                divider.draw(c);
            }
        }
    }

    private int getOrientation(RecyclerView parent) {
        if (!(parent.getLayoutManager() instanceof LinearLayoutManager))
            throw new IllegalStateException("Layout manager must be an instance of LinearLayoutManager");
        return ((LinearLayoutManager) parent.getLayoutManager()).getOrientation();
    }
}

2) Fügen Sie den Dekorator zu Ihrer RecylerView hinzu:

recyclerView.addItemDecoration(new DividerItemDecoration(getActivity()));
Lernen Sie OpenGL ES
quelle
Richtig, es ist für einen LinearLayoutManager gedacht. Sie können die Idee dahinter nehmen, um sie für einen GridLayoutManager anzupassen.
Lernen Sie OpenGL ES
8

Anstatt ein shape xmlzum Ändern der Teilerhöhe und -farbe zu erstellen . Sie können programmgesteuert wie erstellen

val divider = DividerItemDecoration(context,
        DividerItemDecoration.VERTICAL)

divider.setDrawable(ShapeDrawable().apply {
    intrinsicHeight = resources.getDimensionPixelOffset(R.dimen.dp_15)
    paint.color = Color.RED // note: currently (support version 28.0.0), we can not use tranparent color here, if we use transparent, we still see a small divider line. So if we want to display transparent space, we can set color = background color or we can create a custom ItemDecoration instead of DividerItemDecoration. 
})

recycler_devices.addItemDecoration(divider)
Phan Van Linh
quelle
Dies ist eine nützliche Antwort
taha
7

Fügen Sie diese ItemDecoration aus einer Google-Suche zu RecyclerView:

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

private Drawable mDivider;
private boolean mShowFirstDivider = false;
private boolean mShowLastDivider = false;


public DividerItemDecoration(Context context, AttributeSet attrs) {
    final TypedArray a = context
            .obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider});
    mDivider = a.getDrawable(0);
    a.recycle();
}

public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider,
        boolean showLastDivider) {
    this(context, attrs);
    mShowFirstDivider = showFirstDivider;
    mShowLastDivider = showLastDivider;
}

public DividerItemDecoration(Drawable divider) {
    mDivider = divider;
}

public DividerItemDecoration(Drawable divider, boolean showFirstDivider,
        boolean showLastDivider) {
    this(divider);
    mShowFirstDivider = showFirstDivider;
    mShowLastDivider = showLastDivider;
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
        RecyclerView.State state) {
    super.getItemOffsets(outRect, view, parent, state);
    if (mDivider == null) {
        return;
    }
    if (parent.getChildPosition(view) < 1) {
        return;
    }

    if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
        outRect.top = mDivider.getIntrinsicHeight();
    } else {
        outRect.left = mDivider.getIntrinsicWidth();
    }
}

@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
    if (mDivider == null) {
        super.onDrawOver(c, parent, state);
        return;
    }

    // Initialization needed to avoid compiler warning
    int left = 0, right = 0, top = 0, bottom = 0, size;
    int orientation = getOrientation(parent);
    int childCount = parent.getChildCount();

    if (orientation == LinearLayoutManager.VERTICAL) {
        size = mDivider.getIntrinsicHeight();
        left = parent.getPaddingLeft();
        right = parent.getWidth() - parent.getPaddingRight();
    } else { //horizontal
        size = mDivider.getIntrinsicWidth();
        top = parent.getPaddingTop();
        bottom = parent.getHeight() - parent.getPaddingBottom();
    }

    for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) {
        View child = parent.getChildAt(i);
        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

        if (orientation == LinearLayoutManager.VERTICAL) {
            top = child.getTop() - params.topMargin;
            bottom = top + size;
        } else { //horizontal
            left = child.getLeft() - params.leftMargin;
            right = left + size;
        }
        mDivider.setBounds(left, top, right, bottom);
        mDivider.draw(c);
    }

    // show last divider
    if (mShowLastDivider && childCount > 0) {
        View child = parent.getChildAt(childCount - 1);
        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
        if (orientation == LinearLayoutManager.VERTICAL) {
            top = child.getBottom() + params.bottomMargin;
            bottom = top + size;
        } else { // horizontal
            left = child.getRight() + params.rightMargin;
            right = left + size;
        }
        mDivider.setBounds(left, top, right, bottom);
        mDivider.draw(c);
    }
}

private int getOrientation(RecyclerView parent) {
    if (parent.getLayoutManager() instanceof LinearLayoutManager) {
        LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
        return layoutManager.getOrientation();
    } else {
        throw new IllegalStateException(
                "DividerItemDecoration can only be used with a LinearLayoutManager.");
    }
}
}
gatlingxyz
quelle
Dies funktioniert nur für LinearLayoutManager. Was ist für GridLayoutManager zu tun?
Android-Entwickler
6

Dieser Link hat für mich wie ein Zauber gewirkt:

https://gist.github.com/lapastillaroja/858caf1a82791b6c1a36

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private Drawable mDivider;
    private boolean mShowFirstDivider = false;
    private boolean mShowLastDivider = false;


    public DividerItemDecoration(Context context, AttributeSet attrs) {
        final TypedArray a = context
                .obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider});
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider,
            boolean showLastDivider) {
        this(context, attrs);
        mShowFirstDivider = showFirstDivider;
        mShowLastDivider = showLastDivider;
    }

    public DividerItemDecoration(Drawable divider) {
        mDivider = divider;
    }

    public DividerItemDecoration(Drawable divider, boolean showFirstDivider,
            boolean showLastDivider) {
        this(divider);
        mShowFirstDivider = showFirstDivider;
        mShowLastDivider = showLastDivider;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
            RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if (mDivider == null) {
            return;
        }
        if (parent.getChildPosition(view) < 1) {
            return;
        }

        if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
            outRect.top = mDivider.getIntrinsicHeight();
        } else {
            outRect.left = mDivider.getIntrinsicWidth();
        }
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mDivider == null) {
            super.onDrawOver(c, parent, state);
            return;
        }

        // Initialization needed to avoid compiler warning
        int left = 0, right = 0, top = 0, bottom = 0, size;
        int orientation = getOrientation(parent);
        int childCount = parent.getChildCount();

        if (orientation == LinearLayoutManager.VERTICAL) {
            size = mDivider.getIntrinsicHeight();
            left = parent.getPaddingLeft();
            right = parent.getWidth() - parent.getPaddingRight();
        } else { //horizontal
            size = mDivider.getIntrinsicWidth();
            top = parent.getPaddingTop();
            bottom = parent.getHeight() - parent.getPaddingBottom();
        }

        for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            if (orientation == LinearLayoutManager.VERTICAL) {
                top = child.getTop() - params.topMargin;
                bottom = top + size;
            } else { //horizontal
                left = child.getLeft() - params.leftMargin;
                right = left + size;
            }
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }

        // show last divider
        if (mShowLastDivider && childCount > 0) {
            View child = parent.getChildAt(childCount - 1);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            if (orientation == LinearLayoutManager.VERTICAL) {
                top = child.getBottom() + params.bottomMargin;
                bottom = top + size;
            } else { // horizontal
                left = child.getRight() + params.rightMargin;
                right = left + size;
            }
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    private int getOrientation(RecyclerView parent) {
        if (parent.getLayoutManager() instanceof LinearLayoutManager) {
            LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
            return layoutManager.getOrientation();
        } else {
            throw new IllegalStateException(
                    "DividerItemDecoration can only be used with a LinearLayoutManager.");
        }
    }
}

Dann in Ihrer Tätigkeit:

mCategoryRecyclerView.addItemDecoration(
    new DividerItemDecoration(this, null));

Oder dies, wenn Sie ein Fragment verwenden:

mCategoryRecyclerView.addItemDecoration(
    new DividerItemDecoration(getActivity(), null));
Mikro
quelle
1
Dies funktioniert einwandfrei, zeigt jedoch nicht den Teiler unter dem letzten Element in der Liste an. Ich brauche es so: mShowFirstDivider = false, mShowLastDivider = true, aber es wird nicht funktionieren. Irgendeine Idee warum?
Nightfixed
Dies kann mit GridLayoutManager nicht gut umgehen.
Android-Entwickler
6

Wir können die Gegenstände mit verschiedenen Dekoratoren dekorieren, die an die Recycling-Ansicht angehängt sind, wie z. B. DividerItemDecoration:

Verwenden Sie einfach Folgendes ... aus der Antwort von EyesClear

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

private static final int[] ATTRS = new int[]{android.R.attr.listDivider};

private Drawable mDivider;

/**
 * Default divider will be used
 */
public DividerItemDecoration(Context context) {
    final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
    mDivider = styledAttributes.getDrawable(0);
    styledAttributes.recycle();
}

/**
 * Custom divider will be used
 */
public DividerItemDecoration(Context context, int resId) {
    mDivider = ContextCompat.getDrawable(context, resId);
}

@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
    int left = parent.getPaddingLeft();
    int right = parent.getWidth() - parent.getPaddingRight();

    int childCount = parent.getChildCount();
    for (int i = 0; i < childCount; i++) {
        View child = parent.getChildAt(i);

        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

        int top = child.getBottom() + params.bottomMargin;
        int bottom = top + mDivider.getIntrinsicHeight();

        mDivider.setBounds(left, top, right, bottom);
        mDivider.draw(c);
    }
}

} und verwenden Sie dann die obigen Schritte wie folgt

RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST);
recyclerView.addItemDecoration(itemDecoration);

Dadurch werden Teiler zwischen den einzelnen Elementen in der Liste angezeigt, wie unten gezeigt:

Geben Sie hier die Bildbeschreibung ein

Und für diejenigen, die nach weiteren Details suchen, lesen Sie diese Anleitung unter Verwendung der RecyclerView _ CodePath Android Cliffnotes

Einige Antworten hier schlagen die Verwendung von Rändern vor, aber der Haken ist folgender: Wenn Sie sowohl den oberen als auch den unteren Rand hinzufügen, werden beide zwischen Elementen hinzugefügt und sie sind zu groß. Wenn Sie nur eines hinzufügen, wird weder am oberen noch am unteren Rand der gesamten Liste ein Rand angezeigt. Wenn Sie die Hälfte des Abstands oben und die Hälfte unten hinzufügen, sind die äußeren Ränder zu klein.

Daher ist die einzige ästhetisch korrekte Lösung der Teiler, den das System richtig anwenden kann: zwischen Elementen, jedoch nicht über oder unter Elementen.

Bitte lassen Sie mich Zweifel in den Kommentaren unten wissen :)

Anudeep Samaiya
quelle
1
Dies zeigt nicht, wie der DividerItemDecorationCode aussieht.
IgorGanapolsky
1
Es ist eine AOSP-Klasse, ich habe den Code für Sie ausgegraben
Anudeep Samaiya
Es funktioniert nicht gut: Es behandelt keine Zeilen unterschiedlicher Höhe und es zeigt keinen vertikalen Teiler für Gitter
Android-Entwickler
5

Zu spät, aber GridLayoutManagerich benutze dies:

public class GridSpacesItemDecoration : RecyclerView.ItemDecoration
{
    private int space;

    public GridSpacesItemDecoration(int space) {
        this.space = space;
    }

    public override void GetItemOffsets(Android.Graphics.Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
    {
        var position = parent.GetChildLayoutPosition(view);

        /// Only for GridLayoutManager Layouts
        var manager = parent.GetLayoutManager() as GridLayoutManager;

        if (parent.GetChildLayoutPosition(view) < manager.SpanCount)
            outRect.Top = space;

        if (position % 2 != 0) {
            outRect.Right = space;
        }

        outRect.Left = space;
        outRect.Bottom = space;
    }
}

Diese Arbeit für jede Anzahl von Spannen, die Sie haben.

Ollie.

Ollie Strevel
quelle
Wie würden Sie den Top-Space ändern, um ihn auch zu unterstützen FlexboxLayoutManager?
Android-Entwickler
5

Sie können mit programmatisch einfach hinzufügen.

Wenn Ihr Layout-Manager Linearlayout ist, können Sie Folgendes verwenden:

DividerItemDecoration ist eine RecyclerView.ItemDecoration, die als Teiler zwischen Elementen eines LinearLayoutManager verwendet werden kann. Es unterstützt sowohl die horizontale als auch die vertikale Ausrichtung.

 mDividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
         mLayoutManager.getOrientation());
 recyclerView.addItemDecoration(mDividerItemDecoration);

Quelle

Beyaz
quelle
5

Ich habe das Gefühl, dass eine einfache, codebasierte Antwort erforderlich ist, die kein XML verwendet

DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);

ShapeDrawable shapeDrawableForDivider = new ShapeDrawable(new RectShape());

int dividerThickness = // (int) (SomeOtherView.getHeight() * desiredPercent);
shapeDrawableForDivider.setIntrinsicHeight(dividerThickness);
shapeDrawableForDivider.setAlpha(0);

dividerItemDecoration.setDrawable(shapeDrawableForDivider);

recyclerView.addItemDecoration(dividerItemDecoration);
Boober Bunz
quelle
4

Wenn Sie den gleichen Platz für Elemente hinzufügen möchten, ist es am einfachsten, Kartenelementen einen oberen + linken Abstand für RecycleView und einen rechten + unteren Rand hinzuzufügen.

dimension.xml

<resources>
    <dimen name="divider">1dp</dimen>
</resources>

list_item.xml

<CardView
 android:layout_marginBottom="@dimen/divider"
 android:layout_marginRight="@dimen/divider">
 ...
</CardView>

list.xml

<RecyclerView
 android:paddingLeft="@dimen/divider"
 android:paddingTop="@dimen/divider"
/>
Limitium
quelle
4

Ich habe eine Zeile im Listenelement wie unten hinzugefügt

<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/dividerColor"/>

1px zeichnet die dünne Linie.

Wenn Sie den Teiler für die letzte Zeile ausblenden möchten, divider.setVisiblity(View.GONE);klicken Sie auf den onBindViewHolder für das letzte Listenelement.

Raja Peela
quelle
1
Ich bevorzuge dieses, andere sind einfach zu kompliziert.
Sam Chen
3

Das RecyclerViewist ein bisschen anders als das ListView. Eigentlich RecyclerViewbraucht das eine ListViewähnliche Struktur drin. Zum Beispiel a LinearLayout. Das LinearLayouthat Parameter für die Aufteilung jedes Elements. Im folgenden Code habe ich eine RecyclerViewaus CardViewObjekten innerhalb einesLinearLayout mit einem „padding“ , die etwas Platz zwischen den einzelnen Posten wird gesetzt. Machen Sie diesen Raum wirklich klein und Sie erhalten eine Linie.

Hier ist die Recycler-Ansicht in recyclerview_layout.xml

<RelativeLayout 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: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=".ToDoList">

    <!-- A RecyclerView with some commonly used attributes -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/todo_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

Und hier ist, wie jedes Element in einer anderen Datei aussieht (und aufgrund des Android: Auffüllen im LinearLayout, das alles umgibt, als geteilt angezeigt wird): card_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    **android:padding="@dimen/activity_vertical_margin"**>
    <!-- A CardView that contains a TextView -->
    <android.support.v7.widget.CardView
        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="100dp"
        android:elevation="30dp"
        card_view:cardElevation="3dp">
            <TextView
                android:id="@+id/info_text"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                />
    </android.support.v7.widget.CardView>
</LinearLayout>
Fiacobelli
quelle
3

Eine wirklich einfache Lösung ist die Verwendung RecyclerView-FlexibleDivider

Abhängigkeit hinzufügen:

compile 'com.yqritc:recyclerview-flexibledivider:1.4.0'

Fügen Sie Ihrem Recycling-Überblick hinzu:

recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(context).build());

Und du bist fertig!

Cristan
quelle
funktioniert wie ein Zauber ... ich muss Open-Source-Sharing lieben.
Billy
3

1. Einer der Wege ist , dass wir durch die gemeinsame Verwendung von Kartenansicht und Recycler-Ansicht auf einfache Weise Effekte wie Trennwände hinzufügen können. Ex. https://developer.android.com/training/material/lists-cards.html

2.und andere ist das Hinzufügen einer Ansicht als Teiler zu list_item_layout der Recycler-Ansicht .

        <View
            android:id="@+id/view1"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/colorAccent" />
vicky
quelle
3
public class CommonItemSpaceDecoration extends RecyclerView.ItemDecoration {

        private int mSpace = 0;
        private boolean mVerticalOrientation = true;

    public CommonItemSpaceDecoration(int space) {
        this.mSpace = space;
    }

    public CommonItemSpaceDecoration(int space, boolean verticalOrientation) {
        this.mSpace = space;
        this.mVerticalOrientation = verticalOrientation;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.top = SizeUtils.dp2px(view.getContext(), mSpace);
        if (mVerticalOrientation) {
            if (parent.getChildAdapterPosition(view) == 0) {
                outRect.set(0, SizeUtils.dp2px(view.getContext(), mSpace), 0, SizeUtils.dp2px(view.getContext(), mSpace));
            } else {
                outRect.set(0, 0, 0, SizeUtils.dp2px(view.getContext(), mSpace));
            }
        } else {
            if (parent.getChildAdapterPosition(view) == 0) {
                outRect.set(SizeUtils.dp2px(view.getContext(), mSpace), 0, 0, 0);
            } else {
                outRect.set(SizeUtils.dp2px(view.getContext(), mSpace), 0, SizeUtils.dp2px(view.getContext(), mSpace), 0);
            }
        }
    }
}

Dadurch wird oben und unten (oder links und rechts) Platz für jedes Element hinzugefügt. Dann können Sie es auf Ihre festlegen recyclerView.

recyclerView.addItemDecoration(new CommonItemSpaceDecoration(16));

SizeUtils.java

public class SizeUtils {
    public static int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}
wizChen
quelle