1,系統(tǒng)自帶的間割線
系統(tǒng)自帶的間割線實(shí)現(xiàn)方法很簡(jiǎn)單,看下面的代碼:
rv_content.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
rv_content.adapter = rcAdapter
rv_content.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
這樣就實(shí)現(xiàn)了間割線的添加,效果如下:

上面的效果,是將方向設(shè)置為:LinearLayoutManager.VERTICAL,那么將方向設(shè)置為LinearLayoutManager.HORIZONTAL,此時(shí)效果為:

上面的顯示方式為LinearLayoutManager,那么將顯示方式設(shè)置為GridLayoutManager時(shí),也就是:
rv_content.layoutManager = GridLayoutManager(this, 3,GridLayoutManager.VERTICAL, false)
此時(shí)的效果為:

此時(shí),應(yīng)該察覺(jué)到,系統(tǒng)提供的間隔線類DividerItemDecoration只能適用于一些簡(jiǎn)單的情形。當(dāng)布局復(fù)雜時(shí),系統(tǒng)的間隔線就不能滿足我們的要求了,此時(shí)我們就要自己動(dòng)手來(lái)寫一個(gè)自己的間隔線或者使用第三方的間隔線。
2, 自定義間隔線
通過(guò)閱讀代碼,我們可以發(fā)現(xiàn)系統(tǒng)間割線DividerItemDecoration是繼承RecyclerView.ItemDecoration并實(shí)現(xiàn)了onDraw()和getItemOffsets()方法 。
那么我們照著DividerItemDecoration來(lái)寫自己的間隔線類MyItemDecoration,代碼如下:
class MyItemDecoration(context: Context) : RecyclerView.ItemDecoration(){
private var mOrientation: Int? = null
private var dividerLine: Drawable? = null
init {
val typedArray = context.obtainStyledAttributes(ATTRS)
dividerLine = typedArray!!.getDrawable(0)
typedArray.recycle()
}
override fun onDraw(c: Canvas?, parent: RecyclerView?, state: RecyclerView.State?) {
drawHorizontalLine(c, parent, state)
drawVerticalLine(c, parent, state)
}
override fun getItemOffsets(outRect: Rect?, view: View?, parent: RecyclerView?, state: RecyclerView.State?) {
val spanCount = getSpanCount(parent)
val childCount = parent!!.adapter.itemCount
val itemPosition = ((view!!.layoutParams)as RecyclerView.LayoutParams).viewLayoutPosition
if (isLastRow(parent, itemPosition, spanCount, childCount)){
outRect!!.set(0, 0, dividerLine!!.intrinsicWidth, 0)
}else if (isLastColum(parent, itemPosition, spanCount, childCount)){
outRect!!.set(0, 0, 0, dividerLine!!.intrinsicHeight)
}else{
outRect!!.set(0, 0, dividerLine!!.intrinsicWidth, dividerLine!!.intrinsicHeight)
}
}
/**
* 畫豎線
*/
private fun drawVerticalLine(c: Canvas?, parent: RecyclerView?, state: RecyclerView.State?) {
for (i in 0..(parent!!.childCount - 1)){
val child: View = parent.getChildAt(i)
//獲取child布局參數(shù)
val params: RecyclerView.LayoutParams = child.layoutParams as RecyclerView.LayoutParams
val left = child.right + params.rightMargin
val right = left + dividerLine!!.intrinsicWidth
val top = child.top - params.topMargin
val bottom = child.bottom + params.bottomMargin
dividerLine!!.setBounds(left, top, right, bottom)
dividerLine!!.draw(c)
}
}
/**
* 畫橫線
*/
private fun drawHorizontalLine(c: Canvas?, parent: RecyclerView?, state: RecyclerView.State?) {
for (i in 0..(parent!!.childCount - 1)){
val child: View = parent.getChildAt(i)
val params: RecyclerView.LayoutParams = child.layoutParams as RecyclerView.LayoutParams
val left = child.left - params.leftMargin
val right = child.right + params.rightMargin+ dividerLine!!.intrinsicWidth
val top = child.bottom + params.bottomMargin
val bottom = top + dividerLine!!.intrinsicHeight
dividerLine!!.setBounds(left, top, right, bottom)
dividerLine!!.draw(c)
}
}
/**
* 獲取列數(shù)
*/
private fun getSpanCount(parent: RecyclerView?): Int{
var spanCount: Int = -1
val layoutManager: RecyclerView.LayoutManager = parent!!.layoutManager
if (layoutManager is GridLayoutManager){
spanCount = layoutManager.spanCount
}else if(layoutManager is StaggeredGridLayoutManager){
spanCount = layoutManager.spanCount
}
return spanCount
}
/**
* 判定是否為最后一列
*/
private fun isLastColum(parent: RecyclerView?, pos: Int, spanCount: Int, childCount: Int): Boolean{
val layoutManager: RecyclerView.LayoutManager = parent!!.layoutManager
if (layoutManager is GridLayoutManager){
if ((pos + 1)% spanCount == 0) {//如果是最后一列,則不在繪制右邊
return true
}
}else if(layoutManager is StaggeredGridLayoutManager){
val orientation = layoutManager.orientation
if (orientation == StaggeredGridLayoutManager.VERTICAL){
if ((pos + 1)% spanCount == 0) {//如果是最后一列,則不在繪制右邊
return true
}
}else{
val childNum = childCount - childCount % spanCount
if (pos >= childNum) {
return true
}
}
}
return false
}
/**
* 判定是否為最后一行
*/
private fun isLastRow(parent: RecyclerView?, pos: Int, spanCount: Int, childCount: Int): Boolean{
val layoutManager: RecyclerView.LayoutManager = parent!!.layoutManager
if (layoutManager is GridLayoutManager){
val childNum = if(childCount % spanCount == 0) childCount - spanCount else childCount - childCount % spanCount
if (pos >= childNum) {//如果是最后一行,則不在繪制底邊
return true
}
}else if(layoutManager is StaggeredGridLayoutManager){
val orientation = layoutManager.orientation
if (orientation == StaggeredGridLayoutManager.VERTICAL){//縱向滾動(dòng)
val childNum = childCount - childCount % spanCount
if (pos >= childNum) {//如果是最后一行,則不在繪制底邊
return true
}
}else{//橫向滾動(dòng)
if ((pos + 1) % spanCount == 0) {
return true
}
}
}
return false
}
companion object{
private var ATTRS = intArrayOf(android.R.attr.listDivider)
}
}
運(yùn)行程序,看效果圖為:

3,第三方分割線
請(qǐng)參考:
github地址:[Y_DividerItemDecoration]:(https://github.com/yanyusong/Y_DividerItemDecoration)
下面來(lái)看看對(duì)這個(gè)第三方j(luò)ar包的簡(jiǎn)單使用示例:

實(shí)現(xiàn)這個(gè)效果也很簡(jiǎn)單,代碼為:
class RecyclerViewNewListDividerActivity: BaseKotlinActivity(){
private var mAdapter: Y_MultiRecyclerAdapter? = null
private var y_ItemEntityList: Y_ItemEntityList? = null
private var context: Context = this
override fun getLayoutResoucesId(): Int {
return R.layout.activity_recycler_view_simple
}
override fun init() {
y_ItemEntityList = Y_ItemEntityList()
initToolBarScroll()
y_ItemEntityList!!.addItems(R.layout.item_rc_4st, itemList).addOnBind(R.layout.item_rc_4st
, object : Y_OnBind<String>{
override fun onBindChildViewData(holder: GeneralRecyclerViewHolder?, itemData: String?, position: Int) {
holder!!.setText(R.id.tv, itemData)
}
})
rv_content.layoutManager = GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false)//設(shè)置顯示方式--瀑布流
mAdapter = Y_MultiRecyclerAdapter(this, y_ItemEntityList)
rv_content.adapter = mAdapter
/**
* 第三方----子項(xiàng)之間的分割線位置
*/
rv_content.addItemDecoration(MyDividerItemDecoration(this))
mAdapter!!.setOnItemClickListener { position -> showToast("onClick-->"+ position) }
}
private fun initToolBarScroll() {
val param: AppBarLayout.LayoutParams = tb_toolbar.layoutParams as AppBarLayout.LayoutParams
param.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED
}
class MyDividerItemDecoration(val context: Context): Y_DividerItemDecoration(context) {
override fun getDivider(itemPosition: Int): Y_Divider {
var divider: Y_Divider? = null
when(itemPosition) {
else -> {
/**
* 設(shè)置底部線
* setBottomSideLine(boolean isHave, @ColorInt int color, float widthDp, float startPaddingDp, float endPaddingDp)
* isHave:true 顯示線;false 不顯示
* color:線的顏色。@ColorInt int color 表示這里需要的是一個(gè)顏色值,而不是顏色id。因此直接使用R.color.XXX是不行的,可以通過(guò)ContextCompat.getColor(context, R.color.black)來(lái)獲取
* widthDp:線的高度
* startPaddingDp:距離左邊多少dp開(kāi)始畫線
* endPaddingDp:距離右邊多少dp停止畫線
*/
val count = if(itemList.size%2==0) itemList.size - 2 else itemList.size - itemList.size%2
if (itemPosition >= count){
if (itemPosition % 2 == 0){
divider = Y_DividerBuilder().setRightSideLine(true, ContextCompat.getColor(context, R.color.colorAccent), 2F, 0F, 0F)
.create()
}else{
divider = Y_DividerBuilder().setBottomSideLine(true, ContextCompat.getColor(context, R.color.trans), 2F, 0F, 0F).create()
}
}else{
if (itemPosition % 2 == 0){
divider = Y_DividerBuilder().setRightSideLine(true, ContextCompat.getColor(context, R.color.colorAccent), 2F, 0F, 0F)
.setBottomSideLine(true, ContextCompat.getColor(context, R.color.black), 2F, 0F, 0F).create()
}else{
divider = Y_DividerBuilder().setBottomSideLine(true, ContextCompat.getColor(context, R.color.black), 2F, 0F, 0F).create()
}
}
}
}
return divider!!
}
}
companion object{
// private val itemList = listOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "W", "X", "Y", "Z", "Z")
private val itemList = listOf("a", "b", "c", "d", "e")
}
}
上面這個(gè)效果的關(guān)鍵代碼都在Y_DividerItemDecoration類的getDivider方法中,這個(gè)jar包中,給提供了設(shè)置上下左右線的方法,使用起來(lái)并不復(fù)雜。
在看下圖效果:

這個(gè)效果實(shí)現(xiàn)的關(guān)鍵就是每行的列數(shù),有1列的,2列的,3列的,4列的幾種,看列數(shù)獲取的方法:
/**
* 這里的“12”總共的列數(shù),因?yàn)椴季至袛?shù)不定,有1,2,3,4幾種,這樣只有取得它們的公倍數(shù),才能使計(jì)算方便
*/
val layoutManager = GridLayoutManager(this, 12, GridLayoutManager.VERTICAL, false)//設(shè)置顯示方式
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup(){
override fun getSpanSize(position: Int): Int {
if (position == 0 || position == 1) {
return 6
} else if (position == 6 || position == 10) {
return 12
} else if (position in 7..9) {
return 4
} else if (position in 2..5) {
return 3
}
return 3
}
}
rv_content.layoutManager = layoutManager
getDivider方法的實(shí)現(xiàn):
class MyNewDividerItemDecoration(val context: Context): Y_DividerItemDecoration(context) {
override fun getDivider(itemPosition: Int): Y_Divider {
var divider: Y_Divider? = null
if (itemPosition in 1..6 || itemPosition == 9 || itemPosition == 10) {
divider = Y_DividerBuilder()
.setBottomSideLine(true, ContextCompat.getColor(context, R.color.colorAccent), 2f, 0f, 0f)
.create()
} else if (itemPosition == 0 || itemPosition == 7 || itemPosition == 8) {
divider = Y_DividerBuilder()
.setRightSideLine(true, ContextCompat.getColor(context, R.color.black), 2f, 0f, 0f)
.setBottomSideLine(true, ContextCompat.getColor(context, R.color.colorAccent), 2f, 0f, 0f)
.create()
} else if (itemPosition in 11..21) {
when ((itemPosition - 10) % 4) {
1, 2, 3 -> {
divider = Y_DividerBuilder()
.setRightSideLine(true, ContextCompat.getColor(context, R.color.black), 2f, 0f, 0f)
.setBottomSideLine(true, ContextCompat.getColor(context, R.color.colorAccent), 2f, 0f, 0f)
.create()
}
0 -> {
divider = Y_DividerBuilder()
.setBottomSideLine(true, ContextCompat.getColor(context, R.color.colorAccent), 2f, 0f, 0f)
.create()
}
else -> {
divider = Y_DividerBuilder().setBottomSideLine(true, ContextCompat.getColor(context, R.color.trans), 2F, 0F, 0F).create()
}
}
}
return divider!!
}
}
關(guān)于RecyclerView的分割線,下一篇寫RecyclerView的條目動(dòng)畫
參考文檔
1,[Android RecyclerView 使用完全解析 體驗(yàn)藝術(shù)般的控件]:http://blog.csdn.net/lmj623565791/article/details/45059587
2,間隔線第三方github地址:[Y_DividerItemDecoration]:https://github.com/yanyusong/Y_DividerItemDecoration