自定义ArcView-构造拓展性高的view
来源:互联网 发布:淘宝处方药购买步骤 编辑:程序博客网 时间:2024/05/03 05:14
这段时间用做一个飞行统计的模块,其中要做一个弧形展示效果,如图
做这个东西时,我们首先想到的是有没有现成的。于是就去github上找,找到了这个--https://github.com/lzyzsd/CircleProgress,大家有兴趣也可以去研究研究。本文参考的是其中的ArcProgress。其原理就是画弧和画字。。原理图:
先说画弧:
关键代码为:canvas.drawArc(rectF, startAngle, entityAngle, false, paint);
其中rectF为最外面的矩阵,startAngle为绘弧的开始角度,entityAngle为要画弧的最大值,false为不包含圆心,paint为画笔。
其次画字:
float bottomTextBaseline = getMeasuredHeight() - textPaint.descent();底部文字的基线
canvas.drawText(bottomText, (getMeasuredWidth() - textPaint.measureText(bottomText)) / 2.0f, bottomTextBaseline, textPaint);
canvas.drawText(bottomText, (getMeasuredWidth() - textPaint.measureText(bottomText)) / 2.0f, bottomTextBaseline, textPaint);
第一个参数为要画的文字,第二个参数为画字的起始x坐标,第三个为y坐标,第四个参数为文字画笔。
画字时的规则:参考http://blog.csdn.net/tianjf0514/article/details/7642656
接下来开始自定义我们的ArcView了,首先自定义属性,这个没什么可说的:
public ArcView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.Arc); this.radius = ta.getDimensionPixelSize(R.styleable.Arc_radius,0); this.entityAngle = ta.getInt(R.styleable.Arc_entity_angle, DEFAULT_ENTITY_ANGLE); this.initPercent = ta.getInt(R.styleable.Arc_init_percent,0); //初始的百分值 init(context); }
关键是测量我们的view的大小。一般来说,我们画的东西要在这个view可见范围内的中心。在onMeasure()方法中要计算出rectF(弧形的矩阵)。
上代码:
<pre name="code" class="java">protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Log.e("arcView","onMeasure"); //整个内容的宽度 int contentWidth = (int) (radius * 2 + out_stroke_width); //下面计算内容的高度 float halfTemp = out_stroke_width / 2; float angle = (360 - entityAngle) / 2f; arcBottom2CenterHeight = (float) (radius * Math.cos(angle / 180 * Math.PI)); int contentHeight = (int) (radius + arcBottom2CenterHeight + textPaint.descent() + out_stroke_width); setMeasuredDimension(resolveSize(contentWidth,widthMeasureSpec),resolveSize(contentHeight,heightMeasureSpec)); float contentLeft,contentTop,contentRight,contentBottom; //矩阵的左右上底 if(getMeasuredWidth() == contentWidth){ contentLeft = halfTemp; contentRight = contentWidth - halfTemp; }else{ contentLeft = (getMeasuredWidth() - contentWidth) / 2 + halfTemp; contentRight = contentLeft + contentWidth - 2 * halfTemp; } if(getMeasuredHeight() == contentHeight){ contentTop = halfTemp; contentBottom = contentWidth - halfTemp; }else{ contentTop = (getMeasuredHeight() - contentHeight) / 2 + halfTemp; contentBottom = contentTop + contentWidth - 2 * halfTemp; } rectF = new RectF(contentLeft,contentTop,contentRight,contentBottom); }
接下来是ondraw方法:
protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.e("arcView","draw"); //锁屏解锁后会再次调用ondraw()方法 canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG)); paint.setStrokeWidth(default_stroke_width); paint.setColor(unfinishedStrokeColor); canvas.drawArc(rectF, startAngle, entityAngle, false, paint); paint.setStrokeWidth(out_stroke_width); paint.setColor(finishedStrokeColor); canvas.drawArc(rectF, startAngle, initSweepAngle, false, paint); //画下面文字 textPaint.setTextSize(default_gray_text_size); textPaint.setColor(default_gray_text_color); float bottomTextBaseline = getMeasuredHeight() - textPaint.descent(); canvas.drawText(bottomText, (getMeasuredWidth() - textPaint.measureText(bottomText)) / 2.0f, bottomTextBaseline, textPaint); //画上面文字 float topTextBaseline = radius / 2 + out_stroke_width / 2; canvas.drawText(topText,(getMeasuredWidth() - textPaint.measureText(topText)) / 2.0f,topTextBaseline,textPaint); //画中心文字 textPaint.setTextSize(default_percent_text_size); textPaint.setColor(default_percent_text_color); float centerTextBaseline = getMeasuredHeight() / 2 - textPaint.ascent() / 2; canvas.drawText(centerText,(getMeasuredWidth() - textPaint.measureText(centerText)) / 2.0f,centerTextBaseline,textPaint); }
手机锁屏后再亮屏,view的ondraw方法会调用,从下一个activity返回也会调用,结果是view可见是会调用ondraw()方法。
最后重写onSaveInstanceState和onRestoreInstanceState来保存和恢复数据
protected Parcelable onSaveInstanceState() { Log.e("arcView","onSaveInstanceState"); Bundle bundle = new Bundle(); bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState()); bundle.putFloat(INSTANCE_PROGRESS, initSweepAngle); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { Log.e("arcView","onRestoreInstanceState"); if(state instanceof Bundle) { Bundle bundle = (Bundle) state; initSweepAngle = bundle.getFloat(INSTANCE_PROGRESS,0); super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE)); return; } super.onRestoreInstanceState(state); }
我们有可能显示百分数时需要一个animate过程,上代码:
/*第一中方式实现animatePercent private OverScroller scroller; public void animatePercent(int percent){ if(scroller.isFinished()) { scroller.startScroll(0, 0, percent, 0, 2000);// scroller.fling(0,0,500,0,0,100,0,0); invalidate(); } } @Override public void computeScroll() { if(scroller.computeScrollOffset()){ int tempPercent = scroller.getCurrX(); setPercent(tempPercent); } super.computeScroll(); } */ private final int ANIMATE_DURATION = 1000; private static final int SIXTY_FPS_INTERVAL = 1000 / 60; private long mStartTime; static final android.view.animation.Interpolator sInterpolator = new OvershootInterpolator(); public void animatePercent(final int percent){ mStartTime = System.currentTimeMillis(); this.post(new Runnable() { @Override public void run() { float t = interpolate(); float currentPercent = 0 + t * percent; setPercent(currentPercent); if(t < 1){ ArcView.this.postDelayed(this,SIXTY_FPS_INTERVAL); } } }); } private float interpolate() { float t = 1f * (System.currentTimeMillis() - mStartTime) / ANIMATE_DURATION; t = Math.min(1f,t); return sInterpolator.getInterpolation(t); }第一种方式在结束时有点卡顿的现象,不知道你们的手机有没有。我推荐第二种,当然了,我们也可以用属性动画来实现。
最后是效果图
源码:
http://yunpan.cn/cdgSG2ii4CzKh (提取码:560b)
0 0
- 自定义ArcView-构造拓展性高的view
- Android高拓展性,更加方便的自定义Dialog.
- 自定义View的构造函数
- 自定义View的构造方法
- 自定义view的构造方法
- Android之---自定义view显示一张高清的原图(不压缩,支持拖动,可拓展至缩放手势)
- 自定义View 拓展view 没有全部实现夫view中的构造方法 ApplicationContext is null in ApplicationStatus
- 自定义View构造方法的推荐写法
- 自定义View的三个构造方法
- 关于自定义View的四个构造方法
- 自定义View时,构造参数的调用
- 自定义view构造方法
- 保持宽高比的自定义View
- 浅谈自定义View的宽高获取
- 浅谈自定义View的宽高获取
- 浅谈自定义View的宽高获取
- 自定义view设置默认的宽高
- 自定义View的宽高获取
- Java分层架构
- LINUX 串口编程
- JS获取单选框选中的值
- hdoj 2037 今年暑假不AC
- 自定义ActionBar的两种方式(静态&动态)
- 自定义ArcView-构造拓展性高的view
- kindeditor在dialog弹出框,无法编辑,不能获取焦点
- Web Service 的工作原理
- iOS学习开发2:UIView和UIWindow
- Linux 内存使用方法详细解析
- leetcode: 4Sum
- 外部引用校验JS
- 体验引擎游戏设计全景探秘——互动出版网
- spring mvc @Autowired