Android 通讯录(1)-----自定义ItemDecoration实现分类标题
来源:互联网 发布:如何制作淘宝首页模板 编辑:程序博客网 时间:2024/05/21 23:26
前言
RecyclerView 相信大家都不陌生,画分割线一般有两种思路:
- 在itemView的布局文件中留出空挡,或者干脆画条线。
- recyclerView.addItemDecoration() 添加。
其中第二种如果不自定义的话,只能加默认的线条,且只能在LinearLayoutManager中使用。
最终效果
当然了,这是最终效果,这篇文章我们只考虑左边的分类标题,右边的,我们下集更精彩。
写代码之前
自定义View,在写之前我们就需要确认自己需要实现的目标有哪些,比如:
- 标题栏高度
- 标题栏背景色
- 标题栏字体大小
这些是我这个demo中准备实现的。
ItemDecoration主要方法
新建一个类继承RecyclerView.ItemDecoration,需要实现的方法总共也就3个:
- getItemOffsets:可以理解为给RecyclerView中的item设置padding
- onDraw:就是自定view里那个常见的onDraw,画出想画的内容。
- onDrawOver:Over用的很精髓,其实跟onDraw差不多,也是画。只是在onDraw执行完成后才画,表现为所画内容在itemView的上层。
public class TitleItemDecoration extends RecyclerView.ItemDecoration { private Context mContext; private List<CityBean> mData; private Paint mPaint; private Rect mBounds; //标题栏背景色 private static int COLOR_TITLE_BG = Color.parseColor("#FFDFDFDF"); //标题栏字体颜色 private static int COLOR_TITLE_FONT = Color.parseColor("#FF000000"); private int titleSize; private int titleHeight; public TitleItemDecoration(Context mContext, List<CityBean> mData) { this.mContext = mContext; this.mData = mData; //预先设置标题栏高度 titleHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,30,mContext.getResources().getDisplayMetrics()); //预先设置标题栏字体大小 titleSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,mContext.getResources().getDisplayMetrics()); mPaint = new Paint(); //抗锯齿 mPaint.setAntiAlias(true); mBounds = new Rect(); } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); int position = ((RecyclerView.LayoutParams)view.getLayoutParams()).getViewAdapterPosition(); if(position>-1){ //在合适的位置 空出标题栏的高度 if(position == 0){ outRect.set(0,titleHeight,0,0); }else if(!mData.get(position).getTag().equals(mData.get(position - 1).getTag())){ outRect.set(0,titleHeight,0,0); } } } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); for (int i = 0;i<parent.getChildCount();i++){ View childView = parent.getChildAt(i); int position = ((RecyclerView.LayoutParams)childView.getLayoutParams()).getViewAdapterPosition(); if(position >-1){ if(position == 0){ drawTitle(c,left,right,childView,position); }else if(!mData.get(position).getTag().equals(mData.get(position - 1).getTag())){ drawTitle(c,left,right,childView,position); } } } } private void drawTitle(Canvas c, int left, int right, View childView, int position) { //画笔设置颜色为背景色 mPaint.setColor(COLOR_TITLE_BG); //画矩形 c.drawRect(left,childView.getTop() - titleHeight,right,childView.getTop(),mPaint); //画笔设置颜色为字体颜色 mPaint.setColor(COLOR_TITLE_FONT); //画笔设置字体大小 mPaint.setTextSize(titleSize); //获取容纳字的矩形框大小 mPaint.getTextBounds(mData.get(position).getTag(),0,mData.get(position).getTag().length(),mBounds); //画字 c.drawText(mData.get(position).getTag(),childView.getPaddingLeft() ,childView.getTop() - (titleHeight/2 - mBounds.height()/2),mPaint); } @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDrawOver(c, parent, state); boolean flag = false;//标志量:画布是否移动 int position = ((LinearLayoutManager)parent.getLayoutManager()).findFirstVisibleItemPosition(); View childView = parent.findViewHolderForLayoutPosition(position).itemView; if(position + 1 < mData.size() && mData.get(position).getTag()!=null && !mData.get(position).getTag().equals(mData.get(position + 1).getTag())){ //临界点 if(childView.getHeight() + childView.getTop() < titleHeight){ //保存画布状态 c.save(); flag = true; //画布移动 c.translate(0,childView.getHeight() + childView.getTop() - titleHeight); } } mPaint.setColor(COLOR_TITLE_BG); c.drawRect(parent.getPaddingLeft(),parent.getPaddingTop(),parent.getWidth() - parent.getPaddingRight(),parent.getPaddingTop() + titleHeight,mPaint); mPaint.setColor((COLOR_TITLE_FONT)); mPaint.getTextBounds(mData.get(position).getTag(),0,mData.get(position).getTag().length(),mBounds); c.drawText(mData.get(position).getTag(),childView.getPaddingLeft(),parent.getPaddingTop() + titleHeight - (titleHeight/2 - mBounds.height()/2),mPaint); if(flag) c.restore(); }}
14-25行:构造函数,还有自定义view的一些常规设置:预先设置好字体大小、颜色,或者自定义的一些属性值。
33-37行:在合适的位置,设置padding值,将分类标题所需要的预设高度给留出来。
72行:childView.getPaddingLeft()是为了控制方便,遵守itemView布局时的padding值。
83行:临界点可以自己画个图思考下。注意,第一个可见的item是顶部的分类标题遮住的那个。
85和97行 是一对儿:如果要想对整个画布进行操作,必须这样做,否则其他元素会出问题。
demo
点我下载
感兴趣的朋友可以继续阅读 Android 通讯录(2)—–自定义View实现右侧导航栏
阅读全文
1 0
- Android 通讯录(1)-----自定义ItemDecoration实现分类标题
- Android 自定义 View 实现通讯录字母索引(仿微信通讯录)
- Android 自定义 View 实现通讯录字母索引(仿微信通讯录)
- Android 自定义RecyclerView.ItemDecoration(GridLayoutManager布局下)
- Android 通讯录(2)-----自定义View实现右侧导航栏
- RecycleView自定义ItemDecoration,实现时间轴效果
- android ListView的类IOS通讯录效果,分类ListView,ListView标题置顶
- Android 自带ToolBar自定义中间标题&分类
- 使用ItemDecoration自定义RecyclerView的分割线实现头布局
- RecyclerView利用ItemDecoration实现头部悬停效果【类似微信通讯录效果】
- 自定义 RecyclerView.ItemDecoration
- recyclerView-自定义itemDecoration详解
- RecyclerView自定义ItemDecoration
- Python实现通讯录(1)
- android 通讯录的实现
- android 自定义view仿通讯录
- Android 自定义通讯录(仿Ios反弹效果+模糊搜索+查看手机通讯录+拉伸导航条)
- RecycleView-自定义分割线-ItemDecoration
- Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x000001DB1D7557
- 【MyBatis学习09】高级映射之一对多查询
- iOS编程学习六
- Python 数据科学手册 5.7 支持向量机
- Java 只运行一个实例
- Android 通讯录(1)-----自定义ItemDecoration实现分类标题
- python-skimage
- Jeddict目前的使用现状
- 【MyBatis学习10】高级映射之多对多查询
- 18th 【最短路 floyd】智捅马蜂窝
- jQuery-Validate验证插件的使用步骤详解
- 黑化的牛牛
- html笔记
- MySQL更新FROM从句中的字段 mysql [Err] 1093