Jak dodać dzielniki i spacje między elementami w RecyclerView?

938

To jest przykład tego, jak można było to zrobić wcześniej w ListViewklasie, używając parametrów divider i dividerHeight :

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

Jednak nie widzę takiej możliwości w RecyclerViewklasie.

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

Czy w takim przypadku można zdefiniować marginesy i / lub dodać niestandardowy widok podziału bezpośrednio do układu elementu listy, czy jest lepszy sposób na osiągnięcie mojego celu?

Oczy Oczyść
źródło
Pomogło mi to: stackoverflow.com/questions/26892296/...
Jared Burrows,
@EyesClear Dodaj elementy <TextView /> inny plik XML i użyj go na liście Ta sama aktywność.
Amitsharma
7
Istnieje biblioteka wspierająca lib com.homeretailgroup.argos.android.view.decorators.DividerItemDecorationi używaj jej w ten sposób:mRecyclerView.addItemDecoration(new DividerItemDecoration(activity, LinearLayoutManager.VERTICAL));
fada21
Możesz dodać dolny margines do pozycji listy dla list pionowych, a może może być używany jako dzielnik?
resw67
Najprostszym sposobem jest dodanie górnego / dolnego marginesu wokół pierwszego elementu w rzędzie adaptera. android: layout_marginBottom = "4dp". (Uwaga: dodanie marginesów do układu nadrzędnego go nie wycina.)
pstorli

Odpowiedzi:

1227

Aktualizacja z października 2016 r

Wersja 25.0.0 biblioteki obsługi systemu Android wprowadziła DividerItemDecorationklasę:

DividerItemDecoration to RecyclerView.ItemDecoration, który może być używany jako dzielnik między elementami LinearLayoutManager. Obsługuje zarówno HORIZONTALi VERTICALorientacje.

Stosowanie:

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

Poprzednia odpowiedź

Niektóre odpowiedzi albo używają metod, które stały się przestarzałe, albo nie dają kompletnego rozwiązania, więc próbowałem zrobić krótkie, aktualne podsumowanie.


W przeciwieństwie do ListViewtej RecyclerViewklasy nie ma parametrów związanych z dzielnikiem. Zamiast tego, trzeba rozszerzyć ItemDecoration, A RecyclerView„s klasa wewnętrzna:

ItemDecorationUmożliwia aplikację aby dodać specjalny rysunek i układ korekcji do określonych poglądów element z zestawu danych karty. Może to być przydatne do rysowania dzielników między elementami, podświetleniami, wizualnymi granicami grupowania i nie tylko.

Wszystko ItemDecorationsrysowane są w kolejności, w jakiej zostały dodane przed poglądami punkcie (w onDraw()) i po przedmioty (w onDrawOver ( Canvas, RecyclerView, RecyclerView.State).

Vertical rozstaw ItemDecoration

Rozszerz ItemDecoration, dodaj niestandardowy konstruktor, który zajmuje miejsce heightjako parametr i zastąp getItemOffsets()metodę:

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

Jeśli nie chcesz wstawiać spacji poniżej ostatniego elementu, dodaj następujący warunek:

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

Uwaga: można również modyfikować outRect.top, outRect.lefta outRect.rightwłaściwości pożądanego efektu.

Rozdzielacz ItemDecoration

Metoda rozszerzania ItemDecorationi zastępowania onDraw():

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

Możesz wywołać pierwszego konstruktora, który korzysta z domyślnych atrybutów dzielnika Androida, lub drugiego, który używa własnego rysunku, na przykład 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>

Uwaga: jeśli chcesz, aby dzielnik był narysowany nad twoimi przedmiotami, onDrawOver()zamiast tego zastąp metodę.

Stosowanie

Aby użyć nowej klasy dodaj VerticalSpaceItemDecorationlub DividerSpaceItemDecorationdo RecyclerView, na przykład w onCreateView()metodzie fragmentu :

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

Jest też biblioteka Lucasa Rochy która ma uprościć proces dekoracji przedmiotów. Jednak nie próbowałem tego.

Wśród jego funkcji są:

  • Kolekcja dekoracji artykułów magazynowych, w tym:
  • Odstępy między elementami Poziome / pionowe przekładki
  • Element listy
Oczy Oczyść
źródło
3
@droppin_science Popraw mnie, jeśli się mylę, ale nie tworzę żadnych obiektów onDraw(). Po prostu odwołuję się do już istniejących instancji.
EyesClear
1
Zastanawiam się, czy dobrym pomysłem jest używanie Paint zamiast tworzenia rysowania? Następnie można wywołać canvas.drawLine(startX, startY, stopX, stopY, mPaint)w onDrawOver? Jakaś różnica w wydajności?
Arst
1
Tylko komentarz informacyjny: zawsze dodawaj spację do ostatniego elementu, jeśli planujesz dodać elementy później na liście. Jeśli tego nie zrobisz, podczas dodawania elementu nie będzie na nim miejsca. Dzięki za VerticalSpace!
Tsuharesu
24
DividerItemDecoration, jak pokazano powyżej, nie będzie działać, jeśli elementy są całkowicie nieprzezroczyste, przegrody zostaną przesłonięte przez elementy. W takim przypadku musisz również przesłonić getItemOffsets () i dodać dolne przesunięcie do outRect, aby dzielnik znalazł się poza elementem. Alternatywnie można zastąpić onDrawOver () zamiast onDraw (), aby narysować dzielnik po elemencie.
jpop,
115
Najlepszą odpowiedzią jest cała strona kodu, aby po prostu dodać dzielnik do recyclinglerView. Wstydź się, google.
ostrożnie7j
480

Poprostu dodaj

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

Konieczne może być również dodanie zależności
compile 'com.android.support:recyclerview-v7:27.1.0'

EDYTOWAĆ:

Aby go nieco dostosować, możesz dodać niestandardową rysownię:

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

Możesz swobodnie korzystać z dowolnych niestandardowych rysunków, na przykład:

<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
źródło
Aktywność nie jest potrzebna. Kontekst jest wystarczający
mac229,
To musi być poprawna odpowiedź. Plz, zmień getActivity na sam kontekst.
Jhon Fredy Trujillo Ortega
Lepiej też uzyskać orientację z menedżera LayoutManager.
lsrom
Dziękuję Ci! Możesz również użyć Configurationpionowego dzielnika:if (orientation == Configuration.ORIENTATION_LANDSCAPE) { recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL)); } else { recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));}
AlexS
3
Dobra odpowiedź, ale dodaje dzielnik również po ostatnim elemencie.
CoolMind
256

Czy mogę skierować twoją uwagę na ten konkretny plik na Githubie autorstwa Alexa Fu: https://gist.github.com/alexfu/0f464fc3742f134ccd1e

Jest to przykładowy plik DividerItemDecoration.java „pobrany bezpośrednio z demonstracji pomocy technicznej”. ( Https://plus.google.com/103498612790395592106/posts/VVEB3m7NkSS )

Po zaimportowaniu tego pliku do mojego projektu udało mi się uzyskać linie podziału i dodać go jako dekorację przedmiotu do widoku recyklera.

Oto jak wygląda mój onCreateView w moim fragmencie zawierającym Recyclerview:

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

Jestem pewien, że można wykonać dodatkową stylizację, ale jest to punkt wyjścia. :)

Duy Nguyen
źródło
Jak dodać zamienić te: „footerDividersEnabled”, „headerDividersEnabled”, „listSelector”, „fastScrollEnabled”, „smoothScrollbar”, „textFilterEnabled”?
programista Androida
Wszelkie uwagi na temat sposobu umieszczania stylizacji?
nizam.sp
aby zaprojektować to rozwiązanie, musisz zastąpić atrybut „android: listDivider” w swoim motywie
Pavel Dudka
1
Divider nie działa z RecyclerView. Musisz użyć RecyclerView.itemDecoration. Zobacz tę odpowiedź: stackoverflow.com/a/27664023/2311451
Cocorico
3
dlaczego dzielnik rozszerza całą szerokość przedmiotu? jak wyświetlić jak w specyfikacjach google.com/design/spec/components/lists.html#lists-specs
chip
156

Prosta ItemDecorationimplementacja zapewniająca równe odstępy między wszystkimi elementami.

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;
        }
    }
}
Siergiej A.
źródło
dostaję przestrzeń, ale jak zdobyć dzielnik
Pankaj Nimgade
26
getChildPositionjest teraz przestarzałe, getChildAdapterPositionmożna go użyć zamiast tego.
EyesClear
4
Nie zapomnij (jak to zrobiłem), aby usunąć połączenie z super.getItemOffsets, ponieważ twoje przesunięcia zostaną zastąpione.
jayeffkay
@EyesClear nie powinien getChildLayoutPositionbyć używany?
Avinash R
3
czy to implementuje odstępy w pikselach?
filthy_wizard
108

Najprościej jest ustawić kolor tła dla RecyclerView i inny kolor tła dla przedmiotów. Oto przykład ...

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

oraz element TextView (może to być cokolwiek) z dolnym marginesem „x” dp lub px.

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

Wyjście ...

wprowadź opis zdjęcia tutaj

Madan Sapkota
źródło
2
Co za sztuczka! wystarczy, że lista będzie biała podczas ładowania.
Hamzeh Soboh
36
Uważaj na overdraw!
shem
@ shehem czy mógłbyś to rozwinąć?
RominaV
7
Podczas rysowania w Androidzie kilka warstw jedna nad drugą (tło aktywności, tło widoku recyklingu i tło widoku elementu) - Android rysuje je wszystkie, również te niewidoczne dla użytkowników. To się nazywa overdraw i może wpłynąć na twoje wyniki, więcej na ten temat tutaj: youtube.com/watch?v=T52v50r-JfE
shem
41

Myślę, że za pomocą prostego dzielnika pomoże

Aby dodać rozdzielacz do każdej pozycji:
1 Dodaj do tego rozciągliwej katalogu 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:width="1dp"
    android:height="1dp" />
<solid android:color="#999999" />
</shape>

2- Utwórz klasę SimpleDividerItemDecoration
Użyłem tego przykładu do zdefiniowania tej klasy:
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- W aktywności lub fragmencie korzystającym z RecyclerView wewnątrz onCreateView dodaj to:

@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- Aby dodać odstępy między
elementami, wystarczy dodać właściwość wypełnienia do widoku elementu

<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
źródło
Jak sprawić, by działał w GridLayoutManager, aby wyświetlać również pionowe dzielniki między komórkami?
programista Androida
2
resources.getDrawable () jest teraz przestarzałe. Możesz przekazać w kontekście i użyć ContextCompat.getDrawable (w kontekście, R.drawable.line_divider)
Eric B.
36

Jak już ustawiłem ItemAnimators. ItemDecoratorNie wejść lub wyjść wraz z animacją.

Po prostu skończyło się na tym, że w moim pliku układu widoku każdego elementu znajdował się wiersz widoku. To rozwiązało moją sprawę. DividerItemDecorationwydawało się, że jest to zbyt wiele magii, by zwykły podział.

<View
    android:layout_width="match_parent"
    android:layout_height="1px"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:background="@color/lt_gray"/>
Javanator
źródło
Masz rację. Animacje nie działają z dekoracją elementu. Nie jestem pewien, dlaczego, ale bez mojej wiedzy, dostaję animacje i uważam, że bardzo rozpraszające i brzydkie jest to, że linie tworzone przez ItemDecoration nie podążają. Więc użyję rozwiązania takiego jak twoje.
Michel
Jak poradziłeś sobie z ostatnim przedmiotem?
seniorgod
@oldergod. Wskazałeś na właściwy punkt bólu. Najpierw zgodziłbym się, aby projekt miał również dzielnik na ostatni element. Ale jeśli tego nie chcesz. przypisz identyfikator do tego widoku i ukryj w bindView, jeśli pozycja jest ostatnia.
Javanator
@Javanator Widzę ok, to samo podejście, które podjąłem. dzięki.
seniorgod
najprostsze jest najlepsze
hyyou2010,
27

To proste, nie potrzebujesz tak skomplikowanego kodu

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

Dodaj to w swoim drawable: 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
źródło
21

Ponieważ nie ma właściwego sposobu na wdrożenie tego jeszcze poprawnie przy użyciu Material Design, właśnie wykonałem następującą sztuczkę, aby bezpośrednio dodać element dzielący do elementu listy:

<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/dividerColor"/>
Yoann Hercouet
źródło
DividerItemDecoration przestaje działać po tym, jak mam pewne informacje o wysokości konstrukcji materiału (aby uzyskać taki sam efekt jak w skrzynce odbiorczej); stało się to zbyt skomplikowane dla prostej rzeczy. To rozwiązanie jest proste i działa.
DenisGL
20

Sposób, w jaki obsługuję widok Divider, a także wstawki Divider, polega na dodaniu rozszerzenia RecyclerView.

1.

Dodaj nowy plik rozszerzenia, nazywając View lub RecyclerView:

RecyclerViewExtension.kt

i dodaj setDividermetodę rozszerzenia w pliku RecyclerViewExtension.kt.

/*
* 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)

Utwórz plik zasobów do rysowania w drawablepakiecie, taki jak 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>

gdzie możesz określić lewy i prawy margines na android:insetLefti android:insetRight.

3)

W przypadku działania lub fragmentu, w którym zainicjowano RecyclerView, można ustawić niestandardową funkcję rysowania, wywołując:

recyclerView.setDivider(R.drawable.recycler_view_divider)

4

Pozdrawiam 🍺

RecyclerView wiersz z dzielnikiem.

Gent Berani
źródło
16

Jeśli ktoś chce tylko dodać, powiedzmy, odstęp 10dp między elementami, możesz to zrobić, ustawiając opcję rysowania na DividerItemDecoration:

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

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

Gdzie divider_10dpmożna wyciągnąć zasób zawierający:

<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
źródło
11

Dla tych, którzy szukają tylko do przestrzeni pomiędzy elementami w RecyclerViewzobacz moje podejście, gdzie można dostać równe odstępy między wszystkich elementów, z wyjątkiem pierwszej i ostatniej pozycji, gdzie dałem większy wyściółkę. Nakładam tylko na lewą / prawą stronę w poziomie LayoutManageri na górę / dół w pozycji pionowej 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.");
        }
    }
}

dimens.xml

<resources>
    <dimen name="paddingItemDecorationDefault">10dp</dimen>
    <dimen name="paddingItemDecorationEdge">20dp</dimen>
</resources>
Ryan Amaral
źródło
11

Dodaj margines do swojego widoku, to zadziałało dla mnie.

android:layout_marginTop="10dp"

Jeśli chcesz po prostu dodać równe odstępy i chcą to zrobić w XML , wystarczy ustawić paddingna swoim RecyclerViewi równe ilości layoutMargindo elementu, który nadmuchać do swojej RecyclerView, i niech kolor tła określenia koloru dystansową.

Kwantowa materia
źródło
3
Chociaż to zadziała, nie jest to na przykład poprawna odpowiedź, ponieważ nie rozwiązuje to problemu bez robienia dodatkowych rzeczy w układzie wierszy, również u góry pojawi się margines x1, między wierszami margines x2.
Sreekanth Karumanaghat
To nie jest dobry pomysł, ponieważ overscrollefekt ciągnięcia na końcu listy spowoduje, że zostanie zastosowane niepotrzebne dopełnienie, gdy dopełnienie zostanie zastosowaneRecyclerView
AeroEchelon
Lepiej jest zawinąć układ elementu w Support <?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>
Card CardView,
11
  • Oto prosty hack, aby dodać dzielnik
  • Wystarczy dodać tło do układu elementu do recyklingu w następujący sposób

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

Utwórz następujący shape_border.xml w folderze z możliwością rysowania

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

Oto końcowy wynik - RecyclerView z dzielnikiem.

Oto końcowy wynik - RecyclerView z dzielnikiem.

turbandroid
źródło
1
To nie jest preferowane podejście. Mimo że @EyesClear odpowiedź inicjuje int w onDraw i parent.getChildAdapterPosition(view) != parent.getAdapter().getItemCount() - 1prawdopodobnie powinna być parent.getChildAdapterPosition(view) > 0wraz ze outRect.bottom = mVerticalSpaceHeightstawaniem się outRect.top = mVerticalSpaceHeight, powinna być zaakceptowaną odpowiedzią.
droppin_science
@droppin_science - Nie można tego zaniedbać, mówiąc tylko, że nie jest to preferowane podejście, daje mi dokładne wyniki zgodnie z oczekiwaniami, patrzę również na odpowiedź EyesClear, ale ta odpowiedź jest zbyt skomplikowana, aby można ją było podzielić na proste, jednak jeśli trzeba zrób trochę dodatkowej dekoracji z przedmiotem, to może być zaakceptowana odpowiedź.
turbandroid
W przypadku głosujących w dół odpowiedź ta została udzielona w czasie, gdy nie było oficjalnych klas dla DividerItemDecoration, więc po prostu porównaj przerwę czasową między tą odpowiedzią a następną odpowiedzią udzieloną przez Leo Droidcodera. :)
turbandroid
9

Rozwidliłem DividerItemDecoration ze starszej wersji i uprościłem go, aby pasował do mojego przypadku użycia, a także zmodyfikowałem go, aby narysować dzielniki tak, jak są rysowane w ListView, w tym dzielnik po ostatniej pozycji listy. Będzie to również obsługiwać pionowe animacje ItemAnimator:

1) Dodaj tę klasę do swojego projektu:

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) Dodaj dekorator do RecylerView:

recyclerView.addItemDecoration(new DividerItemDecoration(getActivity()));
Dowiedz się OpenGL ES
źródło
Prawidłowo, jest przeznaczony dla LinearLayoutManager. Możesz wziąć pod uwagę pomysł, aby dostosować go do GridLayoutManager.
Naucz się OpenGL ES
8

Zamiast tworzyć znak shape xmlzmiany wysokości i koloru dzielnika. Możesz tworzyć programowo

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
źródło
to przydatna odpowiedź
taha
7

Zaczerpnięte z wyszukiwania w Google, dodaj ten elementDekoracja do 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
źródło
Działa to dobrze tylko dla LinearLayoutManager. Co należy zrobić dla GridLayoutManager?
programista Androida
6

Ten link działał dla mnie jak urok:

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.");
        }
    }
}

Następnie w swojej działalności:

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

Lub to, jeśli używasz fragmentu:

mCategoryRecyclerView.addItemDecoration(
    new DividerItemDecoration(getActivity(), null));
Micro
źródło
1
Działa to dobrze, ale nie pokazuje dzielnika pod ostatnim elementem na liście. Muszę to tak: mShowFirstDivider = false, mShowLastDivider = true, ale to nie będzie działać. Masz pomysł, dlaczego?
skorygowany nocą
To nie może dobrze obsłużyć GridLayoutManager.
programista Androida
6

Możemy ozdobić przedmioty przy użyciu różnych dekoratorów dołączonych do widoku recyklera, takich jak DividerItemDecoration:

Po prostu użyj następujących ... wziętych z odpowiedzi 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);
    }
}

}, a następnie użyj powyższego w następujący sposób

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

Spowoduje to wyświetlenie dzielników między każdą pozycją na liście, jak pokazano poniżej:

wprowadź opis zdjęcia tutaj

A dla tych, którzy szukają więcej szczegółów, zapoznaj się z tym przewodnikiem Korzystanie z RecifflerView _ CodePath Android Cliffnotes

Niektóre odpowiedzi tutaj sugerują użycie marginesów, ale haczyk polega na tym, że: jeśli dodasz zarówno górny, jak i dolny margines, pojawią się oba dodane między elementami i będą zbyt duże. Jeśli dodasz tylko jedno z nich, nie będzie marginesu ani na górze, ani na dole całej listy. Jeśli dodasz połowę odległości u góry, połowę u dołu, zewnętrzne marginesy będą zbyt małe.

Tak więc jedynym poprawnym estetycznie rozwiązaniem jest dzielnik, w którym system wie, gdzie zastosować prawidłowo: między elementami, ale nie powyżej lub poniżej elementów.

Daj mi znać o wszelkich wątpliwościach w komentarzach poniżej :)

Anudeep Samaiya
źródło
1
To nie pokazuje, jak DividerItemDecorationwygląda kod.
IgorGanapolsky
1
Jest to klasa AOSP, wykopałem dla ciebie kod ..... gist.githubusercontent.com/alexfu/0f464fc3742f134ccd1e/raw/…
Anudeep Samaiya
Nie działa dobrze: nie obsługuje rzędów o różnej wysokości i nie pokazuje pionowego dzielnika dla siatek
programista Androida
5

Za późno, ale GridLayoutManagerużywam tego:

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

Działa to dla dowolnej liczby zakresów, którą masz.

Ollie.

Ollie Strevel
źródło
Jeśli chodzi o górną przestrzeń, jak byś ją zmienił na obsługę FlexboxLayoutManager?
programista Androida
5

Możesz łatwo dodawać programowo.

Jeśli Twoim menedżerem układu jest Linearlayout, możesz użyć:

DividerItemDecoration to RecyclerView.ItemDecoration, który może być używany jako dzielnik między elementami LinearLayoutManager. Obsługuje orientacje POZIOME i PIONOWE.

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

źródło

Beyaz
źródło
5

Wydaje mi się, że potrzebna jest prosta odpowiedź oparta na kodzie, która nie korzysta z XML

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
źródło
4

Jeśli chcesz dodać to samo miejsce dla przedmiotów, najprostszym sposobem jest dodanie górnego + lewego marginesu dla RecycleView i prawego + dolnego marginesu dla elementów karty.

dimens.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
źródło
4

Dodałem wiersz w elemencie listy, jak poniżej

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

1px narysuje cienką linię.

Jeśli chcesz ukryć dzielnik dla ostatniego wiersza, to divider.setVisiblity(View.GONE);w onBindViewHolder dla ostatniego elementu listy.

Raja Peela
źródło
1
Wolę ten, inni są zbyt skomplikowani.
Sam Chen
3

To RecyclerViewtrochę różni się od ListView. W rzeczywistości RecyclerViewpotrzebuje ListViewpodobnej struktury. Na przykład LinearLayout. LinearLayoutZawiera parametry do dzielenia każdego elementu. W kodzie poniżej mam RecyclerViewskłada się z CardViewobiektów wLinearLayout z „dopełnienie”, która stworzy jakąś przestrzeń pomiędzy elementami. Spraw, aby ta przestrzeń była naprawdę mała, a otrzymasz linię.

Oto widok Recycler w recyclinglerview_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>

A oto jak wygląda każdy element (i jest podzielony ze względu na Androida: wypełnienie w LinearLayout, które otacza wszystko.) W innym pliku: cards_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
źródło
3

Naprawdę łatwym rozwiązaniem jest użycie RecyclerView-FlexibleDivider

Dodaj zależność:

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

Dodaj do swojego recyklingu:

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

I jesteś skończony!

Cristan
źródło
działa jak urok ... uwielbiam udostępniać oprogramowanie typu open source.
Billy,
3

1.Jedną z tych dróg jest to, że dzięki widokowi kart i widokowi recyklera możemy łatwo dodać efekt jak dzielnik. dawny. https://developer.android.com/training/material/lists-cards.html

2. a drugim jest dodanie widoku jako dzielnika do list_item_layout widoku recyklera .

        <View
            android:id="@+id/view1"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/colorAccent" />
Vicky
źródło
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);
            }
        }
    }
}

Spowoduje to dodanie miejsca na górze i dole każdego elementu (lub po lewej i po prawej). Następnie możesz ustawić go na swój 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
źródło