Android 自定义View 通过Paint和Canvas实现动态打勾对号效果
效果图
一开始是使用的最下面一种,发现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实现动态打勾对号效果相关推荐
- Android Toast 吐司 自定义使用 实现动态打勾对号效果 Toast自定义教程(三)
这篇博客主要是写了功能的实现,在前面已经写了原理. Android 自定义View 通过Paint和Canvas实现动态打勾对号效果 Android Toast 吐司 自定义使用 展示图片 Toast ...
- Android自定义View之Paint绘制文字和线
Android自定义View系列 Android自定义View注意事项 Android自定义View之图像的色彩处理 Android自定义View之Canvas Android自定义View之轻松实现 ...
- Android自定义View精品(LimitScrollerView-仿天猫广告栏上下滚动效果)
版权声明:本文为openXu原创文章[openXu的博客],未经博主允许不得以任何形式转载 文章目录 1.分析 2.定义组合控件布局 3.继承最外层控件 4.自定义属性 5.重写onMeasure 6 ...
- android 自定义paint,Android自定义View中Paint、Rect、Canvas介绍(一)
自定义View对于新手而言貌似是一个很复杂的东西.格式,各函数的意义.对于大神经常忘记各函数及一些参数的具体写法及意义,刚好在做一个风车效果,把过程及遇到的问题都写下来 1.如何自定义一个View p ...
- Android自定义View之paint(一)
2019独角兽企业重金招聘Python工程师标准>>> 学习自定义view,就是将view绘成自己想要的样子,自然就要有绘画的工具,那就是Paint. **1. 构造函数 ** Pa ...
- Android自定义View教你一步一步实现即刻点赞效果
前言 今天朋友看了HenCoder的自定义View后说,HenCoder对自定义View讲的不错.实践中仿写即刻的点赞你有思路吗,你不实现一下?二话不说,看了朋友手机效果,对他说:实现不难,用到了位移 ...
- Android自定义View基础--Paint画笔设置颜色过滤器
Android–Paint画笔设置颜色过滤器 光照效果 /** LightingColorFilter(0xffffff,0x003000);* 第一个参数是去除照片中的某个颜色* 第二个参数是增加颜 ...
- 精通Android自定义View(十一)绘制篇Canvas分析之裁剪
clipRect(int left, int top, int right, int bottom) 这个方法作用就是裁切一个矩形出来,但是图形不还是在canvas上面的,所以本质上还是裁切的can ...
- 精通Android自定义View(九)绘制篇Canvas分析之绘制图片
绘制图片分为:绘制矢量图(drawPicture)和 绘制位图(drawBitmap) 1 drawBitmap 1.1 基本的绘制图片方法 //Bitmap:图片对象,left:偏移左边的位置,to ...
最新文章
- ZedGraph5.1.5源码分析去掉鼠标悬浮内容闪烁问题(附源码下载)
- 不使用sprintf函数使用共用体进行STM32单片机通讯解析
- 基于LZ77算法的文件压缩铺垫
- 基于JavaConfig配置的Spring MVC的构建
- android x86_64 服务器运行,魔趣 android10 编译x86-64 运行模拟器
- java与模式孙悟空_悟空模式-java-工厂方法模式
- 并发环境下的缓存容器性能优化(上):不可变的哈希表
- Java中栈和队列的类
- kswapd进程与swap、swappiness之间的关系及原理
- 安卓机型刷写第三方twrp 刷写第三方rom的教程和一些问题解决
- Dual Thrust 商品期货 (注释版)
- linux编译 __stdcall,Linux中是否有STDCALL?
- python画双坐标图_Python画双坐标曲线图
- 【python统计分析】stats.ttest_ind 独立样本T检验
- 高仿QQ游戏大厅-支持换肤和控件切换动画
- js设计程序实现摄氏度和华氏度转换
- 天宫初级认证答案_跨境电商人才初级认证试题以及答案
- 了解过什么是 DDD吗?一文带你掌握!(至尊典藏版)
- 四川省建设厅关于推行建筑工人实名制管理工作的通知〔2018〕613号
- android remoteViews