ProgramingTip

RecyclerView에서 항목 사이에 구분선과 공백을 추가하는 방법은 무엇입니까?

bestdevel 2020. 9. 28. 09:40
반응형

RecyclerView에서 항목 사이에 구분선과 공백을 추가하는 방법은 무엇입니까?


다음은 dividerdividerHeight 매개 변수를 ListView사용하여 이전에 클래스 에서 수행 할 수 있습니다.

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

그러나 나는 RecyclerView수업 에서 가능성을 보지 못합니다 .

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

이 경우 여백을 정의하거나 사용자 지정 구분선보기를 목록 항목의 레이아웃에 직접 추가해도? 아니면 목표를 달성하는 더 좋은 방법이 있습니까?


2016 년 10 월 업데이트

Android 지원 라이브러리 버전 25.0.0은 다음 클래스를 도입했습니다 .DividerItemDecoration

DividerItemDecoration은 .NET Framework의 항목 간 구분선으로 사용할 수있는 RecyclerView.ItemDecoration입니다 LinearLayoutManager. HORIZONTALVERTICAL방향을 모두 지원합니다 .

용법 :

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

이전 답변

일부 답변은 이후 더 이상 사용되지 않는 방법을 사용하거나 완전한 솔루션을 제공하지 않습니다. 최신 요약을 시도했습니다.


달리 ListViewRecyclerView클래스가 더 분할과 변수가 없습니다. 대신 확장 할 필요가 A, 의 내부 클래스 :ItemDecorationRecyclerView

ItemDecoration사용하면 응용 프로그램이 특수 도면 및 레이아웃을 추가 할 수 있습니다. 이 항목, 하이라이트, 그룹에서는 경계 등 사이의 구분선을 그리는 데 유용 할 수 있습니다.

모든 ItemDecorations(의 항목을보기 전에, 그들이 추가 된 순서대로 그려집니다 onDraw()() 및 항목 후 onDrawOver (에 Canvas, RecyclerView, RecyclerView.State).

Vertical 간격 ItemDecoration

확장 ItemDecoration하고 공간 height을 매개 변수로 사용하는 user-지정 생성자를 추가 하고 getItemOffsets()메서드를 재정의 합니다.

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

마지막 항목 아래에 공백을 추가하지.면 다음 조건을 추가하십시오

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

참고 : 당신은 또한 수정할 수 outRect.top, outRect.leftoutRect.right원하는 효과에, 대한 속성.

분할기 ItemDecoration

확장 ItemDecoration및 재정의 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);
        }
    }
}

기본 Android 구분선 속성을 사용하는 첫 번째 생성자 또는 고유 한 드로어 블을 사용하는 두 번째 생성자 (예 : 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>

참고 : 항목 위에 구분선을 그리려면 대신 메소드 onDrawOver()재정의하십시오 .

용법

클래스를 사용 새하려면 예를 들어 프래그먼트의 메서드 에서 VerticalSpaceItemDecoration또는 DividerSpaceItemDecoration추가 RecyclerView하십시오 onCreateView().

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

아이템 장식 과정을 단순화하는 Lucas Rocha의 라이브러리 도 있습니다 . 그래도 시도하지 않을 수 있습니다.

기능 은 다음과 가능합니다.

  • 다음을 포함 재고 항목 장식 컬렉션 :
  • 항목 간격 가로 / 세로 구분선.
  • 목록 항목

그냥 추가

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

또한 추가를 추가해야 할 수도 있습니다.
compile 'com.android.support:recyclerview-v7:27.1.0'

편집하다 :

약간의 사용자 정의를 위해 사용자 정의 드로어 블을 추가 할 수 있습니다.

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

예를 들어 사용자 정의 드로어 블을 자유롭게 사용할 수 있습니다.

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="@color/colorPrimary"/>
    <size android:height="0.5dp"/>
</shape>

Alex Fu의 Github에있는 특정 파일에주의를 주시겠습니까? https://gist.github.com/alexfu/0f464fc3742f134ccd1e

"지원 스크립트에서 직접 파일"DividerItemDecoration.java 예제 파일입니다. ( https://plus.google.com/103498612790395592106/posts/VVEB3m7NkSS )

내 프로젝트 에서이 파일을 여러 후 구분선을 멋지게 재활용 기보기에 항목 장식으로 추가 할 수 있습니다.

Recyclerview를 포함하는 내 조각에서 내 onCreateView가 어떻게 보이는지 다음과 가변됩니다.

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

추가 스타일링을 할 수 있는지 확신하지만 시작점입니다. :)


ItemDecoration모든 항목 사이의 동일한 공간에 대한 간단한 구현.

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

간단한 방법은 RecyclerView에 대한 배경색을 설정 하고 항목에 대해 다른 배경색을 설정하는 것입니다. 여기에 예가 있습니다 ...

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

그리고 하단 여백 "x"dp 또는 px가 있는 TextView 항목 (어떤 것이 든 가능).

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

출력 ...

여기에 이미지 설명 입력


간단한 구분선을 사용

하면 각 항목에 구분선을 추가하는 데 도움이 될 것이라고 생각합니다 .
1- 드로어 블 디렉토리 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- SimpleDividerItemDecoration 클래스 만들기가
예제를 사용 하여이 클래스를 정의했습니다.
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- RecyclerView를 사용하는 활동 또는 프래그먼트에서 onCreateView 내부에 다음을 추가하십시오.

@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- 항목 사이
에 간격을 추가 할 추가 항목보기에 패딩 속성을 추가하면됩니다.

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

내가 설정 한대로 ItemAnimators. ItemDecorator입력하거나 애니메이션과 함께 종료되지 않습니다.

나는 모든 항목의 항목보기 레이아웃을 끝냈다. 제 사건을 해결했습니다. DividerItemDecoration단순한 분배기에는 너무 많은 마법이라고합니다.

<View
    android:layout_width="match_parent"
    android:layout_height="1px"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:background="@color/lt_gray"/>

간단합니다. 이렇게 복잡한 코드가 필요하지 않습니다.

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

드로어 블에 추가하십시오 : 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>

머티리얼 디자인을 사용하여 제대로 구현할 수있는 올바른 방법이 없기 때문에 목록 항목에 구분선을 추가하기 위해 다음 트릭을 수행했습니다.

<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/dividerColor"/>

2016 년 10 월 업데이트

지원 라이브러리 v25.0.0을 사용하면 기본 수평 및 수직 분할기의 기본 구현을 사용할 수 있습니다!

https://developer.android.com/reference/android/support/v7/widget/DividerItemDecoration.html


항목 사이에 10dp 간격 만 추가하려는 경우 드로어 블을 DividerItemDecoration다음과 같이 설정하면 됩니다.

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

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

다음을 포함 divider_10dp하는 드로어 블 리소스는 어디에 있습니까?

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

단지를 찾고있는 사람들을 위해 항목 사이에 공백RecyclerView당신은 내가 더 큰 패딩을 준 첫 번째 항목과 마지막 항목을 사용하는 모든 항목과 동일한 공간을 내 접근 방식을 참조하십시오. 나는 패딩을 수평에서 왼쪽 / 오른쪽, 수직 LayoutManager에서 위 / 아래에만 적용 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>

  • 여기에 구분선을 추가하는 간단한 해킹이 있습니다.
  • 다음과 같이 리사이클 러 항목의 레이아웃에 배경을 추가하십시오.

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

드로어 블 폴더에 다음 shape_border.xml 생성

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

최종 결과는 다음과 가변적입니다. 구분선이있는 RecyclerView입니다.

최종 결과는 다음과 가변적입니다.  구분선이있는 RecyclerView입니다.


이 실제로 문제를 해결하지 못하지만 임시 해결 방법으로 XML 레이아웃의 카드에 useCompatPadding 속성을 설정하여 Lollipop 이전 버전에서와 동일하게 측정 할 수 있습니다.

card_view:cardUseCompatPadding="true"

당신의 견해에 여백을 추가하십시오.

android:layout_marginTop="10dp"

동일한 간격 을 추가 하고 XML 에서 수행 할 추가 확장 항목에 동일한 양을 설정 padding하고 배경색이 간격 색상을 결정합니다.RecyclerViewlayoutMarginRecyclerView


이전 요점에서 DividerItemDecoration을 분기하고 사용 사례에 맞게 단순화 된 마지막 목록 뒤의 구분선을 포함하여 ListView에서 그리는 방식으로 그리도록 수정 항목이 있습니다. 이는 수직 ItemAnimator 애니메이션도 처리합니다.

1)이 클래스를 프로젝트에 추가하십시오.

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) RecylerView에 데코레이터 추가 :

recyclerView.addItemDecoration(new DividerItemDecoration(getActivity()));

구글에서 검색 가져온 다음 ItemDecoration 을 다음에 추가 하십시오 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.");
    }
}
}

이 링크는 나에게 매력처럼 작동했습니다.

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

그런 다음 활동에서 :

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

또는 조각을 사용하는 경우 :

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

DividerItemDecoration과 같이 recyclerview에 다양한 데코레이터를 사용하여 항목을 장식 할 수 있습니다.

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

} 다음과 같이 위를 사용하십시오.

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

다음은 같이 목록 내의 각 항목 사이에 구분선이 표시됩니다.

여기에 이미지 설명 입력

더 자세한 정보를 원하시는 분들은이 가이드 에서 RecyclerView 사용 _ CodePath Android Cliffnotes를 확인하세요.

여기에 몇 가지 대답은 여백 사용을 제안하지만 문제는 다음과 같습니다. 추가 된 항목 및 여백을 모두 추가하면 나타나고 너무 커집니다. 둘 중 하나만 추가하면 전체 목록의 맨 위 또는 맨 아래에 여백이 없습니다. 거리의 절반을 위쪽에, 절반을 아래쪽에 추가하면 바깥 쪽 여백이 너무 작아집니다.

따라서 미학적으로 올바른 해결책은 시스템이 존재하게 적용 할 위치를 알고있는 구분선입니다.

아래 의견에 의문 사항이 있으면 알려주십시오. :)


너무 늦 GridLayoutManager습니다만 사용합니다.

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

이것은 당신이 모든 스팬에 대해 작동합니다.

올리.


shape xmlfor change을 만드는 대신 구분선 높이와 색상을 변경하십시오. 다음과 같이 프로그래밍 방식으로 만들 수 있습니다.

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)

항목에 대해 동일한 공간을 추가하려는 경우 가장 간단한 방법은 RecycleView에 대해 위쪽 + 왼쪽 여백을 추가하고 카드 항목에 오른쪽 + 하단 여백을 추가하는 것입니다.

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

같이 목록 항목에 줄을 추가했습니다.

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

1px 는가는 선을 그립니다.

마지막 행에 대한 구분선을 숨기려면 divider.setVisiblity(View.GONE);마지막 목록 항목의 onBindViewHolder에서.


프로그래밍 방식으로 쉽게 추가 할 수 있습니다.

레이아웃 관리자가 선형 레이아웃 인 경우 다음에서 사용할 수 있습니다.

DividerItemDecoration은 LinearLayoutManager의 항목 간 구분선으로 사용할 수있는 RecyclerView.ItemDecoration입니다. HORIZONTAL 및 VERTICAL 방향을 모두 지원합니다.

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

출처


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

RecyclerView에서 조금 다르다 ListView. 실제로 RecyclerViewListView비슷한 구조가 필요 합니다. 예를 들어 LinearLayout. LinearLayout(가의 각 요소를 구분하는)의 각 요소를 나타냅니다. 아래 코드 에서 항목 사이에 약간의 공간을 두는 "패딩"이있는 개체 RecyclerView구성 되어 있습니다. 그 공간을 정말 작게 만들면 선이 생생합니다.CardViewLinearLayout

다음은 recyclerview_layout.xml의 Recycler보기입니다.

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

그리고 다음은 다른 파일에있는 각 항목의 모양입니다 (그리고 모든 항목을 둘러싼 LinearLayout의 android : padding으로 인해 분할 된 것으로 표시됩니다.) : 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>

정말 쉬운 해결책은 RecyclerView-FlexibleDivider 를 사용하는 것입니다.

추가 추가 :

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

recyclerview에 추가하십시오.

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

그리고 당신은 끝났습니다!


1. 방법 중 하나는 cardview와 recycler view를 함께 사용하여 디바이더와 같은 효과를 쉽게 추가 할 수 있습니다. 전의. https://developer.android.com/training/material/lists-cards.html

2. 또 다른 방법은 리사이클 러 뷰의 list_item_layout에 구분선으로 뷰를 추가하는 입니다.

        <View
            android:id="@+id/view1"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/colorAccent" />

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


    }
}

이렇게하면 모든 항목의 상단과 하단 (또는 오른쪽과 오른쪽)에 공간이 추가되고 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);
    }
}

자체 버전의 RecyclerView.ItemDecoration 구현

public class SpacingItemDecoration extends RecyclerView.ItemDecoration {
    private int spacingPx;
    private boolean addStartSpacing;
    private boolean addEndSpacing;

    public SpacingItemDecoration(int spacingPx) {
        this(spacingPx, false, false);
    }

    public SpacingItemDecoration(int spacingPx, boolean addStartSpacing, boolean addEndSpacing) {
        this.spacingPx = spacingPx;
        this.addStartSpacing = addStartSpacing;
        this.addEndSpacing = addEndSpacing;
    }

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

        if (addStartSpacing && parent.getChildLayoutPosition(view) < 1 || parent.getChildLayoutPosition(view) >= 1) {
            if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
                outRect.top = spacingPx;
            } else {
                outRect.left = spacingPx;
            }
        }

        if (addEndSpacing && parent.getChildAdapterPosition(view) == getTotalItemCount(parent) - 1) {
            if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
                outRect.bottom = spacingPx;
            } else {
                outRect.right = spacingPx;
            }
        }
    }

    private int getTotalItemCount(RecyclerView parent) {
        return parent.getAdapter().getItemCount();
    }

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

참고 URL : https://stackoverflow.com/questions/24618829/how-to-add-dividers-and-spaces-between-items-in-recyclerview

반응형