RecyclerView에서 마지막 자식의 여백 / 패딩


126

마지막 행에 Padding / Margin Bottom을, 첫 번째 행에 Padding / Margin Top을 추가하려고합니다. 내 모든 차일드에 영향을 미치므로 항목 xml에서 할 수 없습니다.

내 RecyclerView 어댑터에 헤더와 차일이 있으므로 사용할 수 없습니다.

   android:padding="4dp"
   android:clipToPadding="false"

각 헤더의 마지막 첫 번째 행에서 개별적으로 사용해야합니다.


다음과 같이 사용하십시오. <android.support.v7.widget.RecyclerView android : id = "@ + id / list"android : paddingBottom = "5dp"android : layout_width = "match_parent"android : layout_height = "wrap_content"/>
Pankaj Arora

당신은 onBindViewHolder의 패딩과 마진을 변경 한 다음 뷰 홀더에 setIsRecyclable (거짓)를 호출 할 수
user3425867

답변:


9

나는 이것을 kotlin에서 사용합니다.

override fun onBindViewHolder(holder: RecyclerView.ViewHolder(view), position: Int) {
    if (position == itemsList.lastIndex){
        val params = holder.itemView.layoutParams as FrameLayout.LayoutParams
        params.bottomMargin = 100
        holder.itemView.layoutParams = params
    }else{
        val params = holder.itemView.layoutParams as RecyclerView.LayoutParams
        params.bottomMargin = 0
        holder.itemView.layoutParams = params
    }
  //other codes ...
}

233

이 문제는 훨씬 더 쉽게 해결할 수 있습니다. 필요한 패딩을 RecylerView자체에 적용 clipToPadding하고 false로 설정할 수 있습니다 . 그렇지 않으면 패딩으로 인해 스크롤 영역이 잘립니다. 다음은 예입니다.

<android.support.v7.widget.RecyclerView
    android:padding="4dp"
    android:clipToPadding="false"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

패딩은 상단과 하단을 포함한 모든면에 4dp를 추가합니다. 그런 다음 clipToPadding 매개 변수는 자식 항목이 잘리지 않도록합니다. 이제 4dp자녀 항목의 모든면에 패딩을 추가 하면 좋습니다. 총 8dp 패딩이 측면과 항목 사이에 표시됩니다.


그렇습니다.하지만 내 RecyclerView는 헤더로 구성되어 있고 각 헤더에는 자체
자식이 있으므로

이해가 안 돼요. 이것은 RecyclerView 내부의 헤더와 어떤 관련이 있습니까? 헤더에 패딩이 없도록 하시겠습니까? 이 경우에도 동일한 솔루션을 사용하여 왼쪽 및 오른쪽 패딩을 제거 할 수 있습니다.
Subin Sebastian

헤더가 있고 각 헤더에는 비 특정 하위 수가 있으므로 각 헤더의 마지막 하위에 상단 패딩 / 여백과 첫 번째 하위 및 하단 패딩 / 여백을 추가하고 싶습니다.
RedEagle

내가 가진 유일한 아이디어는 헤더의 레이아웃에 상단 및 하단 여백을 설정하는 것이었지만이를 달성하는 더 현명한 방법이 있는지 궁금합니다
RedEagle

이 경우 마지막 자녀 뒤에 가짜 항목을 RecyclerView에 추가 할 수 있습니다. 이것은 이것을 달성하는 가장 현명한 방법은 아니지만 가장 간단합니다. :)
Subin Sebastian

82

상단 및 하단 항목 모두에 패딩을 추가하는 대신 RecyclerView의 상단과 하단에 패딩을 추가하고 clipToPadding속성을로 설정할 수 false있습니다.

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:paddingTop="8dp"
    android:paddingBottom="8dp" />

그것은 쉬운 해결책이지만 내 RecyclerView에 헤더와
차일드가있어서

@RedEagle 원하는 효과를 얻었는지 확인하고 작동하지만 작동하는지 확신합니다.
Collins Abitekaniza 2015

1
이 솔루션은 아이템 데코레이션보다 낫습니다. ListAdapter를 사용하고 다른 목록을 제출할 때 이전 목록의 마지막 항목이 위치를 변경하지 않았지만 그 뒤에 새 항목이 추가 된 경우 전자는 목록의 마지막 항목이 아니더라도 맨 아래 패딩을 유지합니다. 더.
Ana Koridze 2019 년

38

사용 ItemDecoration:

private 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) {
        int position = parent.getChildAdapterPosition(view);
        boolean isLast = position == state.getItemCount()-1;
        if(isLast){
            outRect.bottom = space;
            outRect.top = 0; //don't forget about recycling...
        }
        if(position == 0){
            outRect.top = space;
            // don't recycle bottom if first item is also last
            // should keep bottom padding set above
            if(!isLast)
                outRect.bottom = 0;
        }
    }
}

//8dp as px
int space = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8,
            getResources().getDisplayMetrics()); // calculated
//int space = getResources().getDimensionPixelSize(
//    R.dimen.list_item_padding_vertical); // from resources
recyclerView.addItemDecoration(new SpacesItemDecoration(space));

1
이봐, RecyclerView.ItemDecoration이 더 이상 리소스 클래스를 얻는 것처럼 보이지 않습니다. 방금 생성자에 인수로 추가했습니다.
Krtko

2
Goog 솔루션! 반전 레이아웃 지원 : gist.github.com/Miha-x64/4e8754e72a1e65e3ca742744ea501f16
Miha_x64

2
이 답변은 찬성되어야합니다! Subin Sebastian의 대답은 잘 작동하지만 ItemDecoration 공간은 동일하지 않습니다.
iroiroys

1
그러나 제거 항목을 삽입 한 후에는 모든 항목에 대한 오프셋을 다시 그리지 않습니다
user924

notifyItemInserted/ Removed는 하나의 항목 만 그립니다 / 항목을 제거하고 청소하면 View다른 모든 자식은 그대로 유지되므로 사실 일 수 있습니다 . 예를 들어 어떤 항목이 목록에서 처음 (상단 패딩으로 그려 짐)하고 새 항목을 맨 위에 추가 할 때 이전의 첫 번째 현재 두 번째 항목이 여전히 맨 위에 채워집니다. 쉬운 수정은 호출하는 것입니다 notifyDataSetChanged(강제 다시 그리기 모두 ...), 더 복잡한 것은 첫 번째 및 / 또는 마지막 위치에있는 항목을 인식하고 이동 한 다음 호출하는 항목을 인식하기위한 로직이 필요합니다notifyItemChanged(newPositionOfOldFirstAndOrLastItem)
snachmsm

28
<android.support.v7.widget.RecyclerView
    android:id="@+id/rv_tpf"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clipToPadding="false"
    android:paddingBottom="100dp" />

추가 android:clipToPadding="false"하고 android:paddingBottom="100dp"당신의 recyclerview있다.


2
대박! 즉 완벽
KevinB

16

recyclerview에 android : clipToPadding = "false"및 android : paddingBottom = "65dp"를 추가하십시오. 리사이클 러 뷰 셀에서 팹 메뉴 버튼 및 작업을 사용하는 경우.

<androidx.recyclerview.widget.RecyclerView
      android:id="@+id/dinner_recycler_view"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:clipToPadding="false"
      android:paddingBottom="65dp"/>

3

어떤 이유로 오래된 clipToPadding=false솔루션이 작동하지 않습니다. 그래서 ItemDecoration을 추가했습니다

https://gist.github.com/kassim/582888fa5960791264fc92bc41fb6bcf

public class BottomPaddingDecoration extends RecyclerView.ItemDecoration {
    private final int bottomPadding;

    public BottomPaddingDecoration(int bottomPadding) {
        this.bottomPadding = bottomPadding;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
        if (position == parent.getAdapter().getItemCount() - 1) {
            outRect.set(0, 0, 0, bottomPadding);
        }
    }
}

1

나는 더 나은 @snachmsm 대답을 수정하고 올바르게 사용하는 방법을 알려줍니다.

public class SpacesItemDecoration extends DividerItemDecoration {
    private int space;

    public SpacesItemDecoration(Context clContext,int oriantation,int space) {
        super(clContext,oriantation);
        this.space = space;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect,view,parent,state);
        int position = parent.getChildAdapterPosition(view);
        boolean isLast = position == state.getItemCount()-1;
        if(isLast){
            outRect.bottom = space;
            outRect.top = 0; //don't forget about recycling...
        }
       /* if(position == 0){
            outRect.top = space;
            // don't recycle bottom if first item is also last
            // should keep bottom padding set above
            if(!isLast)
                outRect.bottom = 0;
        }*/
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.