一、前言
之前的方法在某些情况下使用会有问题,这个新的类适配了各种情况,可以在线下布局,网格布局,垂直,水平方向上都能实现很好的分隔效果。
二、使用方法详解
val build = IntervalItemDecoration.Builder().divider(space)//设置每个 item 之间的间距// .dividerHorrizontal(space)//设置 item 左右间隔// .dividerVertical(space)//设置 item 上下间隔.margin(space)//设置 recyclerview 四周间隔// .horriontalMargin(space)//设置 recyclerview 左右间隔// .verticalMargin(space * 2)//设置 recyclerview上下间隔// .leftMargin(space)//单独设置 recyclerview 左边间隔// .rightMargin(space)//单独设置 recyclerview 右边间隔// .topMargin(space)//单独设置 recyclerview 上边间隔// .bottomMargin(space)//单独设置 recyclerview 下边间隔.build()
三、详细代码和引入地址
class IntervalItemDecoration private constructor(private val builder: Builder) :RecyclerView.ItemDecoration() {//每个 item 上下左右两侧间隔private var divider = 0// 每个item左右两侧的间距private var dividerHorrizontal = 0// 每个item上下的间距private var dividerVertical = 0//整个 recyclerview 间距private var margin = 0//整个 recyclerview 左右间距private var horriontalMargin = 0//整个 recyclerview 上下间距private var verticalMargin = 0// 整个RecyclerView的左间距private var leftMargin = 0// 整个RecyclerView的顶部间距private var topMargin = 0// 整个RecyclerView的右间距private var rightMargin = 0// 整个RecyclerView的底部间距private var bottomMargin = 0override fun getItemOffsets(outRect: Rect,view: View,parent: RecyclerView,state: RecyclerView.State) {super.getItemOffsets(outRect, view, parent, state)// 得到当前Item在RecyclerView中的位置,从0开始// 得到当前Item在RecyclerView中的位置,从0开始val position = parent.getChildAdapterPosition(view)// 得到RecyclerView中Item的总个数// 得到RecyclerView中Item的总个数val count = parent.adapter!!.itemCountif (parent.layoutManager is GridLayoutManager) { // 网格布局val gridLayoutManager =parent.layoutManager as GridLayoutManager?// 得到网格布局的列数val spanCount = gridLayoutManager!!.spanCount// 判断该网格布局是水平还是垂直if (LinearLayoutManager.VERTICAL == gridLayoutManager.orientation) { // 垂直if (spanCount == 1) { // 列数为1verticalColumnOne(outRect, position, count)} else { // 列数大于1verticalColumnMulti(outRect, position, count, spanCount)}} else if (LinearLayoutManager.HORIZONTAL == gridLayoutManager.orientation) { // 水平if (spanCount == 1) { // 行数为1horizontalColumnOne(outRect, position, count)} else { // 行数大于1horizontalColumnMulti(outRect, position, count, spanCount)}}} else if (parent.layoutManager is LinearLayoutManager) { // 线性布局val layoutManager =parent.layoutManager as LinearLayoutManager?if (LinearLayoutManager.VERTICAL == layoutManager!!.orientation) { // 垂直verticalColumnOne(outRect, position, count)} else if (LinearLayoutManager.HORIZONTAL == layoutManager.orientation) { // 水平horizontalColumnOne(outRect, position, count)}} else if (parent.layoutManager is StaggeredGridLayoutManager) { // 流布局//TODO 瀑布流布局相关}}/*** 列表垂直且列数为1** @param outRect 包括左上右下四个参数,分别控制view左上右下的margin* @param position 当前view所处位置* @param count RecyclerView中Item的总个数*/private fun verticalColumnOne(outRect: Rect,position: Int,count: Int) {when (position) {0 -> { // 位置为0时(即第一个Item),不设置底部间距outRect[leftMargin, topMargin, rightMargin] = 0}count - 1 -> { // 最后一个ItemoutRect[leftMargin, dividerVertical, rightMargin] = bottomMargin}else -> { // 中间的Item,不设置底部间距outRect[leftMargin, dividerVertical, rightMargin] = 0}}}/*** 列表垂直且列数大于1** @param outRect 包括左上右下四个参数,分别控制view左上右下的margin* @param position 当前view所处位置* @param count RecyclerView中Item的总个数* @param spanCount 布局的列数*/private fun verticalColumnMulti(outRect: Rect,position: Int,count: Int,spanCount: Int) {// 由于是网格布局,故每个item宽度是固定的,这里计算出每个item的左右边距之和val mEachSpace: Int =(leftMargin + rightMargin + (spanCount - 1) * dividerHorrizontal) / spanCount// 通过计算得出总行数val totalRow = count / spanCount + if (count % spanCount == 0) 0 else 1// 计算得出当前view所在的行val row = position / spanCountval column = position % spanCountval diff = (mEachSpace - rightMargin - leftMargin) / (spanCount - 1)val left = (column + 1 - 1) * diff + leftMarginval right = mEachSpace - leftwhen (row) {0 -> {outRect[left, topMargin, right] = dividerVertical}totalRow - 1 -> {outRect[left, 0, right] = bottomMargin}else -> {outRect[left, 0, right] = dividerVertical}}}/*** 列表水平且行数为1** @param outRect 包括左上右下四个参数,分别控制view左上右下的margin* @param position 当前view所处位置* @param count RecyclerView中Item的总个数*/private fun horizontalColumnOne(outRect: Rect,position: Int,count: Int) {when (position) {0 -> { // 位置为0时(即第一个Item)outRect[leftMargin, topMargin, dividerHorrizontal / 2] = bottomMargin}count - 1 -> { // 最后一个ItemoutRect[dividerHorrizontal / 2, topMargin, rightMargin] = bottomMargin}else -> { // 中间的ItemoutRect[dividerHorrizontal / 2, topMargin, dividerHorrizontal / 2] = bottomMargin}}}/*** 列表水平且行数大于1** @param outRect 包括左上右下四个参数,分别控制view左上右下的margin* @param position 当前view所处位置* @param count RecyclerView中Item的总个数* @param spanCount 布局的行数*/private fun horizontalColumnMulti(outRect: Rect,position: Int,count: Int,spanCount: Int) {// 通过计算得出总列数val totalColumn = count / spanCount + if (count % spanCount == 0) 0 else 1// 计算得出当前view所在的列val column = position / spanCount// 通过对position加1对spanCount取余得到row// 保证row等于1为第一行,等于0为最后一个,其它值为中间行val row = (position + 1) % spanCountval mEachSpace: Int =(topMargin + bottomMargin + (spanCount - 1) * dividerVertical) / spanCountval diff = (mEachSpace - bottomMargin - topMargin) / (spanCount - 1)val top = (position % spanCount + 1 - 1) * diff + topMarginval bottom = mEachSpace - topwhen (row) {1 -> {outRect[if (column == 0) leftMargin else dividerHorrizontal / 2, top, if (column == totalColumn - 1) rightMargin else dividerHorrizontal / 2] =bottom}0 -> {outRect[if (column == 0) leftMargin else dividerHorrizontal / 2, top, if (column == totalColumn - 1) rightMargin else dividerHorrizontal / 2] =bottom}else -> {outRect[if (column == 0) leftMargin else dividerHorrizontal / 2, top, if (column == totalColumn - 1) rightMargin else dividerHorrizontal / 2] =bottom}}}class Builder {private val iid = IntervalItemDecoration(this)fun divider(divider: Int): Builder {iid.divider = dividerreturn this}fun dividerHorrizontal(dividerHorrizontal: Int): Builder {iid.dividerHorrizontal = dividerHorrizontalreturn this}fun dividerVertical(dividerVertical: Int): Builder {iid.dividerVertical = dividerVerticalreturn this}fun margin(margin: Int): Builder {iid.margin = marginreturn this}fun horriontalMargin(horriontalMargin: Int): Builder {iid.horriontalMargin = horriontalMarginreturn this}fun verticalMargin(verticalMargin: Int): Builder {iid.verticalMargin = verticalMarginreturn this}fun leftMargin(leftMargin: Int): Builder {iid.leftMargin = leftMarginreturn this}fun topMargin(topMargin: Int): Builder {iid.topMargin = topMarginreturn this}fun rightMargin(rightMargin: Int): Builder {iid.rightMargin = rightMarginreturn this}fun bottomMargin(bottomMargin: Int): Builder {iid.bottomMargin = bottomMarginreturn this}fun build(): IntervalItemDecoration {initSet()return iid}private fun initSet() {iid.run {if (divider != 0) {dividerHorrizontal = dividerdividerVertical = divider}if (margin != 0) {leftMargin = marginrightMargin = margintopMargin = marginbottomMargin = margin}if (verticalMargin != 0) {topMargin = verticalMarginbottomMargin = verticalMargin}if (horriontalMargin != 0) {leftMargin = horriontalMarginrightMargin = horriontalMargin}}}}}
