步骤

1.自定义属性
2.在xml中使用
3.创建自定义view文件 写好构造函数
4.在上面的Java文件中访问自定义属性
5.实现onMeasure方法
6.画外圆弧 内圆弧 文字
7.添加一点动画

效果图

新建attrs文件夹 编写自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources><!-- step1 定义组定义属性 --><declare-styleable name="QQStepView"><attr name="outerColor" format="color"/><attr name="innerColor" format="color"/><attr name="borderWidth" format="dimension"/><attr name="stepTextSize" format="dimension"/><attr name="stepTextColor" format="color"/></declare-styleable>
</resources>

在xml中使用

<?xml version="1.0" encoding="utf-8"?>
<!-- step2 在xml中使用自定义属性 -->
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:chjapp="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="16dp"tools:context=".MainActivity"><com.example.chj.myapplication.QQStepViewandroid:id="@+id/myQQStepView"chjapp:stepTextColor="@color/colorAccent"chjapp:stepTextSize="30sp"chjapp:innerColor="@color/colorAccent"chjapp:outerColor="@color/colorPrimary"android:background="@android:color/holo_green_light"chjapp:borderWidth="15dp"android:layout_width="200dp"android:layout_height="200dp" /></android.support.constraint.ConstraintLayout>

编写自定义view

package com.example.chj.myapplication;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;public class QQStepView extends View {private int mOuterColor = Color.BLUE;private int mInnerColor = Color.GREEN;private int mBorderWidth = 1;private int mStepTextSize = 5;private int mStepTextColor = Color.GRAY;private Paint mOuterArcPaint, mInnerArcPaint, mTextPaint;private float mStepMax = 8000;private float mStepCurrent = 2000;//step3 创建java 文件并准备好构造方法public QQStepView(Context context) {this(context, null);}public QQStepView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public QQStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//step4 获取自定义属性TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.QQStepView);mInnerColor = array.getColor(R.styleable.QQStepView_innerColor, mInnerColor);mOuterColor = array.getColor(R.styleable.QQStepView_outerColor, mOuterColor);mStepTextColor = array.getColor(R.styleable.QQStepView_stepTextColor, mStepTextColor);mBorderWidth = (int) array.getDimension(R.styleable.QQStepView_borderWidth, mBorderWidth);mStepTextSize = array.getDimensionPixelSize(R.styleable.QQStepView_stepTextSize, mStepTextSize);array.recycle();mOuterArcPaint = new Paint();mOuterArcPaint.setAntiAlias(true);//抗锯齿mOuterArcPaint.setColor(mOuterColor);mOuterArcPaint.setStrokeWidth(mBorderWidth);mOuterArcPaint.setStyle(Paint.Style.STROKE);//画空心弧mOuterArcPaint.setStrokeCap(Paint.Cap.ROUND);//收口(帽子)为圆形 而不是直角mInnerArcPaint = new Paint();mInnerArcPaint.setAntiAlias(true);//抗锯齿mInnerArcPaint.setColor(mInnerColor);mInnerArcPaint.setStrokeWidth(mBorderWidth);mInnerArcPaint.setStyle(Paint.Style.STROKE);//画空心弧mInnerArcPaint.setStrokeCap(Paint.Cap.ROUND);//收口(帽子)为圆形 而不是直角mTextPaint = new Paint();mTextPaint.setAntiAlias(true);//抗锯齿mTextPaint.setColor(mStepTextColor);mTextPaint.setTextSize(mStepTextSize);}//step5 编写onMeasure方法 决定控件宽高@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);//如果xml中定义的宽高任意一个是wrap content 给控件一个最小宽高int smallerValue = 50;if (MeasureSpec.AT_MOST != MeasureSpec.getMode(widthMeasureSpec) && MeasureSpec.AT_MOST != MeasureSpec.getMode(heightMeasureSpec)) {//TODO 疑问 如果使用match parent出现的效果不对 不是正方形 但是断点看 应该宽高设置一致了。。。int width = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);//宽高取最小值 确保是个正方形smallerValue = Math.min(width, height);}setMeasuredDimension(smallerValue, smallerValue);}//step6 编写onDraw方法 画外圆弧 内圆弧 文字@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//step6.1 绘制外圆弧//边缘没有显示完整 是因为描边有宽度 需要减去描边宽度的一半 视频中的计算有些复杂了 不够直接RectF rectF = new RectF(mOuterArcPaint.getStrokeWidth() / 2, mOuterArcPaint.getStrokeWidth() / 2, getWidth() - mOuterArcPaint.getStrokeWidth() / 2, getHeight() - mOuterArcPaint.getStrokeWidth() / 2);//参数 绘制区域 开始绘制的角度 画笔扫过后绘制的角度 是否封闭 画笔canvas.drawArc(rectF, 135, 270, false, mOuterArcPaint);if (mStepMax == 0) {return;}//step6.2 绘制内圆弧(当前步数占总步数的比例==内弧的角度占外弧角度的比例)float innerArcSweepAngle = (mStepCurrent / mStepMax) * 270;//270是外弧的角度canvas.drawArc(rectF, 135, innerArcSweepAngle, false, mInnerArcPaint);//step6.3 绘制文字String mStepCurrentStr = (int) mStepCurrent + "";//计算文字绘制的左边起始点:(控件的宽度-文字的宽度)/2Rect textBounds = new Rect();mTextPaint.getTextBounds(mStepCurrentStr, 0, mStepCurrentStr.length(), textBounds);//用于计算text的宽度float textStartX = (getWidth() - textBounds.width()) / 2.0f;//计算文字绘制的baselinePaint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();int baseLine = getHeight() / 2 - fontMetricsInt.bottom / 2 - fontMetricsInt.top / 2;//int baseLine = Math.abs((fontMetricsInt.bottom - fontMetricsInt.top - getHeight()) / 2 + fontMetricsInt.top);//使用方法drawText(@NonNull String text, float x, float y, @NonNull Paint paint)//含义 文本 左边的绘制起始点 baseline 画笔canvas.drawText(mStepCurrentStr, textStartX, baseLine, mTextPaint);}public synchronized void setStepMax(int stepMax) {this.mStepMax = stepMax;}public synchronized void setStepCurrent(int stepCurrent) {this.mStepCurrent = stepCurrent;//不断绘制invalidate();}
}

在主界面使用自定义view

package com.example.chj.myapplication;import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.animation.DecelerateInterpolator;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final QQStepView qqStepView = findViewById(R.id.myQQStepView);qqStepView.setStepMax(20000);//step7 添加属性动画ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0,10799);valueAnimator.setDuration(1500);valueAnimator.setInterpolator(new DecelerateInterpolator());//插值器 用于调整动画播放速度 先快后慢valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float currentStep = (float) animation.getAnimatedValue();qqStepView.setStepCurrent((int) currentStep);}});valueAnimator.start();}}

代码:
https://github.com/caihuijian/learn_darren_android.git

红橙Darren视频笔记 仿QQ步数计数view 画笔的使用相关推荐

  1. 红橙Darren视频笔记 仿QQ侧滑效果

    这一篇没有什么新的内容 就是改写 红橙Darren视频笔记 仿酷狗侧滑效果 的侧滑的效果 1.去掉淡入淡出效果 2.加上黑色模板效果 效果: 去掉淡入淡出效果很简单 就是注释掉onScrollChan ...

  2. 红橙Darren视频笔记 仿汽车之家 可拖动列表

    最终效果演示 1.ViewDragHelper简介 1.1ViewDragHelper可以做什么基本效果 1.2实现code public class DragView extends FrameLa ...

  3. 红橙Darren视频笔记 仿酷狗侧滑效果

    效果 需求 1.思路利用ScrollView包裹两个布局+scroll实现侧滑效果 2.新建menu和主体的xml布局文件 自定义属性 并获取 4.在onFinishInflate修改布局宽度 思考o ...

  4. 红橙Darren视频笔记 UML图简介

    整体架构复制自红橙原视频的课堂笔记 因为他这一课没有博客,所以没有转载链接,CSDN没有转载地址是无法作为转载类型的文章发表的,暂时标记为原创 参考链接 https://blog.csdn.net/r ...

  5. 红橙Darren视频笔记 代理模式 动态代理和静态代理

    红橙Darren视频笔记 代理模式 动态代理和静态代理(Android API 25) 关于代理模式我之前有过相关的介绍: https://blog.csdn.net/u011109881/artic ...

  6. 红橙Darren视频笔记 类加载机制(API28) 自己写个热修复 查看源码网站

    第一部分 类加载机制 一个Activity是如何被Android虚拟机找到的? 在之前的文章 红橙Darren视频笔记 自定义View总集篇(https://blog.csdn.net/u011109 ...

  7. 红橙Darren视频笔记 利用阿里巴巴AndFix进行热修复

    注意 由于AndFix在2017年左右就停止更新了,在最新版本的apk上遇到很多问题,我最终也没有成功进行热修复.本节主要是学习热修复的原理 在上一篇 红橙Darren视频笔记 自己捕获异常并保存到本 ...

  8. 红橙Darren视频笔记 Behavior的工作原理源码分析

    主要coordinatorlayout的代码来自coordinatorlayout-1.0.0-sources.jar 本文从源码介绍 CoordinatorLayout 的 behavior 怎么工 ...

  9. 红橙Darren视频笔记 ViewGroup事件分发分析 基于API27

    本节目标,通过案例,先看程序运行结果,然后跟踪源码,理解为什么会有这样的输出,继而理解view group的分发机制,感觉和证明题很像呢. 考虑以下程序的运行结果: case1: public cla ...

最新文章

  1. js 识别汉字和全角字符
  2. 时间周期 java_周期和持续时间 / Period and Duration
  3. OpenResty 反向代理的用法与技巧
  4. 《Man Vs wild》 Notes-法国阿尔卑斯山
  5. pyecharts学习(part4)--pyecharts饼图
  6. 尤大是如何发布vuejs的,学完可以应用到项目
  7. PostgreSQL 统计信息pg_statistic格式及导入导出dump_stat - 兼容Oracle
  8. opoengl 投影矩阵的推导
  9. 记一次tomcat故障排查(转)
  10. python 安卓库_python 库实战 - 安卓简易自动化框架
  11. 工具--nssm详解
  12. CacheCloud详解(一)----------CacheCloud搭建(Redis云平台)
  13. 智科人之人工智能大实验四选一验优报告参考:基于遗传算法的函数极值求取
  14. 邻家的百万富翁(一)
  15. CJB的大作 - 乱搞
  16. 18个免费替代Photoshop的图像编辑软件
  17. 2016年408计网选择题
  18. 2019.6.24 校内测试 NOIP模拟 Day 2 分析+题解
  19. 学习记录540@SVN查看日志报错:Item is not readable
  20. 云服务器htdocs文件夹在,htdocs文件夹

热门文章

  1. element筛选 ajax,vue使用element Transfer 穿梭框实现ajax请求数据和自定义查询
  2. linux svn 启动命令行,Linux下启动、关闭SVN服务
  3. (转) intellij idea部署web项目时的位置(Tomcat)
  4. PAT-乙级-1034 有理数四则运算
  5. [转]Aptana Studio 3配置Python开发环境图文教程
  6. 选课_ctsc1997_ssl1606_树形dp
  7. silverlight中DataGrid错误:data未定义
  8. rtt面向对象oopc——3.对官方IO设备模型框架图的补充绘图
  9. 《数据结构C语言版》——线性表详解,你一定能够看得懂学得会的宝典
  10. 15日直播预告丨SQL条件等价改写秘笈(主讲人:怀晓明)