-
你尝试过子类化吗 网格布局管理器 和重写 生成默认布局参数() 还有亲属? – 通用软件 评论 2015年2月15日22:35 -
我没有,我以为会有一种方法,我只是没有看到,以设置类似网格视图的间距。 我会试试的 – 尼克·H 评论 2015年2月15日22:44 -
stackoverflow.com/a/35226600/4176070 – 六氯环己烷 评论 2019年5月13日19:45 -
试试这个 gist.github.com/Arpit0492/cf14df02ddf53741df5dde864002e89c – Arpit J。 评论 2020年2月6日8:39
33个答案
公共类GridSpacingItemDecoration扩展了RecyclerView。 项目装饰{ 私有int spanCount; 私有int间距; private boolean includeEdge; public GridSpacingItemDecoration(int spanCount,int spacing,boolean includeEdge){ this.spanCount=span计数; this.space=间距; this.includeEdge=包含边缘; } @覆盖 public void getItemOffsets(Rect outRect,View View,RecyclerView父级,Recycle View.State状态){ int position=parent.getChildAdapterPosition(视图);// 项目位置 int column=位置%spanCount;// 项目列 if(包括Edge){ outRect.left=间距-列*间距/spanCount;// 间距-列*((1f/spanCount)*间距) outRect.right=(column+1)*间距/spanCount;// (列+1)*((1f/spanCount)*间距) 如果(位置<spanCount){//上边缘 outRect.top=间距; } outRect.bottom=间距;// 项目底部 }其他{ outRect.left=列*间距/spanCount;// 列*((1f/spanCount)*间距) outRect.right=间距-(列+1)*间距/spanCount;// 间距-(列+1)*((1f/spanCount)*间距) if(位置>=spanCount){ outRect.top=间距;// 项目顶部 } } } }
用法
1.无边缘
int span计数=3;// 3列 int间距=50;// 50像素 boolean includeEdge=false; recyclerView.addItemDecoration(新的GridSpacingItemDecorsion(spanCount,spacing,includeEdge));
2.带边缘
int span计数=3;// 3列 int间距=50;// 50像素 boolean includeEdge=true; recyclerView.addItemDecoration(新的GridSpacingItemDecorsion(spanCount,spacing,includeEdge));
-
21 -
11 伟大的回答; 一个提示:间距以px为单位(因此可以使用Math.round(someDpValue*getResources().getDisplayMetrics().density)将dp转换为px)) – 李兆光 评论 2016年3月3日19:40 -
三 它工作正常,但我有一个问题,我使用的是GridLayoutManager,spanCount为2(默认值),但用户可以更改spanCount,因此当spanCount从默认位置更改时,某些位置上的填充更为可见,例如spanCount将为3,而不是2,38,912,13等上的填充/边距。 – 哈里斯·库拉什 评论 2016年3月15日8:13 -
三 效果很好! 但我在使用StaggeredGridLayoutManager时遇到了一些问题。 imgur.com/XVutH5u 水平边距有时会有所不同。 – 乌夫科库 评论 2016年3月25日10:38 -
6 当布局为rtl(2列或更多)时,这不起作用。 当前,在rtl模式下,列之间的间距不正确。 当outRect.left位于rtl中时,需要将其替换为outRect.right。 – 马苏德·穆罕默德 评论 2017年7月17日6:15
公共类SpacesItemDecoration扩展了RecyclerView。 项目装饰{ 私有int空间; 公共空间项目装饰(int space){ this.space=空格; } @覆盖 public void getItemOffsets(Rect outRect,查看视图, RecyclerView父级,Recycler视图。 州-州){ outRect.left=空格; outRect.right=空间; outRect.bottom=空格; //仅为第一个项目添加上边距,以避免项目之间出现双重空格 if(parent.getChildLayoutPosition(view)==0){ outRect.top=空格; }其他{ outRect.top=0; } } }
mRecyclerView=(回收视图)rootView.findViewById(R.id.my_recycler_view); int spacingInPixels=getResources().getDimensionPixelSize(R.dimen.spacing); mRecyclerView.addItemDecoration(新的SpacesItemDecorsion(像素间距));
项目抵消装饰
公共类ItemOffsetDecoration扩展了RecyclerView。 项目装饰{ 私有int mItemOffset; 公共项目偏移装饰(int itemOffset){ mItemOffset=项目偏移; } public ItemOffsetDecoration(@NonNull上下文,@DimenRes int itemOffsetId){ this(context.getResources().getDimensionPixelSize(itemOffsetId)); } @覆盖 public void getItemOffsets(Rect outRect,View View,RecyclerView parent, 回收站视图。 州-州){ super.getItemOffsets(outRect,view,parent,state); outRect.集合(mItemOffset、mItemOffest、mItemOffset、mItemOffset); } }
实施
mRecyclerView.setLayoutManager(新的网格布局管理器(context,NUM_COLUMNS); ItemOffsetDecoration itemDecoration=新ItemOffsetDecoration(上下文,R.dimen.item_offset); mRecyclerView.addItemDecoration(itemDecoration);
<android.support.v7.widget。 回收站视图 android:id=“@+id/recyclerview_grid” android:layout_width=“匹配租金” android:layout_height=“match_parent” android:clipToPadding=“false” android:padding=“@dimen/item_offset”/>
已编辑
公共类ListSpacingDecoration扩展了RecyclerView。 项目装饰{ private static final int VERTICAL=OrientationHelper。 垂直; 私有int方向=-1; private int spanCount=-1; 私有int间距; private int半间距; public ListSpacingDecoration(上下文上下文,@DimenRs-int-spacingDimen){ spacing=context.getResources().getDimensionPixelSize(spacingDimen); 半间距=间距/2; } 公共列表间距装饰(int spacingPx){ 间距=间距Px; 半间距=间距/2; } @覆盖 public void getItemOffsets(Rect outRect,View View,RecyclerView父级,Recycle View.State状态){ super.getItemOffsets(outRect,view,parent,state); if(方向==-1){ orientation=getOrientation(父级); } 如果(spanCount==-1){ spanCount=getTotalSpan(父级); } int childCount=父项.getLayoutManager().getItemCount(); int childIndex=parent.getChildAdapterPosition(视图); int itemSpanSize=getItemSpanSize(父项,子索引); int spanIndex=getItemSpanIndex(父项,子索引); /*无效跨度*/ 如果(spanCount<1)返回; setSpacings(outRect、parent、childCount、childIndex、itemSpanSize、spanIndex); } 受保护的void setSpacings(Rect outRect,RecyclerView parent,int childCount,int child Index,int itemSpanSize,int spanIndex){ outRect.top=半间距; outRect.bottom=半间距; outRect.left=半间距; outRect.right=半间距; if(isTopEdge(parent、childCount、childIndex、itemSpanSize、spanIndex)){ outRect.top=间距; } if(isLeftEdge(parent、childCount、childIndex、itemSpanSize、spanIndex)){ outRect.left=间距; } if(isRightEdge(parent、childCount、childIndex、itemSpanSize、spanIndex)){ outRect.right=间距; } if(isBottomEdge(parent、childCount、childIndex、itemSpanSize、spanIndex)){ outRect.bottom=间距; } } @禁止警告(“全部”) protected int getTotalSpan(RecyclerView父级){ 回收站视图。 LayoutManager管理器=parent.getLayoutManager(); if(GridLayoutManager的mgr实例){ return((GridLayoutManager)管理器).getSpanCount(); }else if(交错网格布局管理器的mgr实例){ return((交错网格布局管理器)mgr).getSpanCount(); }else if(LinearLayoutManager的mgr实例){ 返回1; } 返回-1; } @禁止警告(“全部”) protected int getItemSpanSize(RecyclerView父级,int childIndex){ 回收站视图。 LayoutManager管理器=parent.getLayoutManager(); if(GridLayoutManager的mgr实例){ return((GridLayoutManager)mgr).getSpanSizeLookup().getSpranSize(childIndex); }else if(交错网格布局管理器的mgr实例){ 返回1; }else if(线性布局管理器的mgr实例){ 返回1; } 返回-1; } @禁止警告(“全部”) protected int getItemSpanIndex(RecyclerView父级,int childIndex){ 回收站视图。 LayoutManager管理器=parent.getLayoutManager(); if(GridLayoutManager的mgr实例){ return((GridLayoutManager)mgr).getSpanSizeLookup().getSpranIndex(childIndex,spanCount); }else if(交错网格布局管理器的mgr实例){ return childIndex%spanCount; }else if(线性布局管理器的mgr实例){ 返回0; } 返回-1; } @禁止警告(“全部”) protected int getOrientation(RecyclerView父级){ 回收站视图。 LayoutManager管理器=parent.getLayoutManager(); if(LinearLayoutManager的mgr实例){ return((LinearLayoutManager)管理器).getOrientation(); }else if(GridLayoutManager的mgr实例){ return((GridLayoutManager)管理器).getOrientation(); }else if(交错网格布局管理器的mgr实例){ return((StaggeredGridLayoutManager)管理器).getOrientation(); } 返回VERTICAL; } 受保护的布尔值isLeftEdge(RecyclerView父级,int childCount,int child Index,int itemSpanSize,int spanIndex){ if(方向==垂直){ 返回span索引==0; }其他{ return(childIndex==0)||isFirstItemEdgeValid((childIndex<spanCount),parent,childIndex); } } protected boolean isRightEdge(RecyclerView父级,int childCount,int childIndex,int itemSpanSize,int spanIndex){ if(方向==垂直){ return(spanIndex+itemSpanSize)==spanCount; }其他{ return isLastItemEdgeValid((childIndex>=childCount-spanCount),parent,childCount,childIndex,spanIndex); } } 受保护的布尔值isTopEdge(RecyclerView父级,int childCount,int child Index,int itemSpanSize,int spanIndex){ if(方向==垂直){ return(childIndex==0)||isFirstItemEdgeValid((childIndex<spanCount),parent,childIndex); }其他{ return span指数==0; } } protected boolean isBottomEdge(RecyclerView父级,int childCount,int childIndex,int itemSpanSize,int spanIndex){ if(方向==垂直){ return isLastItemEdgeValid((childIndex>=childCount-spanCount),parent,childCount,childIndex,spanIndex); }其他{ return(spanIndex+itemSpanSize)==spanCount; } } 受保护的布尔值isFirstItemEdgeValid(布尔值isOneOfFirstItems,RecyclerView父级,int childIndex){ int totalSpanArea=0; if(是OneOfFirstItems){ for(int i=childIndex;i>=0;i--){ totalSpanArea=总跨度面积+getItemSpanSize(父项,i); } } return是OneOfFirstItems&&totalSpanArea<=spanCount; } 受保护的布尔值isLastItemEdgeValid(布尔值isOneOfLastItems,RecyclerView父级,int childCount,int child Index,int spanIndex){ int totalSpanRemaining=0; if(是最后一项之一){ for(int i=childIndex;i<childCount;i++){ totalSpanRemaining=totalSpan Remaining+getItemSpanSize(父项,i); } } return isOneOfLastItems&&(totalSpanRemaining<=spanCount-spanIndex); } }
-
1 我在第一行项目后面有双跨度。 发生这种情况是因为parent.getChildCount()为第一项返回1,为第二项返回2,依此类推。所以,我建议为顶部边缘的项添加空格,例如:outRect.top=childIndex<spanCount? 像素间距:0; 并为每个项目添加底部空间:outRect.bottom=spacingInPixels; – 伊凡·P 评论 2015年5月24日12:53 -
-
三 我认为parent.getChildCount()应该更改为“parent.getLayoutManager().getItemCount(”。 此外,isBottomEdge函数需要更改为“return childIndex>=childCount-spanCount+spanIndex”。 在改变这些之后,我得到了相等的间距。 但请注意,如果跨距计数大于2,则此解决方案不会为我提供相等的项目大小,因为偏移值因位置而异。 – yqritc公司 评论 2015年5月27日2:31 -
1 @yqritc感谢您伤害了parent.getChildCount()。 我已经更新了我的答案以使用parent.getLayoutManager().getItemCount() 评论 2015年12月23日20:08 -
2
<CardView android:layout_width=“匹配租金” android:layout_height=“wrap_content” android:margin=“10dp”>
<回收站视图 android:layout_width=“匹配租金” android:layout_height=“wrap_content” android:padding=“10dp”/>
公共类SpacesItemDecoration扩展了RecyclerView。 项目装饰{ private int halfSpace; 公共空间项目装饰(内部空间){ this.halfSpace=空格/2; } @覆盖 public void getItemOffsets(Rect outRect,View View,RecyclerView父级,Recycle View.State状态){ if(parent.getPaddingLeft()!= 半空间){ parent.setPadding(半空间、半空间、半空、半空间); parent.setClipToPadding(false); } outRect.top=半空格; outRect.bottom=半空格; outRect.left=半空间; outRect.right=半空间; } }
mRecyclerView.addItemDecoration(新空间ItemDecorsion(mMargin));
-
1 -
-
-
只是右边少了? 这可能是因为xml中已经在左侧设置了一半空间作为leftPadding,并且此代码仅检查是否在RecyclerView上设置了左填充。 – 马克·赫瑟林顿 评论 2015年9月1日22:03 -
公共类GridSpacesItemDecoration扩展了RecyclerView。 项目装饰{ private final boolean includeEdge; 私有int间距; public GridSpacesItemDecoration(int间距,boolean includeEdge){ this.space=间距; this.includeEdge=包含边缘; } @覆盖 public void getItemOffsets(Rect outRect,View View,RecyclerView父级,Recycle View.State状态){ if(GridLayoutManager的parent.getLayoutManager()实例){ GridLayoutManager layoutManager=(GridLayotManager)父项.getLayoutManager(); int spanCount=布局管理器.getSpanCount(); int position=parent.getChildAdapterPosition(视图);// 项目位置 int column=位置%spanCount;// 项目列 if(包括Edge){ outRect.left=间距-列*间距/spanCount;// 间距-列*((1f/spanCount)*间距) outRect.right=(column+1)*间距/spanCount;// (列+1)*((1f/spanCount)*间距) if(位置<spanCount){//上边缘 outRect.top=间距; } outRect.bottom=间距;// 项目底部 }其他{ outRect.left=列*间距/spanCount;// 列*((1f/spanCount)*间距) outRect.right=间距-(列+1)*间距/span计数;// 间距-(列+1)*((1f/spanCount)*间距) if(位置>=spanCount){ outRect.top=间距;// 项目顶部 } } } } }
公共类GridAutofitLayoutManager扩展了GridLayoutManager{ private int mColumnWidth; 私有布尔值mColumnWidthChanged=true; public GridAutofitLayoutManager(上下文上下文,int columnWidth) { /*最初将spanCount设置为1,稍后将自动更改*/ 超(上下文,1); setColumnWidth(checkedColumnWidth(context,columnWith)); } public GridAutofitLayoutManager(上下文上下文,int unit,int columnWidth) { /*最初将spanCount设置为1,稍后将自动更改*/ 超(上下文,1); int pixColumnWidth=(int)TypedValue.applyDimension(unit,columnWith,context.getResources().getDisplayMetrics()); setColumnWidth(checkedColumn宽度(context,pixColumnWidth)); } public GridAutofitLayoutManager(上下文上下文,int columnWidth,int orientation,boolean reverseLayout) { /*最初将spanCount设置为1,稍后将自动更改*/ super(context,1,orientation,reverseLayout); setColumnWidth(checkedColumnWidth(context,columnWith)); } private int checkedColumnWidth(上下文上下文,int columnWith) { if(列宽<=0) { /*设置默认的columnWidth值(此处为48dp)。 最好移动这个常数 在顶部设置为静态常量,但我们需要上下文将其转换为dp,所以不能 这样做*/ columnWidth=(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,48, context.getResources().getDisplayMetrics()); } return columnWidth;返回列宽度; } 公共void setColumnWidth(int newColumnWidth) { if(newColumnWidth>0&&newColumn Width!=m列宽度) { mColumnWidth=newColumnWidth; mColumnWidthChanged=真; } } @覆盖 公共void onLayoutChildren(RecyclerView.Recycler回收器,Recycler-View.State状态) { int width=获取宽度(); int height=getHeight(); if(mColumnWidthChanged&&mColumnWidth>0&&width>0&&height>0) { int totalSpace; if(getOrientation()==垂直) { totalSpace=宽度-getPaddingRight()-getPadingLeft(); } 其他的 { totalSpace=高度-getPaddingTop()-getPadingBottom(); } int spanCount=数学最大值(1,totalSpace/mColumnWidth); 设置跨度计数(spanCount); mColumnWidthChanged=假; } super.onLayoutChildren(州回收商); } }
mDevicePhotosView.setLayoutManager(新的网格自动布局管理器(getContext(),getResources().getDimensionPixelSize(R.dimen.item_size))); mDevicePhotosView.addItemDecoration(新的GridSpacesItemDecorsion(Util.dpToPx(getContext(),2),true));
公共类GridSpacingItemDecoration扩展了RecyclerView。 项目装饰{ 私有int mSpanCount; 私有浮点mItemSize; public GridSpacingItemDecoration(int spanCount,int itemSize){ this.mSpanCount=span计数; mItemSize=项大小; } @覆盖 public void getItemOffsets(final Rect outRect,final View View,RecyclerView parent, 回收站视图。 州-州){ 最终int位置=parent.getChildLayoutPosition(视图); 最终int列=位置%mSpanCount; final int parentWidth=parent.getWidth(); int间距=(int)(parentWidth-(mItemSize*mSpanCount))/(mSpan计数+1); outRect.left=间距-列*间距/mSpanCount; outRect.right=(列+1)*间距/mSpanCount; if(位置<mSpanCount){ outRect.top=间距; } outRect.bottom=间距; } }
<线性布局 xmlns:android=“ http://schemas.android.com/apk/res/android " android:layout_width=“@dimen/recycler_view_item_width” ... > ... </LinearLayout>
<dimen name=“recycler_view_item_width”>60dp
int numberOfColumns=3; mRecyclerView.setLayoutManager(新的网格布局管理器(this,numberOfColumns)); mRecyclerView.setAdapter(…); mRecyclerView.addItemDecoration(新的GridSpacingItemDecoration(3, getResources().getDimensionPixelSize(R.dimen.recycler_view_item_width));
类GridSpacingItemDecoration(private val columnCount:Int,@Px preferredSpace:Int、private val includeEdge:Boolean):回收视图。 项目装饰(){ /** *在该算法中,空间应除以3而无余量或项目宽度可以有差异 *我们希望它们完全相同 */ 私有val空间=if(preferredSpace%3==0)preferredSpace else(preferredSpace+(3-preferredSpace%3)) override fun getItemOffsets(outRect:Rect,view:view,parent:RecyclerView,state:RecyclerView.state?){ val位置=parent.getChildAdapterPosition(视图) if(包括Edge){ 何时{ 位置%columnCount==0->{ outRect.left=空格 outRect.right=空格/3 } 位置%columnCount==columnCont-1->{ outRect.right=空间 outRect.left=空格/3 } 其他->{ outRect.left=空格*2/3 outRect.right=空间*2/3 } } if(位置<columnCount){ outRect.top=空格 } outRect.bottom=空格 }其他{ 何时{ 位置%columnCount==0->outRect.right=空格*2/3 位置%columnCount==columnCount-1->outRect.left=空格*2/3 其他->{ outRect.left=空格/3 outRect.right=空格/3 } } if(位置>=columnCount){ outRect.top=空格 } } } }
<androidx.cardview.widget。 CardView(卡片视图) xmlns:app=“ http://schemas.android.com/apk/res-auto " app:cardUseCompatAdding=“true” app:cardElevation=“2dp”>
公共类GridSpacingItemDecoration扩展了RecyclerView。 项目装饰{ 私有int spanCount; 私有int间距; private boolean includeEdge; private int headerNum; 私有布尔值isRtl=TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault())==ViewCompat。 布局_方向_ RTL; public GridSpacingItemDecoration(int spanCount,int spacing,boolean includeEdge,int headerNum){ this.spanCount=span计数; this.space=间距; this.includeEdge=包含边缘; this.headerNum=头编号; } @覆盖 public void getItemOffsets(Rect outRect,View View,RecyclerView父级,Recycle View.State状态){ int position=parent.getChildAdapterPosition(视图)-headerNum;// 项目位置 如果(位置>=0){ int column=位置%spanCount;// 项目列 如果(isRtl){ column=spanCount-1列; } if(包括Edge){ outRect.left=间距-列*间距/spanCount;// 间距-列*((1f/spanCount)*间距) outRect.right=(column+1)*间距/spanCount;// (列+1)*((1f/spanCount)*间距) if(位置<spanCount){//上边缘 outRect.top=间距; } outRect.bottom=间距;// 项目底部 }其他{ outRect.left=列*间距/spanCount;// 列*((1f/spanCount)*间距) outRect.right=间距-(列+1)*间距/spanCount;// 间距-(列+1)*((1f/spanCount)*间距) if(位置>=spanCount){ outRect.top=间距;// 项目顶部 } } }其他{ outRect.left=0; outRect.right=0; outRect.top=0; outRect.bottom=0; } } }
class VerticalGridSpacingDecoration(私有值间距:Int):RecyclerView。 项目装饰(){ 覆盖fun getItemOffsets( outRect:矩形, 视图:视图, 父级:RecyclerView, state:状态 ) { val layoutManager=parent.layoutManager为? 网格布局管理器 if(layoutManager==null ||layoutManager.orientation!=VERTICAL){ return super.getItemOffsets(outRect,view,parent,state) } val spanCount=布局管理器。spanCount val位置=parent.getChildAdapterPosition(视图) val列=位置%spanCount 带(outRect){ left=if(column==0)0 else间距/2 right=if(column==spanCount.dec())0 else间距/2 顶部=if(位置<spanCount)0其他间距 } } }
私有静态类MyItemDecoration扩展了RecyclerView。 项目装饰{ @覆盖 public void getItemOffsets(Rect outRect,View视图,RecyclerView父级,RecyclerView.State状态){ super.getItemOffsets(outRect,视图,父级,状态); int index=((StaggeredGridLayoutManager.LayoutParams)view.getLayoutParams()).getSpanIndex(); } }
公共类GridSpacingItemDecoration扩展了RecyclerView。 项目装饰{ 私有int spanCount; 私有int间距; private boolean includeEdge; public GridSpacingItemDecoration(int spanCount,int spacing,boolean includeEdge){ this.spanCount=span计数; this.space=间距; this.includeEdge=包含边缘; } @覆盖 public void getItemOffsets(Rect outRect,View View,RecyclerView父级,Recycle View.State状态){ 交错网格布局管理器。 LayoutParams params=(StaggeredGridLayoutManager.LayoutParams)视图.getLayoutPartams(); int列=params.getSpanIndex(); if(包括Edge){ outRect.left=间距-列*间距/spanCount;// 间距-列*((1f/spanCount)*间距) outRect.right=(列+1)*间距/span计数;// (列+1)*((1f/spanCount)*间距) if(位置<spanCount){//上边缘 outRect.top=间距; } outRect.bottom=间距;// 项目底部 }其他{ outRect.left=列*间距/spanCount;// 列*((1f/spanCount)*间距) outRect.right=间距-(列+1)*间距/span计数;// 间距-(列+1)*((1f/spanCount)*间距) if(位置>=spanCount){ outRect.top=间距;// 项目顶部 } } } }
类ItemOffsetDecoration:回收视图。 项目装饰{ //添加到填充的数量 私有val_itemOffset:Int 构造函数(itemOffset:Int){ _itemOffset=项目偏移 } 构造函数(@NonNull context:context,@DimenRes itemOffsetId:Int){ _itemOffset=上下文.resources.getDimensionPixelSize(itemOffsetId) } /** *将填充应用于[Rect](视图的容器)的所有边 */ 覆盖fun getItemOffsets(outRect:Rect,view:view,parent:RecyclerView,state:Recycle view.state){ super.getItemOffsets(outRect、view、parent、state) outRect.set(_itemOffset、_itemOffset、_itemOffset、_itemOffset) } }
类ItemDividerGrid(私有值numberOfColumns:Int,私有值rowSpacingDP:Float=0f,私有值columnSpacingDP:Float=0,私有值edgeSpacingVerticalDP:Float=0,私人值edgeSpaceHorizontalDP:Flota=0):ItemDecoration(){ 覆盖fun getItemOffsets(outRect:Rect,view:view,parent:RecyclerView,state:Recycle view.state){ val位置=parent.getChildAdapterPosition(视图) val numberOfRows=(parent.adapter?.itemCount?:-1)/numberOfColumns val列=位置%numberOfColumns val行=位置/列数 val上下文=view.context ///水平 when(列){ 0 -> { outRect.left=将Dp转换为像素(edgeSpaceVerticalDP,上下文) outRect.right=convertDpToPixel(columnSpacingDP/2,上下文) } 列数-1->{ outRect.left=convertDpToPixel(columnSpacingDP/2,上下文) outRect.right=将Dp转换为像素(edgeSpaceVerticalDP,上下文) } 其他->{ outRect.left=convertDpToPixel(columnSpacingDP/2,上下文) outRect.right=convertDpToPixel(columnSpacingDP/2,上下文) } } //垂直 何时(行){ 0 -> { outRect.top=将Dp转换为像素(edgeSpaceHorizontalDP,上下文) outRect.bottom=将Dp转换为像素(行间距DP/2,上下文) } 行数->{ outRect.top=convertDpToPixel(rowSpacingDP/2,上下文) outRect.bottom=将Dp转换为像素(edgeSpaceHorizontalDP,上下文) } 其他->{ outRect.top=convertDpToPixel(rowSpacingDP/2,上下文) outRect.bottom=将Dp转换为像素(行间距DP/2,上下文) } } } fun convertDpToPixel(dp:Float,context:context?):Int{ return if(context!=null){ val资源=context.resources val metrics=资源.displayMetrics (dp*(metrics.densityDpi.toFloat()/显示度量。 DENSITY_DEFAULT)).roundToInt() }其他{ val metrics=资源.getSystem().displayMetrics (dp*(metrics.densityDpi.toFloat()/DisplayMetrics)。 密度_DEFAULT)).roundToInt() } } }
公共类SpacesItemDecoration扩展了RecyclerView。 项目装饰{ 私有int空间; 私有int mNumCol; 公共空间项目装饰(int space,int numCol){ this.space=空格; this.mNumCol=numCol; } @覆盖 public void getItemOffsets(Rect outRect,查看视图, RecyclerView父级,Recycler视图。 州-州){ //outRect.right=空间; outRect.bottom=空格; //outRect.left=空格; //Log.d(“ttt”,“项目位置”+parent.getChildLayoutPosition(视图)); int position=parent.getChildLayoutPosition(视图); 如果(mNumCol<=2){ if(位置==0){ outRect.left=空格; outRect.right=空格/2; }其他{ if((位置%mNumCol)!= 0) { outRect.left=空格/2; outRect.right=空间; }其他{ outRect.left=空格; outRect.right=空格/2; } } }其他{ if(位置==0){ outRect.left=空格; outRect.right=空格/2; }其他{ if((位置%mNumCol)==0){ outRect.left=空格; outRect.right=空格/2; }else if((位置%mNumCol)==(mNumCol-1)){ outRect.left=空格/2; outRect.right=空间; }其他{ outRect.left=空格/2; outRect.right=空格/2; } } } if(位置<mNumCol){ outRect.top=空格; }其他{ outRect.top=0; } //仅为第一个项目添加上边距,以避免项目之间出现双重空格 /* if(parent.getChildLayoutPosition(view)==0){ }其他{ outRect.top=0; }*/ } }
recyclerView.addItemDecoration(新的SpacesItemDecorsion(spacingInPixels,numCol));
getChildAdapterPosition(视图) getChildLayoutPosition(视图)
public void getItemOffsets(Rect outRect,int itemPosition,RecyclerView父级)
public void getItemOffsets(Rect outRect,View View,RecyclerView父级,State State)
recyclerView.addItemDecoration(new recyclerView.ItemDecoration){ @覆盖 public void getItemOffsets(Rect outRect,int itemPosition,RecyclerView父级){ 适配器。 VH VH=(TheAdapter.VH)回收器View.findViewHolder用于适配器位置(itemPosition); 查看itemView=vh.itemView// itemView是viewHolder的基本视图 //或者可以使用View itemView=layoutManager.findViewByPosition(itemPosition)代替上面的两行。。。 未测试 交错网格布局管理器。 布局参数itemLayoutParams=(StaggeredGridLayoutManager.LayoutParams)itemView.getLayoutPartams(); int spanIndex=itemLayoutParams.getSpanIndex(); 如果(span索引==0) ... 其他的 ... } });
在另一个布局中包装CardView项目 为外部布局填充X/2(4dp) 使外部布局背景透明
<LinearLayout xmlns:android=“ http://schemas.android.com/apk/res/android " android:layout_width=“200dp” android:layout_height=“200dp” android:background=“@android:color/transparent” android:padding=“4dip”> <android.support.v7.widget。 CardView(卡片视图) android:layout_width=“匹配租金” android:layout_height=“match_parent”> </android.support.v7.widget。 CardView> </LinearLayout>
给你的回收站视图填充X/2(4dp)
<android.support.v7.widget。 回收站视图 android:layout_width=“匹配租金” android:layout_height=“match_parent” android:padding=“4dp”/>
添加的填充 0.5 dp 到 每个项目 添加的填充 -0.5分贝 到 回收视图 就这样!:)
类GridItemDecoration( val间距:Int, 私有值spanCount:Int, private val includeEdge:布尔 ) : 回收站视图。 项目装饰(){ /** *将填充应用于[Rect](视图的容器)的所有边 */ 覆盖fun getItemOffsets( outRect:矩形, 视图:视图, 父级:RecyclerView, 状态:RecyclerView。 州 ) { val position=parent.getChildAdapterPosition(view)//项目位置 val列=位置%spanCount//项列 if(包括Edge){ 出口矩形左= spacing-列*间距/spanCount//间距-列*((1f/spanCount)*间距) outRect.右侧= (第+1列)*间距/spanCount//(第+1栏)*((1f/spanCount)*间距) if(位置<spanCount){//上边缘 outRect.top=间距 } outRect.bottom=间距//项底部 }其他{ outRect.left(左出矩形)= 列*间距/spanCount//column*((1f/spanCount)*间距) outRect.右侧= 间距-(列+1)*间距/spanCount//间距-(列+1)*((1f/spanCourt)*间距) if(位置>=spanCount){ outRect.top=间距//项顶部 } } } }
回收商查看.addItemDecoration( 网格项装饰( resources.getDimensionPixelOffset(R.dimen.h1), 三, 真的 ) )
类RecyclerItemDecoration(私有值span计数:Int,私有值间距:Int):Recycler视图。 项目装饰(){ 覆盖fun getItemOffsets(outRect:Rect,view:view,parent:RecyclerView,state:Recycle view.state){ val spacing=数学.round(spacing*parent.context.resources.displayMetrics.density) val位置=parent.getChildAdapterPosition(视图) val列=位置%spanCount outRect.left=间距-列*间距/span计数 outRect.right=(列+1)*间距/spanCount outRect.top=如果(位置<spanCount)间距为0 outRect.bottom=间距 } }
公共类GridSpacingItemDecoration扩展了RecyclerView。 项目装饰{ 私有int spanCount; 私有int间距; private boolean includeEdge; private int headerNum; public GridSpacingItemDecoration(int spanCount,int spacing,boolean includeEdge,int headerNum){ this.spanCount=span计数; this.space=间距; this.includeEdge=包含边缘; this.headerNum=头编号; } @覆盖 public void getItemOffsets(Rect outRect,View View,RecyclerView父级,Recycle View.State状态){ int position=parent.getChildAdapterPosition(视图)-headerNum;// 项目位置 if(位置>=0){ int column=位置%spanCount;// 项目列 if(包括Edge){ outRect.left=间距-列*间距/spanCount;// spacing-列*((1f/spanCount)*间距) outRect.right=(column+1)*间距/spanCount;// (列+1)*((1f/spanCount)*间距) if(位置<spanCount){//上边缘 outRect.top=间距; } outRect.bottom=间距;// 项目底部 }其他{ outRect.left=列*间距/span计数;// 列*((1f/spanCount)*间距) outRect.right=间距-(列+1)*间距/spanCount;// 间距-(列+1)*((1f/spanCount)*间距) if(位置>=spanCount){ outRect.top=间距;// 项目顶部 } } }其他{ outRect.left=0; outRect.right=0; outRect.top=0; outRect.bottom=0; } } } }
int列=位置%spanCount
recyclerView.removeItemDecoration(gridItemDecorator) recyclerView.removeItemDecoration(listItemDecorator) if(showAsList){ recyclerView.layoutManager=线性布局管理器(this,LinearLayoutManager.VERTICAL,false) recyclerView.addItemDecoration(listItemDecorator) }其他{ recyclerView.layoutManager=网格布局管理器(this,spanCount) recyclerView.addItemDecoration(gridItemDecorator) }
实现“com.github.grzegorzojdana:SpacingItemDecoration:1.1.0”
public static int dpToPx(上下文c,int dp){ 资源r=c.getResources(); return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,r.getDisplayMetrics())); }
photosRecycler.addItemDecoration(新的间距项目装饰(2,dpToPx(this,4),true));
@禁止警告(“全部”) protected int getItemSpanSize(RecyclerView父级,View视图,int childIndex){ 回收站视图。 LayoutManager管理器=parent.getLayoutManager(); if(GridLayoutManager的mgr实例){ return((GridLayoutManager)mgr).getSpanSizeLookup().getSpranSize(childIndex); }else if(交错网格布局管理器的mgr实例){ return((交错网格布局管理器.LayoutParams)view.getLayoutParams()).isFullSpan()? span计数:1; }else if(线性布局管理器的mgr实例){ 返回1; } 返回-1; } @禁止警告(“全部”) protected int getItemSpanIndex(RecyclerView父级,View视图,int childIndex){ 回收站视图。 LayoutManager管理器=parent.getLayoutManager(); if(GridLayoutManager的mgr实例){ return((GridLayoutManager)mgr).getSpanSizeLookup().getSpranIndex(childIndex,spanCount); }else if(交错网格布局管理器的mgr实例){ return((StaggeredGridLayoutManager.LayoutParams)view.getLayoutParams()).getSpanIndex(); }else if(线性布局管理器的mgr实例){ 返回0; } 返回-1; }
内部类SpacesItemDecoration(itemSpace:Int):RecyclerView。 项目装饰(){ var空间:Int=itemSpace 覆盖fun getItemOffsets(outRect:Rect?,view:view?,parent:RecyclerView?,state:Recycle view.state?){ super.getItemOffsets(outRect、view、parent、state) val位置=父级!!。 获取儿童适配器位置(视图) val viewType=parent.adapter.getItemViewType(位置) //选中可不对标题项设置任何边距 if(viewType==GridViewAdapter.TYPE_HEADER){ 出矩形!!。 顶部=0 outRect.left=0 outRect.right=0 outRect.bottom=0 }其他{ 出矩形!!。 left=空格 outRect.right=空间 outRect.bottom=空格 if(parent.getChildLayoutPosition(view)==0){ outRect.top=空格 }其他{ outRect.top=0 } } } }
gridView.addItemDecoration(空间项目装饰(10))