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?



@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

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>

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. :)


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

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


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>

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

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>

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

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.


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>



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>

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ą.


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.


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

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)

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

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

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


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.


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


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

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

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.


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>

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!


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

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);
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.