自定义控件之动态进度View
来源:互联网 发布:骚男的衣服淘宝店 编辑:程序博客网 时间:2024/06/08 03:21
效果
首先看一下效果
实现思路
仔细看这个效果,将整个过程一个一个的分解:
分解 1.画一个箭头 2.箭头渐变 3.弹出圆球 4.画圆弧 5.画勾每个过程通过一个进度百分比来记录进度,然后就是按顺序一个个的画出来
public class LoadingView extends View { // 开始绘制的标志 private boolean mCanDraw = true; private boolean mIsStart = true; private int mDrawUpLinePercent; private int mDrawOnLinePercent; private int mOutPointPercent; private int mDrawGouPercent; private int mWidth = 0; private int mheight = 0; // 圆心半径 private float mCircleX = 0; private float mCircleY = 0; private float mRedius = 80; private int mOuterCircleStrokeWidth = 10; private Paint mPaint; private RectF mRectF; public LoadingView(Context context) { this(context, null); } public LoadingView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStrokeWidth(mOuterCircleStrokeWidth); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.parseColor("#44FFFFFF")); } @Override protected void onDraw(Canvas canvas) { // 获取圆心 mCircleX = mWidth / 2; mCircleY = mheight / 2; // 这个path一定只能在这里初始化 Path path = new Path(); mRectF = new RectF(mCircleX - mRedius, mCircleY - mRedius, mCircleX + mRedius, mCircleY + mRedius); // 绘制外圆 mPaint.setColor(Color.parseColor("#44FFFFFF")); canvas.drawCircle(mCircleX, mCircleX, mRedius, mPaint); if (mCanDraw) { mIsStart = true; mPaint.setColor(Color.WHITE); if (mDrawUpLinePercent < 95) { // 绘制竖线 float temp = (mCircleY / 4) * mDrawUpLinePercent / 100; canvas.drawLine(mCircleX, mCircleY * 3 / 4 + temp, mCircleX, mCircleY * 5 / 4 - temp, mPaint); // 竖线变化的时候 箭头一直存在 path.moveTo(mCircleX * 3 / 4, mCircleY); path.lineTo(mCircleX, mCircleY * 5 / 4); path.lineTo(mCircleX * 5 / 4, mCircleY); canvas.drawPath(path, mPaint); mDrawUpLinePercent += 5; } else { // path变成直线 if (mDrawOnLinePercent < 100) { // 箭头变形 path.moveTo(mCircleX * 3 / 4, mCircleY); float temp = (mCircleY / 4) * mDrawOnLinePercent / 100; path.lineTo(mCircleX, mCircleY * 5 / 4 - temp); path.lineTo(mCircleX * 5 / 4, mCircleY); canvas.drawPath(path, mPaint); mDrawOnLinePercent += 5; // 圆心一直存在 canvas.drawCircle(mCircleX, mCircleY, 2.5f, mPaint); } else { // 将点弹出圆外 if (mOutPointPercent < 100) { float temp = mRedius * mOutPointPercent / 100; canvas.drawCircle(mCircleX, mCircleY - temp, 2.5f, mPaint); mOutPointPercent += 5; //弹出圆外的过程中,直线是一直存在的 canvas.drawLine(mCircleX * 3 / 4, mCircleY, mCircleX * 5 / 4, mCircleY, mPaint); mOutPointPercent += 5; } else { if (mDrawGouPercent < 100) { // 同时画勾 path.moveTo(mCircleX * 3 / 4, mCircleY); float t = (mCircleY / 4) * mDrawGouPercent / 100; path.lineTo(mCircleX, mCircleY + t); path.lineTo(mCircleX * 5 / 4, mCircleY); canvas.drawPath(path, mPaint); // 画圆弧 mPaint.setStrokeWidth(mOuterCircleStrokeWidth); float temp = (mDrawGouPercent / 100f) * 360; canvas.drawArc(mRectF, 270, -temp, false, mPaint); mDrawGouPercent += 5; } else { // 绘制最终的圆 mPaint.setColor(Color.WHITE); canvas.drawCircle(mCircleX, mCircleY, mRedius, mPaint); // 绘制最终的勾 path.moveTo(mCircleX * 3 / 4, mCircleY); path.lineTo(mCircleX, mCircleY * 5 / 4); path.lineTo(mCircleX * 5 / 4, mCircleY * 4 / 5); canvas.drawPath(path, mPaint); // 绘制完成 mCanDraw = false; } } } } } else { // 绘制最终的圆 mPaint.setColor(Color.WHITE); canvas.drawCircle(mCircleX, mCircleY, mRedius, mPaint); // 绘制最终的勾 path.moveTo(mCircleX * 3 / 4, mCircleY); path.lineTo(mCircleX, mCircleY * 5 / 4); path.lineTo(mCircleX * 5 / 4, mCircleY * 4 / 5); canvas.drawPath(path, mPaint); mIsStart = false; // 绘制静态箭头// canvas.drawLine(mCircleX, mCircleY * 3 / 4,// mCircleX, mCircleY * 5 / 4, mPaint);//// path.moveTo(mCircleX * 3 / 4, mCircleY);// path.lineTo(mCircleX, mCircleY * 5 / 4);// path.lineTo(mCircleX * 5 / 4, mCircleY);// canvas.drawPath(path, mPaint); } if (mIsStart) { postInvalidateDelayed(30); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { mWidth = width; } else { mWidth = 400; } if (heightMode == MeasureSpec.EXACTLY) { mheight = height; } else { mheight = 400; } // 设置自己的真实大小 setMeasuredDimension(width, height); }}
踩的坑
这个view我自己调了一下午才调出来,还几次都想放弃,最后还是坚持下来了,给自己点个赞!下面说说我遇到的问题吧:
1.坐标计算不熟悉,花费了很多时间,动手比较少2.这个进度onDraw每次触发的时候,我们希望重新绘制下个画面,然而我在画直线的时候将new Path()放在了全局,相当于每次对这个path对象操作,导致每次onDraw画的直线都在,花了好久才找到原因!3.Paint的一些属性改变之后需要重新设置.
0 0
- 自定义控件之动态进度View
- Android自定义View系列之进度指示控件
- Android自定义控件 多样式进度View
- Android自定义view之图片加载进度
- 自定义View之带进度百分比ProgressBar
- 自定义View之线性进度展示
- Android 自定义View实例之进度圆环
- 自定义圆形进度View
- 自定义view 进度圈
- 自定义view,进度圆
- 自定义审核进度View
- 自定义控件之 继承 View
- 自定义View之组合控件
- 自定义View之组合控件
- 自定义View之组合控件
- 自定义view之继承控件
- 自定义View之捆绑控件
- 自定义View之组合控件
- Android高级索引以及搜索使用场景
- 【模拟】Codeforces 704A & 705C Thor
- 左值与右值的区别
- ArrayList、Vector、HashMap、HashSet的默认初始容量、加载因子、扩容增量
- codeforces 368(div 2)前三题
- 自定义控件之动态进度View
- Java集合---HashSet的源码分析
- TortoiseGit密钥设置
- DOM节点
- 单点登录SSO学习小结
- 默认readline切换为vi
- L3-008. 喊山-PAT团体程序设计天梯赛GPLT(广度优先搜索)
- Windows窗口消息循环中TranslateAcclerator的理解
- python 列表处理,for循环语句,if条件判断