效果图

一开始是使用的最下面一种,发现canvas绘制线,一个点一个点绘制会非常的慢,于是改进成第一个,另外把对号单独提取出来了。

设计稿

分为一个圆和两条线,中间小的方框的边长就是代码中的hookSize,每次绘画的时候会先去找圆心,然后以圆心为中心去绘制正方形。

首先绘制圆,绘制完成后再分别绘制两条线,先画短的,画完短的再开始画长的。

几个注意点

1. 坐标系以左上角为原点,横X竖Y

2.在构造函数中通过getWidth来获取宽度得到的结果往往是0,在执行到onDraw的时候,控件大小才划定;

3.可以直接在布局文件中调用来使用

直接上代码

代码里都有注释

先上第三个的

DrawHookView.java

public class DrawHookView extends View {//绘制圆弧的进度值private int progress = 0;//线1的x轴private int line1_x = 0;//线1的y轴private int line1_y = 0;//线2的x轴private int line2_x = 0;//线2的y轴private int line2_y = 0;public DrawHookView(Context context) {super(context); }public DrawHookView(Context context, AttributeSet attrs) {super(context, attrs); }public DrawHookView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle); }//绘制@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);progress++;Paint paint = new Paint();//设置画笔颜色paint.setColor(getResources().getColor(R.color.colorPrimary));//设置圆弧的宽度paint.setStrokeWidth(5);//设置圆弧为空心paint.setStyle(Paint.Style.STROKE);//消除锯齿paint.setAntiAlias(true);//获取圆心的x坐标int center = getWidth() / 2;int center1 = center - getWidth() / 5;//圆弧半径int radius = getWidth() / 2 - 5;//定义的圆弧的形状和大小的界限RectF rectF = new RectF(center - radius -1, center - radius -1 ,center + radius + 1, center + radius + 1);//根据进度画圆弧canvas.drawArc(rectF, 235, -360 * progress / 100, false, paint);//先等圆弧画完,才话对勾if(progress >= 100) {if(line1_x < radius / 3) {line1_x++;line1_y++; }//画第一根线canvas.drawLine(center1, center, center1 + line1_x, center + line1_y, paint);if (line1_x == radius / 3) {line2_x = line1_x;line2_y = line1_y;line1_x++;line1_y++; }if (line1_x >= radius / 3 && line2_x <= radius) {line2_x++;line2_y--; }//画第二根线canvas.drawLine(center1 + line1_x - 1, center + line1_y, center1 + line2_x, center + line2_y, paint); }//每隔10毫秒界面刷新postInvalidateDelayed(10); }}

再上第一个的

DrawCheckMarkView.java

public class DrawCheckMarkView extends View {//绘制圆弧的进度值private int progress = 0;//打勾的起点int checkStartX;//线1的x轴增量private int line1X = 0;//线1的y轴增量private int line1Y = 0;//线2的x轴增量private int line2X = 0;//线2的y轴增量private int line2Y = 0;//增量值int step=2;//线的宽度private int lineThick = 4;//获取圆心的x坐标int center;//圆弧半径int radius;//定义的圆弧的形状和大小的界限RectF rectF;Paint paint;//控件大小float totalWidth;boolean secLineInited = false;public DrawCheckMarkView(Context context) {super(context);init(); }public DrawCheckMarkView(Context context, AttributeSet attrs) {super(context, attrs);Pattern p = Pattern.compile("\\d*");Matcher m = p.matcher(attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_width"));if (m.find()) {totalWidth = Float.valueOf(m.group()); }totalWidth = DisplayUtils.dp2px(context, totalWidth);init(); }public DrawCheckMarkView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(); }void init() {paint = new Paint();//设置画笔颜色paint.setColor(getResources().getColor(R.color.colorAccent));//设置圆弧的宽度paint.setStrokeWidth(lineThick);//设置圆弧为空心paint.setStyle(Paint.Style.STROKE);//消除锯齿paint.setAntiAlias(true);//获取圆心的x坐标center = (int) (totalWidth / 2);//圆弧半径radius = (int) (totalWidth / 2) - lineThick;checkStartX = (int) (center - totalWidth / 5);rectF = new RectF(center - radius,center - radius,center + radius,center + radius); }//绘制@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Log.w("check mark", "drawing... # progress=" + progress);if (progress < 100)progress += step;//根据进度画圆弧canvas.drawArc(rectF, 235, -360 * progress / 100, false, paint);//先等圆弧画完,画对勾if (progress >= 100) {if (line1X < radius / 3) {line1X+=step;line1Y+=step; }//画第一根线canvas.drawLine(checkStartX, center, checkStartX + line1X, center + line1Y, paint);if (line1X >= radius / 3) {if (!secLineInited) {line2X = line1X;line2Y = line1Y;secLineInited=true; }line2X+=step;line2Y-=step;//画第二根线canvas.drawLine(checkStartX + line1X - lineThick / 2,center + line1Y, checkStartX + line2X, center + line2Y, paint); } }//每隔6毫秒界面刷新if (line2X <= radius)postInvalidateDelayed(6); }}

最后是中间的

DrawHookMarkView.java

public class DrawHookMarkView  extends View {//打勾的起点int checkStartX;//线1的x轴增量private int line1X = 0;//线1的y轴增量private int line1Y = 0;//线2的x轴增量private int line2X = 0;//线2的y轴增量private int line2Y = 0;//增量值int step = 3;//线的宽度private int lineThick = 6;//获取圆心的x坐标int center;//圆弧半径int radius;Paint paint;//控件大小float totalWidth;boolean secLineInited = false;public DrawHookMarkView(Context context) {super(context);init(); }public DrawHookMarkView(Context context, AttributeSet attrs) {super(context, attrs);Pattern p = Pattern.compile("\\d*");Matcher m = p.matcher(attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_width"));if (m.find()) {totalWidth = Float.valueOf(m.group()); }totalWidth = DisplayUtils.dp2px(context, (int) totalWidth);init(); }public DrawHookMarkView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(); }void init() {paint = new Paint();//设置画笔颜色paint.setColor(getResources().getColor(R.color.colorPrimaryDark));//设置宽度paint.setStrokeWidth(lineThick);//设置空心paint.setStyle(Paint.Style.STROKE);//消除锯齿paint.setAntiAlias(true);//获取圆心的x坐标center = (int) (totalWidth / 2);//圆弧半径radius = (int) (totalWidth / 2) - lineThick;checkStartX = (int) (center - totalWidth / 5); }//绘制@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (line1X < radius / 3) {line1X += step;line1Y += step; }//画第一根线canvas.drawLine(checkStartX, center, checkStartX + line1X, center + line1Y, paint);if (line1X >= radius / 3) {if (!secLineInited) {line2X = line1X;line2Y = line1Y;secLineInited = true; }line2X += step;line2Y -= step;//画第二根线canvas.drawLine(checkStartX + line1X - lineThick / 2,center + line1Y, checkStartX + line2X, center + line2Y, paint); }//每隔6毫秒界面刷新if (line2X <= radius)postInvalidateDelayed(6); }}

一个px、dp、sp的转换工具类

DisplayUtils.java

public class DisplayUtils {public static float px2dp(final Context context, final float px) {return px / context.getResources().getDisplayMetrics().density; }public static float dp2px(final Context context, final float dp) {return dp * context.getResources().getDisplayMetrics().density; }/*** 将px值转换为sp值,保证文字大小不变* @param pxValue* @return*/public static int px2sp(Context context, float pxValue) {final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;return (int) (pxValue / fontScale + 0.5f); }/*** 将sp值转换为px值,保证文字大小不变* @param spValue* @return*/public static int sp2px(Context context, float spValue) {final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;return (int) (spValue * fontScale + 0.5f); }}

项目地址:github

Android 自定义View 通过Paint和Canvas实现动态打勾对号效果相关推荐

  1. Android Toast 吐司 自定义使用 实现动态打勾对号效果 Toast自定义教程(三)

    这篇博客主要是写了功能的实现,在前面已经写了原理. Android 自定义View 通过Paint和Canvas实现动态打勾对号效果 Android Toast 吐司 自定义使用 展示图片 Toast ...

  2. Android自定义View之Paint绘制文字和线

    Android自定义View系列 Android自定义View注意事项 Android自定义View之图像的色彩处理 Android自定义View之Canvas Android自定义View之轻松实现 ...

  3. Android自定义View精品(LimitScrollerView-仿天猫广告栏上下滚动效果)

    版权声明:本文为openXu原创文章[openXu的博客],未经博主允许不得以任何形式转载 文章目录 1.分析 2.定义组合控件布局 3.继承最外层控件 4.自定义属性 5.重写onMeasure 6 ...

  4. android 自定义paint,Android自定义View中Paint、Rect、Canvas介绍(一)

    自定义View对于新手而言貌似是一个很复杂的东西.格式,各函数的意义.对于大神经常忘记各函数及一些参数的具体写法及意义,刚好在做一个风车效果,把过程及遇到的问题都写下来 1.如何自定义一个View p ...

  5. Android自定义View之paint(一)

    2019独角兽企业重金招聘Python工程师标准>>> 学习自定义view,就是将view绘成自己想要的样子,自然就要有绘画的工具,那就是Paint. **1. 构造函数 ** Pa ...

  6. Android自定义View教你一步一步实现即刻点赞效果

    前言 今天朋友看了HenCoder的自定义View后说,HenCoder对自定义View讲的不错.实践中仿写即刻的点赞你有思路吗,你不实现一下?二话不说,看了朋友手机效果,对他说:实现不难,用到了位移 ...

  7. Android自定义View基础--Paint画笔设置颜色过滤器

    Android–Paint画笔设置颜色过滤器 光照效果 /** LightingColorFilter(0xffffff,0x003000);* 第一个参数是去除照片中的某个颜色* 第二个参数是增加颜 ...

  8. 精通Android自定义View(十一)绘制篇Canvas分析之裁剪

    clipRect(int left, int top, int right, int bottom)  这个方法作用就是裁切一个矩形出来,但是图形不还是在canvas上面的,所以本质上还是裁切的can ...

  9. 精通Android自定义View(九)绘制篇Canvas分析之绘制图片

    绘制图片分为:绘制矢量图(drawPicture)和 绘制位图(drawBitmap) 1 drawBitmap 1.1 基本的绘制图片方法 //Bitmap:图片对象,left:偏移左边的位置,to ...

最新文章

  1. ZedGraph5.1.5源码分析去掉鼠标悬浮内容闪烁问题(附源码下载)
  2. 不使用sprintf函数使用共用体进行STM32单片机通讯解析
  3. 基于LZ77算法的文件压缩铺垫
  4. 基于JavaConfig配置的Spring MVC的构建
  5. android x86_64 服务器运行,魔趣 android10 编译x86-64 运行模拟器
  6. java与模式孙悟空_悟空模式-java-工厂方法模式
  7. 并发环境下的缓存容器性能优化(上):不可变的哈希表
  8. Java中栈和队列的类
  9. kswapd进程与swap、swappiness之间的关系及原理
  10. 安卓机型刷写第三方twrp 刷写第三方rom的教程和一些问题解决
  11. Dual Thrust 商品期货 (注释版)
  12. linux编译 __stdcall,Linux中是否有STDCALL?
  13. python画双坐标图_Python画双坐标曲线图
  14. 【python统计分析】stats.ttest_ind 独立样本T检验
  15. 高仿QQ游戏大厅-支持换肤和控件切换动画
  16. js设计程序实现摄氏度和华氏度转换
  17. 天宫初级认证答案_跨境电商人才初级认证试题以及答案
  18. 了解过什么是 DDD吗?一文带你掌握!(至尊典藏版)
  19. 四川省建设厅关于推行建筑工人实名制管理工作的通知〔2018〕613号
  20. android remoteViews

热门文章

  1. android开发 迅雷下载地址,用迅雷下载Android SDK全系列
  2. 12家上市银行日均净赚逾23亿 利息收入以价补量
  3. 如何一站式管理固定资产的全生命周期?
  4. 深度学习环境配置(GPU)
  5. 骁龙778gplus和天玑8100哪个好
  6. Kotlin中的byte转int
  7. [网赚项目] 羊了个羊,周边日赚几百几千玩法
  8. linux ssh公钥文件,linux配置ssh公钥认证
  9. 开发技巧-解决打开谷歌浏览器跳转问题
  10. [言论]影响世界的100条管理名言