Android仪表盘实现自动增长的动画
来源:互联网 发布:中文域名申请 编辑:程序博客网 时间:2024/05/20 18:19
先看一下效果图
随着时间的变化,圆弧增长的同时,圆弧顶点的圆球也跟着增长.
上代码,注释很详细:
自定义view类
public class CircleProgressView extends View { /** * 直径 */ private int mDiameter; /** * 绘制时控制绘制的范围 */ private Paint mPaint; private float progressValue = 0; RectF rect; public CircleProgressView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleProgressView(Context context) { this(context, null); } /** * 获得自定义的样式属性 * * @param context * @param attrs * @param defStyle */ public CircleProgressView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CircleProgressView, defStyle, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.CircleProgressView_diameter: // 默认设置为40dp mDiameter = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 40, getResources().getDisplayMetrics())); break; } } a.recycle(); mPaint = new Paint(); rect = new RectF(); progressValue = 0; } public void setProgressValue(float progressValue) { this.progressValue = progressValue; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = 0; int height = 0; //设置直径的最小值 if (mDiameter <= 40) { mDiameter = 40; } height = mDiameter; width = mDiameter; setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int mWidth = getMeasuredWidth();//得到测量宽度 int mHeight = getMeasuredHeight();//得到测量高度 /************************************绘制圆弧***********************************/ float section = progressValue / 100;//progressValue是传进来的值,由定时器不停地发送过来 mPaint.setAntiAlias(true);//消除锯齿 mPaint.setStrokeWidth((float) 11);//画笔宽度 mPaint.setStyle(Style.STROKE);//描边 mPaint.setStrokeCap(Cap.ROUND);//ROUND,表示是圆角的笔触 rect.set(20, 20, mWidth - 20, mHeight - 20);//矩形区域,用来限制绘制的圆弧范围 mPaint.setColor(Color.BLACK); /* 颜色线性渐变 LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,Shader.TileMode tile) float x0: 渐变起始点x坐标 float y0:渐变起始点y坐标 float x1:渐变结束点x坐标 float y1:渐变结束点y坐标 int color0: 起始渐变色 int color1: 结束渐变色 Shader.TileMode tile: CLAMP边缘拉伸 */ LinearGradient shader = new LinearGradient(3, 3, mWidth - 3, mHeight - 3, Color.parseColor("#4299ff"), Color.parseColor("#3cedff"), Shader.TileMode.CLAMP); mPaint.setShader(shader); //画弧,第一个参数是RectF,第二个参数是角度的开始,第三个参数是旋转多少度,第四个参数是true的时候画扇形,是false的时候画弧线 canvas.drawArc(rect, 90, section * 360, false, mPaint); /************************************绘制小圆球***********************************/ mPaint.setStyle(Style.FILL);//填充 mPaint.setColor(Color.BLUE); float radius = rect.height() / 2;//半径 //获取圆弧的圆心坐标 PointF mCenterPoint = new PointF(rect.centerX(), rect.centerY()); PointF mRunCirclePoint = new PointF();//小圆球的圆心坐标 float a = section * 360 + 90;//小球圆心和圆弧圆心连线与x轴的夹角(顺时针旋转) if (a >= 90 && a < 180) { mRunCirclePoint.x = mCenterPoint.x - radius * (float) Math.sin((a - 90) * (2 * Math.PI / 360)); mRunCirclePoint.y = mCenterPoint.y + radius * (float) Math.cos((a - 90) * (2 * Math.PI / 360)); Log.i("CircleProgressView", "第三象限: x=" + mRunCirclePoint.x + ",y=" + mRunCirclePoint.y); } if (a >= 180 && a < 270) { mRunCirclePoint.x = mCenterPoint.x - radius * (float) Math.cos((a - 180) * (2 * Math.PI / 360)); mRunCirclePoint.y = mCenterPoint.y - radius * (float) Math.sin((a - 180) * (2 * Math.PI / 360)); Log.i("CircleProgressView", "第四象限: x=" + mRunCirclePoint.x + ",y=" + mRunCirclePoint.y); } if (a >= 270 && a < 360) { mRunCirclePoint.x = mCenterPoint.x + radius * (float) Math.sin((a - 270) * (2 * Math.PI / 360)); mRunCirclePoint.y = mCenterPoint.y - radius * (float) Math.cos((a - 270) * (2 * Math.PI / 360)); Log.i("CircleProgressView", "第一象限: x=" + mRunCirclePoint.x + ",y=" + mRunCirclePoint.y); } if (a >= 360 && a <= 450) { mRunCirclePoint.x = mCenterPoint.x + radius * (float) Math.cos((a - 360) * (2 * Math.PI / 360)); mRunCirclePoint.y = mCenterPoint.y + radius * (float) Math.sin((a - 360) * (2 * Math.PI / 360)); Log.i("CircleProgressView", "第二象限: x=" + mRunCirclePoint.x + ",y=" + mRunCirclePoint.y); } //绘制圆球,参数一是中心点的x轴,参数二是中心点的y轴,参数三是半径,参数四是paint对象 canvas.drawCircle(mRunCirclePoint.x, mRunCirclePoint.y, 10, mPaint); }}
在布局XML文件中的使用方式:
<com.lhy.view.CircleProgressView android:id="@+id/circle_progress_view4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" custom:diameter="180px" />
在资源文件values文件夹下的新增attr.xml添加如下代码:
<attr name="diameter" format="dimension" /> <declare-styleable name="CircleProgressView"> <attr name="diameter" /> </declare-styleable>
调用方式(主要代码):
private CircleProgressView circleProgressView4;circleProgressView4 = (CircleProgressView) findViewById(R.id.circle_progress_view4);// progressValue4 即为不断传入的值,从0开始,不断的自增长,直到和h(目标值)相等. private Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { if (msg.what == 4) { //空气湿度 circleProgressView4.setProgressValue(progressValue4);//设置传入的值 circleProgressView4.postInvalidate(); progressValue4 += 0.1; if (progressValue4 > h) {// h 即为目标值(空气湿度) task4.cancel(); } } } return false; });
TimerTask task4 = new TimerTask() { @Override public void run() { Message message = Message.obtain(); message.what = 4; handler.sendMessage(message); } };
Timer timer = new Timer();timer.schedule(task4, 1000, 10);
好了,代码已经贴完,下面继续上图(自己理解的小球运动轨迹公式):
对应的代码如下:
/************************************绘制小圆球***********************************/ mPaint.setStyle(Style.FILL);//填充 mPaint.setColor(Color.BLUE); float radius = rect.height() / 2;//半径 //获取圆弧的圆心坐标 PointF mCenterPoint = new PointF(rect.centerX(), rect.centerY()); PointF mRunCirclePoint = new PointF();//小圆球的圆心坐标 float a = section * 360 + 90;//小球圆心和圆弧圆心连线与x轴的夹角(顺时针旋转) if (a >= 90 && a < 180) { mRunCirclePoint.x = mCenterPoint.x - radius * (float) Math.sin((a - 90) * (2 * Math.PI / 360)); mRunCirclePoint.y = mCenterPoint.y + radius * (float) Math.cos((a - 90) * (2 * Math.PI / 360)); Log.i("CircleProgressView", "第三象限: x=" + mRunCirclePoint.x + ",y=" + mRunCirclePoint.y); } if (a >= 180 && a < 270) { mRunCirclePoint.x = mCenterPoint.x - radius * (float) Math.cos((a - 180) * (2 * Math.PI / 360)); mRunCirclePoint.y = mCenterPoint.y - radius * (float) Math.sin((a - 180) * (2 * Math.PI / 360)); Log.i("CircleProgressView", "第四象限: x=" + mRunCirclePoint.x + ",y=" + mRunCirclePoint.y); } if (a >= 270 && a < 360) { mRunCirclePoint.x = mCenterPoint.x + radius * (float) Math.sin((a - 270) * (2 * Math.PI / 360)); mRunCirclePoint.y = mCenterPoint.y - radius * (float) Math.cos((a - 270) * (2 * Math.PI / 360)); Log.i("CircleProgressView", "第一象限: x=" + mRunCirclePoint.x + ",y=" + mRunCirclePoint.y); } if (a >= 360 && a <= 450) { mRunCirclePoint.x = mCenterPoint.x + radius * (float) Math.cos((a - 360) * (2 * Math.PI / 360)); mRunCirclePoint.y = mCenterPoint.y + radius * (float) Math.sin((a - 360) * (2 * Math.PI / 360)); Log.i("CircleProgressView", "第二象限: x=" + mRunCirclePoint.x + ",y=" + mRunCirclePoint.y); } //绘制圆球,参数一是中心点的x轴,参数二是中心点的y轴,参数三是半径,参数四是paint对象 canvas.drawCircle(mRunCirclePoint.x, mRunCirclePoint.y, 10, mPaint);
一句话概括: 开启一个定时器不断地传入一个自增长的值.
OK,全部搞定!
0 0
- Android仪表盘实现自动增长的动画
- Android 仪表盘动画
- android 自定义View 仪表盘 DashboardView 的实现
- Android属性动画实现数字自增长
- android实现仪表盘效果
- Android动画背景图自动播放的实现
- Android动画背景图自动播放的实现
- Android动画背景图自动播放的实现
- oracle中自动增长列的实现
- SQL Server实现列的自动增长
- Oracle实现列的自动增长
- iOS简单实现仪表盘进度动画
- oracle 实现自动增长
- Android自定义View----时钟/仪表盘的简单实现
- SQL 实现从表中自动增长字段的最大值向上自动增长
- 简单实现数字增长动画
- android 简易仪表盘的设计
- Android animation 动画背景图自动播放的实现
- JsonOnlineViewer for Android Studio
- Unity3D再次点击以退出程序
- 详解 Java 线程池与工作队列
- 第四周博客作业
- 看论文方法
- Android仪表盘实现自动增长的动画
- 旋转数组中的最小值
- android闪屏(普通闪屏、倒计时闪屏、倒计时+动画闪屏)
- 简单LMDB用法
- 苹果电脑上查看iPhone中的沙盒文件夹
- 20170103:for 统计思维
- Hbase 批量插入(mapReduce)
- 首先灌入一万条数据(利用msyql存储过程)
- windows 下 webligic集群 apache 分发