版本:2.0

日期:2014.3.21 2014.3.28
版权:© 2014 kince 转载注明出处
android-circlebutton是github上的一个开源项目,正如它的简介一样:Circle button widget for Android,就是一个圆形的button。它与一般圆形的button不同之处在于它是画出来的,属于自定义UI的范畴,因此我拿来介绍一下,而们平常一般使用的button可能是来自于美工的图片。它的好处是节省了资源空间,当然缺点也很明显开发人员也要参与界面设计这块了。其实这样也不能说不好,反过来想减少了对美工的依赖,而且也比较适合开发人员自己去实现一些扁平化的东西,因为它很简洁。

首先看代码,

package com.example.circlebutton;import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ImageView;public class CircleButton extends ImageView {private static final int PRESSED_COLOR_LIGHTUP = 255 / 25;private static final int PRESSED_RING_ALPHA = 75;private static final int DEFAULT_PRESSED_RING_WIDTH_DIP = 4;private static final int ANIMATION_TIME_ID = android.R.integer.config_shortAnimTime;private int centerY;private int centerX;private int outerRadius;private int pressedRingRadius;private Paint circlePaint;private Paint focusPaint;private float animationProgress;private int pressedRingWidth;private int defaultColor = Color.BLACK;private int pressedColor;private ObjectAnimator pressedAnimator;public CircleButton(Context context) {super(context);init(context, null);}public CircleButton(Context context, AttributeSet attrs) {super(context, attrs);init(context, attrs);}public CircleButton(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(context, attrs);}@Overridepublic void setPressed(boolean pressed) {super.setPressed(pressed);if (circlePaint != null) {circlePaint.setColor(pressed ? pressedColor : defaultColor);}if (pressed) {showPressedRing();} else {hidePressedRing();}}@Overrideprotected void onDraw(Canvas canvas) {canvas.drawCircle(centerX, centerY, pressedRingRadius + animationProgress, focusPaint);canvas.drawCircle(centerX, centerY, outerRadius - pressedRingWidth, circlePaint);super.onDraw(canvas);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);centerX = w / 2;centerY = h / 2;outerRadius = Math.min(w, h) / 2;pressedRingRadius = outerRadius - pressedRingWidth - pressedRingWidth / 2;}public float getAnimationProgress() {return animationProgress;}public void setAnimationProgress(float animationProgress) {this.animationProgress = animationProgress;this.invalidate();}public void setColor(int color) {this.defaultColor = color;this.pressedColor = getHighlightColor(color, PRESSED_COLOR_LIGHTUP);circlePaint.setColor(defaultColor);focusPaint.setColor(defaultColor);focusPaint.setAlpha(PRESSED_RING_ALPHA);this.invalidate();}private void hidePressedRing() {pressedAnimator.setFloatValues(pressedRingWidth, 0f);pressedAnimator.start();}private void showPressedRing() {pressedAnimator.setFloatValues(animationProgress, pressedRingWidth);pressedAnimator.start();}private void init(Context context, AttributeSet attrs) {this.setFocusable(true);this.setScaleType(ScaleType.CENTER_INSIDE);setClickable(true);circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);circlePaint.setStyle(Paint.Style.FILL);focusPaint = new Paint(Paint.ANTI_ALIAS_FLAG);focusPaint.setStyle(Paint.Style.STROKE);pressedRingWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_PRESSED_RING_WIDTH_DIP, getResources().getDisplayMetrics());int color = Color.BLACK;if (attrs != null) {final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleButton);color = a.getColor(R.styleable.CircleButton_cb_color, color);pressedRingWidth = (int) a.getDimension(R.styleable.CircleButton_cb_pressed_ring_width, pressedRingWidth);a.recycle();}setColor(color);focusPaint.setStrokeWidth(pressedRingWidth);final int pressedAnimationTime = getResources().getInteger(ANIMATION_TIME_ID);pressedAnimator = ObjectAnimator.ofFloat(this, "animationProgress", 0f, 0f);pressedAnimator.setDuration(pressedAnimationTime);}private int getHighlightColor(int color, int amount) {return Color.argb(Math.min(255, Color.alpha(color)), Math.min(255, Color.red(color) + amount),Math.min(255, Color.green(color) + amount), Math.min(255, Color.blue(color) + amount));}
}
继承了ImageView,这也注定了没有文字效果,所以如果你还想有文字效果,那么可以继承于button。看一下变量,除了Paint之外,再也就是3.0之后引入的属性动画ObjectAnimator这个类。既然是属性动画,当然是改变属性值了(不断更改对象的属性值),在这里就是改变button的颜色值。
构造方法里,还是常规的初始化paint、从attrs里获取属性值以及设置一些其他变量值,还要就是ObjectAnimator的初始化。然后CircleButton类会进入onSizeChanged方法,在这个方法里初始化了CircleButton的圆形坐标以及其他的变量。接着进入onDraw方法,在这里面绘制CircleButton,代码如下:

  canvas.drawCircle(centerX, centerY, pressedRingRadius + animationProgress, focusPaint);canvas.drawCircle(centerX, centerY, outerRadius - pressedRingWidth, circlePaint);

可以看到它绘制了两个圆形,其实是这样的,从两个Paint变量就可以看出:一个是cirlcePaint,它的Style是FILL类型的,说明它画的是实心圆也就是默认状态下的button。另一个focusPaint是获取焦点时候调用的,它的Style是STROKE类型的,所以画出一个圆环效果,这也就是点击button之后出现的。但是看一下这两个圆环的半径发现实心圆的半径比空心圆的半径要大4。那把画实心圆的代码注释掉,效果是这样的:

看完就明白了,原来是实心圆把空心圆给遮住了,所以默认情况下,看到的是实心圆。当点击button的时候,执行setPressed()方法,这个方法在里面会调用showPressedRing()方法,也就是开启动画效果。这样,关于CircleButton的机制就清楚了。
接下来根据这个lizi 做一个拓展,学以致用。比如我还想使用矩形的butoon,然后也有点击动画的效果,那如何完成呢?很简单,原理同上,上面的例子画的是圆形,那么类似地就画矩形。在onDraw()中加入如下代码:
        //可以放大的矩形RectF rect=new RectF();rect.left=8-animationProgress;rect.top=8-animationProgress;rect.right= 47+ animationProgress;rect.bottom=47 + animationProgress;canvas.drawRect(rect, focusPaint);// 长方形  //实心矩形RectF rect1=new RectF();rect1.left=5;rect1.top=5;rect1.right=50;rect1.bottom=50;canvas.drawRect(rect1, circlePaint);// 长方形  

思路是通过RecF画矩形,在每次点击的时候,让坐标位置随着animationProgress而改变。

android-circlebutton介绍相关推荐

  1. android AsyncTask介绍(转)

    android AsyncTask介绍 AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接 ...

  2. Android类库介绍

    Android类库介绍 GPhone开发包Android SDK含了很多丰富的类库: android.util 涉及系统底层的辅助类库 android.os 提供了系统服务.消息传输.IPC管道 an ...

  3. 1.android体系结构介绍

    一.Android的介绍 android介绍见百度百科:Android的介绍,度娘把Android介绍的这么清楚,如果谷歌是Android的爹,那度娘就是娘了. 二.Android的架构图 andro ...

  4. 【转】Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析

    原文网址:http://blog.csdn.net/xubin341719/article/details/38584469 关键词:蓝牙blueZ  A2DP.SINK.sink_connect.s ...

  5. 作业Android自我介绍

    ***Android自我介绍***

  6. Android HIDL 介绍学习之客户端调用

    应上一篇文章Android HIDL 介绍学习_Super Jang的博客-CSDN博客_安卓hidl读者的要求,本文更新客户端调用方法. hidl的客户端调用相比服务端的实现要简单很多,本次我们通过 ...

  7. Android开发介绍

    Android开发介绍 这个教程设计是帮助你学习基础的Android开发和快速搭建您的开发环境.这个是在我的Window 7上编写的,当然它也支持Linux(uBuntu).Mac OS其他支持And ...

  8. android 模拟器的使用(Android模拟器介绍及创建)

    做了这么久的android开发,一直想把在开发过程中积累的经验或问题总结一下,可是都没有时间,现在有一点点空闲,所以慢慢把我在android中遇到的问题整理一下写出来,供自己以后参考,也希望和大家一起 ...

  9. Android bluetooth介绍(一):基本概念及硬件接口

    关键词:蓝牙硬件接口 UART  PCM  blueZ  版本:基于android4.2之前版本 bluez 内核:linux/linux3.08 系统:android/android4.1.3.4 ...

  10. Android bluetooth介绍(二): android 蓝牙代码架构及其uart 到rfcomm流程

    关键词:蓝牙blueZ  UART  HCI_UART H4  HCI  L2CAP RFCOMM  版本:基于android4.2之前版本 bluez内核:linux/linux3.08 系统:an ...

最新文章

  1. Pandownload 下线了,我自己花了 30 分钟自己搭建了一个网盘
  2. 人工智能:从经典计算机到量子计算机,弱AI进阶到强AI时代?
  3. 小波变换如何去噪的思想
  4. _Ansible批量管理与维护
  5. 整数的个数(信息学奥赛一本通-T1067)
  6. 前端实现街道地图_使用百度地图实现地图网格的示例_白峰_前端开发者
  7. 分析一个文本文件(英文文章)中各个词出现的频率,并且把频率最高的十个词打印出来...
  8. 混合app用百分比还是rem_[笔记]em, rem最佳实践
  9. 《SAP从入门到精通》——导读
  10. dede 表单必填_织梦给自定义表单增加必填功能,织梦表单必填设置
  11. html怎么偏左居中,word文档偏左怎么调到中间
  12. STM32 触摸屏触摸功能
  13. 30天自制操作系统笔记--Day01
  14. macbook卡在进度条开不了机_Mac电脑开机一直卡在加载进度条怎么办?
  15. 户外运动装备新品--云息智能定位胸牌
  16. 阿里云后台运行python程序(后台运行scrapy爬虫)的方法
  17. Java中实现图片的上传
  18. 写给想要入行或刚刚入行程序员的二十条至理格言
  19. 元宇宙路在何方?觅伊以视频社交切入迎接新机遇
  20. IIS配置Web服务

热门文章

  1. [转] [Elasticsearch] 数据建模 - 处理关联关系(1)
  2. 网络文件系统访问与ftp服务
  3. CAP原理和最终一致性(Eventually Consistency)
  4. aspx页面中文汉字显示为乱码
  5. 20180921 su与sudo命令、限制root用户通过ssh远程登录
  6. AD 脚本kixtart运用之三(添加windows共享打印机)
  7. 企业要做好安全遵从的五个实用技巧
  8. redis 之 ae 模型测试
  9. 中国光谷大数据产业联盟成立 打造大数据产业生态圈
  10. 解决载入自定义视图时出现InflateException #8:Error inflating的错误