一、前言

上节 通过一个简单的旋转环对自定义view作了一个基本的认识,本文将大致讲解下实现的思路以及对该view的一些可能的改进。

二、思路

主要通过重写 view 中的 onDraw() 方法,利用 canvas 类中的 drawArc() 方法绘制圆弧,其中第一个参数 rectF 是一个浮点矩形,确定了圆弧的大小及位置 (想象一个放在矩形中的圆,截取其弧即成圆环)。其中圆弧颜色由画笔类 Paint 定义, 为简单起见,这里使用两种颜色的渐变色。值得一提的是,当圆弧两端成圆头时 ( paint.getStrokeCap() == Paint.Cap.ROUND ),其首端的圆头颜色为尾部的颜色,如图2.1.1 所示。因此此处要将起始旋转角度 + width/2。其中 width 为圆环的宽度,除以2 恰好为圆头的半径,故可以通过这种办法消除掉,如图2.1.2所示

绘制圆弧需要确定起始角度 startAngle,以及扫过的角度sweepAngle,对于 startAngle,其中3点钟方向为0°, sweepAngle一般不超过360° (超过即成一个完整的圆)。此外还需要一个boolean变量的值,来确定是否绘出圆弧对应的半径。由于我们不需要扇形,这里设为fasle。

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.rotate(angle, centerX, centerY);
canvas.drawArc(rectF, paint.getStrokeCap() == Paint.Cap.ROUND ? startAngle + width/2f: startAngle,
sweepAngle, false, paint);
}

         

图2.1.1  首部圆头部分出现尾部颜色                      图2.1.2   正常的圆弧

canvas.drawArc() 的第五个参数为Paint类型,这里定义了绘制圆弧所用到的画笔,如下所示

private void setPaint(){
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setShader(new SweepGradient(centerX, centerY,
new int[]{startColor, endColor},
new float[]{startAngle/360f*1.0f, sweepAngle/360f*1.0f}));
paint.setAntiAlias(true);
paint.setStrokeWidth(width);
}

  

此处主要说说何处初始化该 paint 的原因。由于实现圆弧的渐变色用到了 SweepGradient 着色器,着色器需要传入x、y来确定扫描渐变色的中心,故需要在获取到控件中心之后再进行初始化。在该自定义圆弧控件中,是通过 onSizeChanged(int w, int h, int oldw, int oldh) 方法来获取控件视图的中点,故在 onSizeChanged() 方法中对画笔进行初始化,如下所示

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
centerX = w / 2;
centerY = h / 2;
rectF = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
setPaint();
}

  

最后,通过 ValueAnimator 类给圆弧设置一个旋转动画,通过调用视图本身的 invalidate() 方法,不断通知视图进行重绘 (不断调用onDraw()方法 ),实现了圆弧视觉上的旋转。

public void startAnim(){
final ValueAnimator animator = ValueAnimator.ofInt(0,360);
animator.setDuration(duration);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
angle = (int) animation.getAnimatedValue();
invalidate();
}
});
animator.start();
}

  

下节 讲述如何添加自定义属性,在xml中声明旋转环的颜色、半径、宽度,旋转速率等,避免在代码中显式调用setXXX()方法。

Android 自定义View (二)的更多相关文章

  1. Android自定义View (二) 进阶

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24300125 继续自定义View之旅,前面已经介绍过一个自定义View的基础的例 ...

  2. Android 自定义View (二) 进阶

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24300125 继续自定义View之旅,前面已经介绍过一个自定义View的基础的例 ...

  3. Android 自定义View二(深入了解自定义属性attrs.xml)

    1.为什么要自定义属性 要使用属性,首先这个属性应该存在,所以如果我们要使用自己的属性,必须要先把他定义出来才能使用.但我们平时在写布局文件的时候好像没有自己定义属性,但我们照样可以用很多属性,这是为 ...

  4. Android 自定义view(二) —— attr 使用

    前言: attr 在前一篇文章<Android 自定义view -- attr理解>已经简单的进行了介绍和创建,那么这篇文章就来一步步说说attr的简单使用吧 自定义view简单实现步骤 ...

  5. Android 自定义View及其在布局文件中的使用示例(二)

    转载请注明出处 http://www.cnblogs.com/crashmaker/p/3530213.html From crash_coder linguowu linguowu0622@gami ...

  6. Android自定义View(二、深入解析自定义属性)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51468648 本文出自:[openXu的博客] 目录: 为什么要自定义属性 怎样自定义属性 ...

  7. Android 自定义 view(三)—— onDraw 方法理解

    前言: 上一篇已经介绍了用自己定义的属性怎么简单定义一个view<Android 自定义view(二) -- attr 使用>,那么接下来我们继续深究自定义view,下一步将要去简单理解自 ...

  8. Android 自定义View及其在布局文件中的使用示例(三):结合Android 4.4.2_r1源码分析onMeasure过程

    转载请注明出处 http://www.cnblogs.com/crashmaker/p/3549365.html From crash_coder linguowu linguowu0622@gami ...

  9. android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索

    我们的手机通讯录一般都有这样的效果,如下图: OK,这种效果大家都见得多了,基本上所有的android手机通讯录都有这样的效果.那我们今天就来看看这个效果该怎么实现. 一.概述 1.页面功能分析 整体 ...

  10. Android自定义View研究--View中的原点坐标和XML中布局自定义View时View触摸原点问题

    这里只做个汇总~.~独一无二 文章出处:http://blog.csdn.net/djy1992/article/details/9715047 Android自定义View研究--View中的原点坐 ...

随机推荐

  1. 一个MySQL双引号把我坑惨了!

    一.前言 最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程,把我坑得够惨. 二.过程 由于开发需要在生产环节中修复数据,需要执行120条SQL语句,需要将数据进行更新, ...

  2. tomcat反向代理,监控,性能优化详细步骤

    第1章 tomcat简介Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache,Sun和其他一些公司及个人共同 ...

  3. Centos7 更换yum软件源

    https://blog.csdn.net/zhinian1204/article/details/123975403

  4. 7.项目结构的构建和提交到gitee

    创建微服务模块 以商城项目的产品模块为例 点击Next,然后倒入依赖的包,Spring Web 然后在选择一个微服务和微服务之间调用需要的包:OpenFeign 导入这两个微服务的组件就行,后面需要用 ...

  5. java8 stream流的使用

    List<Paper> list = new ArrayList<>();list.add(new Paper("m",2L));list.add(new ...

  6. 从零搭建php环境-php8-扩展-redis

    一.下载1.https://pecl.php.net/get/redis-5.3.2.tgz下载到本地,文件传输上传到 /usr/local/src/2.wget -P /usr/local/src/ ...

  7. Docker学习——多阶段构建(六)

    之前的做法 在 Docker 17.05 版本之前,我们构建 Docker 镜像时,通常会采用两种方式: 全部放入一个 Dockerfile 一种方式是将所有的构建过程编包含在一个 Dockerfil ...

  8. zabbix监控mysql数据库——qps和tps

    首先可以继续顺着zabbix监控mysql继续往下做 1.首先在42的继续编写qps和tps 1.1qps 在41服务端查询: 1.2 tps 2.在web进行查看

  9. Check If Binary Tree Is Completed

    Check if a given binary tree is completed. A complete binary tree is one in which every level of the ...

  10. 训练题——DS18B20部分

    Author:Cherry_Ywj 0. 前言 本文档以 DS18B20 为例,主要介绍如何针对一种传感器编写相应的驱动库,驱动是单片机开发中难度较大的一环.从看别人代码并对照 datasheet 开 ...