Android自定义View(三)--可点击的节点进度条
来源:互联网 发布:最惨的动漫男主 知乎 编辑:程序博客网 时间:2024/06/06 09:13
需求
根据效果图,我们可以确定,用自定义View完全可以搞定,在自定义控件系列博客第一篇中,我们总结了自定义View的几个步骤:
继承View,覆盖构造方法自定义属性重写onMeasure方法测量宽高重写onDraw方法绘制控件
当然,你没有必要完全依照步骤去做,这个步骤是你对控件应该怎么写已经有了完整的思路和规划,这在实际情况下是不现实的,往往我们自定义控件都是做到哪里缺什么就做什么,首先我们应该将它画出来,有一个可视的供我们思考的视图。所以,这里我们将这个步骤灵活的变换一下,由于我们现在还不确定需要自定义哪些属性,以及需要怎样测量,所以我们把这两个步骤挪到后面。
重写onDraw绘制
首先我们分析一下这个控件里面有哪些元素,有一条直线,上面有n个选项,分布着n个圆,当选中哪一个后这上面的圆变为蓝色的,还有n项字,当选中后字变为蓝色。下面我们初步确定一下需要的常量和一些简单的计算:
1. 一些必要的数据:字体大小mTextSize,字体颜色mColorTextDef,线段和圆圈的颜色mColorDef,被选中后的颜色mColorSelected,直线的高度mLineHight,圆圈的直径mCircleHight,被选中后蓝色空心圆圈的宽度mCircleSelStroke,当前选中的序号selectedIndex2. 直线的长度float lineLength=整个控件的宽度-左边圆圈的半径 -右边圆圈的半径(为了让直线两端正好在两端圆圈的中心)3. 圆圈的分布间隔距离float splitLength = lineLength / (n-1);4. 字体与上面部分的间距mMarginTop private void initPaint(){ mLinePaint = new Paint(); mCirclePaint = new Paint(); mTextPaint = new Paint(); mCircleSelPaint = new Paint(); mTextSelPaint=new Paint(); mLinePaint.setColor(mColorDef); mLinePaint.setStyle(Paint.Style.FILL);//设置填充 mLinePaint.setStrokeWidth(mLineHight);//笔宽像素 mLinePaint.setAntiAlias(true);//锯齿不显示 mCirclePaint.setColor(mColorDef); mCirclePaint.setStyle(Paint.Style.FILL);//设置填充 mCirclePaint.setStrokeWidth(1);//笔宽像素 mCirclePaint.setAntiAlias(true);//锯齿不显示 mCircleSelPaint.setColor(mColorSelected); mCircleSelPaint.setStyle(Paint.Style.STROKE); //空心圆圈 mCircleSelPaint.setStrokeWidth(mCircleSelStroke); mCircleSelPaint.setAntiAlias(true); mTextPaint.setTextSize(mTextSize);//文本 画笔 mTextPaint.setColor(mColorTextDef); mLinePaint.setAntiAlias(true); mTextSelPaint.setTextSize(mTextSize);//选中后的文本画笔 mTextSelPaint.setColor(mColorSelected); mTextSelPaint.setAntiAlias(true);}/** * 测量文字的长宽 */private void measureText(){// mBounds = new ArrayList<>(); for(IDataBean name : textList){ Rect mBound = new Rect(); mTextPaint.getTextBounds(name.getTextName(), 0, name.getTextName().length(), mBound); mBounds.add(mBound); }}private void measureHeight(){//测量view的高度 if (mBounds!=null && mBounds.size()!=0) defaultHeight=mCircleHight + mMarginTop+mCircleSelStroke+mBounds.get(0).height()/2; else defaultHeight=mCircleHight + mMarginTop+mCircleSelStroke;}@Overrideprotected void onDraw(Canvas canvas) { if (textList==null || textList.size()==0) return; canvas.drawLine(mCircleHight/2,mCircleHight/2+mCircleSelStroke,getWidth()-mCircleHight/2,mCircleHight/2+mCircleSelStroke,mLinePaint); circleCount=textList.size();//画灰色园的个数 dividWidth=(getWidth()-mCircleHight)/(circleCount-1);//每个园相隔的距离 for (int i=0; i<=circleCount;i++) { if (i==selectIndex){ canvas.drawCircle(mCircleHight / 2 + i * dividWidth, mCircleHight / 2+mCircleSelStroke, mCircleHight / 2, mCircleSelPaint); }else { canvas.drawCircle(mCircleHight / 2 + i * dividWidth, mCircleHight / 2+mCircleSelStroke, mCircleHight / 2, mCirclePaint); } } for (int i=0; i<textList.size();i++){ int currentTextWidth=mBounds.get(i).width(); if (i==0){ if (i==selectIndex){ canvas.drawText(textList.get(i).getTextName(), 0, mCircleHight + mMarginTop+mCircleSelStroke+mBounds.get(i).height()/2, mTextSelPaint); }else { canvas.drawText(textList.get(i).getTextName(), 0, mCircleHight + mMarginTop+mCircleSelStroke+mBounds.get(i).height()/2, mTextPaint); } }else if (i==textList.size()-1){ if (i==selectIndex){ canvas.drawText(textList.get(i).getTextName(), getWidth() - currentTextWidth, mCircleHight + mMarginTop+mCircleSelStroke+mBounds.get(i).height()/2, mTextSelPaint); }else { canvas.drawText(textList.get(i).getTextName(), getWidth() - currentTextWidth, mCircleHight + mMarginTop+mCircleSelStroke+mBounds.get(i).height()/2, mTextPaint); } }else { if (i==selectIndex){ canvas.drawText(textList.get(i).getTextName(), mCircleHight / 2 + i * dividWidth - currentTextWidth / 2, mCircleHight + mMarginTop+mCircleSelStroke+mBounds.get(i).height()/2, mTextSelPaint); }else { canvas.drawText(textList.get(i).getTextName(), mCircleHight / 2 + i * dividWidth - currentTextWidth / 2, mCircleHight + mMarginTop+mCircleSelStroke+mBounds.get(i).height()/2, mTextPaint); } } }}
重写onTouchEvent
为了有点击选中的效果,我们必须要重写onTouchEvent,为了简单我们的实现方法如下:
@Override public boolean onTouchEvent(MotionEvent event) { float eventX; float eventY; int i = event.getAction(); if (i == MotionEvent.ACTION_DOWN) { Log.e("onTouchEvent", "ACTION_DOWN"); } else if (i == MotionEvent.ACTION_MOVE) { Log.e("onTouchEvent", "ACTION_MOVE"); } else if (i == MotionEvent.ACTION_UP) { Log.e("onTouchEvent", "ACTION_UP"); eventX = event.getX(); eventY = event.getY(); float select = eventX / dividWidth; //计算选中的index float xs = select - (int) (select); selectIndex = (int) select + (xs > 0.5 ? 1 : 0); } invalidate(); return true; }
重写onMeasure计算宽高
另外我们还需要在用户设置view的宽高为自适应时设置其宽高如下:
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); if(widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){//宽高都设置为wrap_content setMeasuredDimension(widthSpecSize,defaultHeight); }else if(widthSpecMode == MeasureSpec.AT_MOST){//宽设置为wrap_content setMeasuredDimension(widthSpecSize,heightSpecSize); }else if(heightSpecMode == MeasureSpec.AT_MOST){//高设置为wrap_content setMeasuredDimension(widthSpecSize, defaultHeight); }else{//宽高都设置为match_parenth或具体的dp值 setMeasuredDimension(widthSpecSize, heightSpecSize); }}
源码下载:
代码下载
http://download.csdn.net/download/hzmming2008/9980953
阅读全文
0 0
- Android自定义View(三)--可点击的节点进度条
- Android 自定义View 点击可旋转的饼状图
- Android自定义View之三种流行进度条的写法
- Android自定义View之可随时暂停、开启的圆形下载进度条
- android 自定义View(三) 自定义ViewGroup之可添加的view
- 自定义View(三)-圆形进度条-百分比进度条
- 自定义View——可打点记录的进度条
- 【Android自定义View】美观个性的进度条
- view 自定义标题+点击才开始的进度条+使用二维码
- Android -自定义view(三)自定义view的流程
- 自定义view (三) 用view圆环进度条
- Android自定义View动画(进度条)
- Android 自定义view --圆形百分比(进度条)
- Android 自定义view --圆形百分比(进度条)
- android 自定义 View(4)- 进度条(ProgressBar)
- 自定义View---圆形进度条&&点击改变颜色
- Android 简单实现可全屏拖动,可点击的View
- Android自定义可拖动进度条
- 使用当前类加载器查找文件
- 有数量不限的硬币,币值为25分、10分、5分和1分,请编写代码计算n分有几种表示法
- JavaScript- 使用 atan2 来绘制 箭头 和 曲线
- 函数的 length 属性只能得到他的形参个数,而无法得知实参个数。
- tslib移植出现的小问题
- Android自定义View(三)--可点击的节点进度条
- 如何掌握所有的程序语言
- Mybatis 输入映射和输出映射
- IPU相关知识(二)
- QT界面设计并保存到文件(以JSON格式)
- [日推荐]『初次见』这里有故事,还有诗和远方!
- spring中的拦截器
- zabbix3.4 监控tomcat多实例(二)
- 没有通过申硕考试怎么办?