内容简介:想到分割线,原先一直是在item的布局中直接加入,在adapter中进行判断,若是最后一个子项则将分割线隐藏,感觉太小儿科了,今天来好好研究这个ItemDecoration的使用。文章参考自通过
想到分割线,原先一直是在item的布局中直接加入,在adapter中进行判断,若是最后一个子项则将分割线隐藏,感觉太小儿科了,今天来好好研究这个ItemDecoration的使用。
文章参考自 RecyclerView 之 ItemDecoration 讲解及高级特性实践 ,写的很详细,仔细看后就会用了,我只是在此基础上增添了可以更改颜色、宽度、左右偏移的功能。废话不多说,咱们开始做吧。
简单的添加分割线:
一、建立工程,创建Adapter,加载布局文件
public class MainActivity extends AppCompatActivity { @BindView(R.id.recyclerview) RecyclerView recyclerview; private List<String> dataList; //数据项 private MyAdapter myAdapter; //适配器 @Override protected void onCreate(Bundle savedInstanceState) { ... initData(); myAdapter = new MyAdapter(R.layout.item_recyclerview,dataList); recyclerview.setAdapter(myAdapter); LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); recyclerview.setLayoutManager(layoutManager); } private void initData(){ dataList = new ArrayList<>(); for(int i = 0;i<20;i++){ dataList.add("子项"+i); } } } 复制代码
public class MyAdapter extends BaseQuickAdapter<String, BaseViewHolder> { public MyAdapter(int layoutResId, List<String> data) { super(layoutResId, data); } @Override protected void convert(BaseViewHolder helper, String item) { helper.setText(R.id.tv_content, item); } } 复制代码
二、建立分割器
提前说明,以下内容均是在每个ItemView的顶部加入分割线,第一个不加
通过 recyclerview.addItemDecoration(new SimpleItemDecoration());
将以下分割器加入到RecyclerView中即可
public class SimpleItemDecoration extends RecyclerView.ItemDecoration { /** * @param outRect 全为0的rect,用来指定偏移区域 * @param view 指RecyclerView中的Item * @param parent 指RecyclerView本身 * @param state 状态 */ @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); if (parent.getChildAdapterPosition(view) != 0) { //直接设置为1px outRect.top = 1; } } } 复制代码
加入后的效果:
自定义颜色偏移宽度的分割器
以上方法,通过使每个ItemView向上撑出1px距离,而RecyclerView背景为灰色,这样就显示出1px的灰色线,实现分割线功能,看到这你可能会想,这也太粗糙了,如果我想要改变分割线的宽度、颜色该怎么办,总不能每写一个RecyclerView都再写一套分割器,更改RecyclerView背景颜色吧,而且一般分割线并不占满全部宽度,有左右偏移,那该怎么实现呢?
别急,我们先了解下getItemOffsets()方法中的outRect这个参数。
其中的蓝色部分为我们的RecyclerView的子项ItemView,外部黄色部分为outRect,只是黄色,并不包含ItemView压的那部分, left,right,top,bottom四个参数其实就是距离itemView的四个方向的偏移量,是指偏移 ItemView 各个方向的数值 ,在上面的例子中,我们设置了 outRect.top=1
,所以每个ItemView之间有1px的空隙,所以呈现出1px灰色的分割线,分割线颜色决定于RecyclerView的背景色。
一、设置高度:
既然知道了这四个参数代表相对itemview的偏移,那么分割线的高度就好办了。
如图,想要红色那样高度的分割线,只需要outRect.top等于该高度就可以了。我们将该高度定义为 mDividerHeight
二、设置颜色、左右偏移:
高度有了,如果我们只想绘制红色那部分矩形而不是ItemView上方的全部该怎么办?我们知道每一个View中的onDraw()方法是用来绘制组件的UI效果,所以想要颜色的话,需要我们重写ItemDecoration中的onDraw()方法。
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state); 复制代码
可以看到onDraw()方法中有参数Canvas,通过它来绘制红色矩形,所以我们需要知道该矩形的四条边的位置。
float dividerTop = view.getTop() - mDividerHeight; //矩形顶部 float dividerBottom = view.getTop(); //矩形底部 float dividerLeft = parent.getPaddingLeft() + margin; //矩形左侧 float dividerRight = parent.getWidth() - parent.getPaddingRight() - margin; //矩形右侧 复制代码
矩形顶部=itemview的顶部加上分割线的高度,咦?我怎么写的减号?看下图你应该就会明白
安卓中坐标是这样的,向下向右为正,所以红色矩形顶部位置就应该是itemView的top位置-矩形高度
偏移的话左侧加上偏移量,右侧减去偏移量即可。
c.drawRect(dividerLeft, dividerTop, dividerRight, dividerBottom, mPaint); 复制代码
这样我们要绘制的矩形就出来了,等等,我们只是画了个矩形,还没颜色呢,再来看看drawRect()中的参数,我们还缺一个mPaint画笔,通过它来设置矩形分割线颜色。
public MyDecoration() { mPaint = new Paint(); mPaint.setAntiAlias(true); //抗锯齿 mPaint.setColor(Color.GRAY); //默认灰色 } 复制代码
通过以上步骤,带有颜色和偏移量,且具有一定高度的分割线就画好了,其实还没完, 需要注意:getItemOffsets 是针对每一个 ItemView,而 onDraw 方法却是针对 RecyclerView 本身,所以在 onDraw 方法中需要遍历屏幕上可见的 ItemView,分别获取它们的位置信息,然后分别的绘制对应的分割线。
代码如下:
@Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); int childCount = parent.getChildCount(); //可见ItemView个数 //因为getItemOffsets是针对每一个ItemView,而onDraw方法是针对RecyclerView本身,所以需要循环遍历来设置 for (int i = 0; i < childCount; i++) { View view = parent.getChildAt(i); int index = parent.getChildAdapterPosition(view); //第一个ItemView不需要绘制 if (index == 0) { continue;//跳过本次循环体中尚未执行的语句,立即进行下一次的循环条件判断 } float dividerTop = view.getTop() - mDividerHeight; //矩形顶部 float dividerLeft = parent.getPaddingLeft() + margin; //矩形左侧 float dividerBottom = view.getTop(); //矩形底部 float dividerRight = parent.getWidth() - parent.getPaddingRight() - margin;//矩形右侧 c.drawRect(dividerLeft, dividerTop, dividerRight, dividerBottom, mPaint); } } 复制代码
在实际运用中,我们的分割线颜色高度等样式可能不一样,这里我们通过建造者模式来设置这些属性
//设置左右偏移(默认是设置的一样的,若需要自己更改) public MyDecoration setMargin(float margin) { this.margin = margin; return this; } //设置颜色 public MyDecoration setColor(int color) { mPaint.setColor(color); return this; } //设置分割线高度 public MyDecoration setDividerHeight(float height) { this.mDividerHeight = height; return this; } 复制代码
这样我们就完成了分割线的自定义
完整代码如下:
public class MyDecoration extends RecyclerView.ItemDecoration { private float mDividerHeight = 1; //线的高度 private Paint mPaint; //画笔将自己做出来的分割线矩形画出颜色 private float margin = 0; //左右偏移量 public MyDecoration() { mPaint = new Paint(); mPaint.setAntiAlias(true); //抗锯齿 mPaint.setColor(Color.GRAY); //默认颜色 } //通过建造者模式来设置三个属性 //设置左右偏移(默认是设置的一样的,若需要自己更改) public MyDecoration setMargin(float margin) { this.margin = margin; return this; } //设置颜色 public MyDecoration setColor(int color) { mPaint.setColor(color); return this; } //设置分割线高度 public MyDecoration setDividerHeight(float height) { this.mDividerHeight = height; return this; } //在这里就已经把宽度的偏移给做好了 @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); //第一个ItemView不需要在上面绘制分割线 if (parent.getChildAdapterPosition(view) != 0) { outRect.top = (int) mDividerHeight;//指相对itemView顶部的偏移量 } } //这里主要是绘制颜色的 @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); int childCount = parent.getChildCount(); //因为getItemOffsets是针对每一个ItemView,而onDraw方法是针对RecyclerView本身,所以需要循环遍历来设置 for (int i = 0; i < childCount; i++) { View view = parent.getChildAt(i); int index = parent.getChildAdapterPosition(view); //第一个ItemView不需要绘制 if (index == 0) { continue;//跳过本次循环体中尚未执行的语句,立即进行下一次的循环条件判断 } float dividerTop = view.getTop() - mDividerHeight; float dividerLeft = parent.getPaddingLeft() + margin; float dividerBottom = view.getTop(); float dividerRight = parent.getWidth() - parent.getPaddingRight() - margin; c.drawRect(dividerLeft, dividerTop, dividerRight, dividerBottom, mPaint); } } } 复制代码
使用:
MyDecoration myDecoration = new MyDecoration(); myDecoration.setColor(ContextCompat.getColor(getContext(),R.color.line_gray)).setMargin(ConvertUtils.dp2px(getContext(), 15)).setDividerHeight(ConvertUtils.dp2px(getContext(),1)); recyclerView.addItemDecoration(myDecoration); 复制代码
实际使用中我们是dp单位,所以这里我使用了ConvertUtils工具类,将dp转为px
代码如下:
public static int dp2px(Context context, final float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } 复制代码
看下效果:
到这里我们想要的功能就全部完成了。(终于码完了开心!)
如果我们的RecyclerView是横向的滑动,原理类似,剩下的就交给你们了(懒得写了嘿嘿)
以上所述就是小编给大家介绍的《自定义ItemDecoration分割线的高度、颜色、偏移,看完这个你就懂了》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 地表最强 RecyclerView 分割线 Y_DividerItemDecoration 2.0
- [iOS开发]UITableView的分割线设置及不能全屏原因
- 记一次Access偏移注入
- ios – reloadRowsAtIndexPaths时保持偏移量
- Kafka 消息偏移量的维护
- Spark Streaming 之 Kafka 偏移量管理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。