Android自定义评分控件:RatingStarView
RatingStarView
Android自定义的评分控件,类似RatingBar那样的,使用星星图标(full、half、empty)作为rating值的“评分/打分控件”。
效果图
图1:
RatingStarView控件支持的特性:

- 半颗星支持(实际支持任意小数)
- 填充色、底色、描边色
- 指定高度,宽度自适应
- 拐角弧度、描边宽度、星星间距
- 肥胖指数(star thickness),越胖越可爱
- 点击评分(不支持半颗星)
实现思路
下面是RatingStarView的实现设计。
如何画一颗星
Star标准坐标
可以在抽象的xOy坐标系中计算得到一个star的“标准坐标”。这个坐标可以作为后续有关坐标计算(偏移和缩放)的基准。
图2:

以上面的图为例,这里其中心点O为原点。
这里为了描述方便,称A,B,C,D,E为5个外点(Outer Corner Vertex),a,b,c,d,e 五个点为内点(Inner Corner Vertex)。
这里坐标值的选取完全出于计算方便来考虑,实现方式毕竟很多,大家可以选取其它坐标方式,比如原点O的位置在其它处,或者星星的范围由高度、宽度表示等。
5个外顶点
A拐点的坐标为(0,1),其它几个点的坐标根据几何公式是可以固定下来的。为了简化计算,可以将这几个值作为常量保存,之后的其它值的计算基于它们。下面代码为了程序上的便利E点坐标x,y值是起始元素:
private static final float[] starVertexes = new float[]{
-0.9511f, 0.3090f, // E (left)
0.0000f, 1.0000f, // A (top vertex)
0.9511f, 0.3090f, // B (right)
0.5878f, -0.8090f, // C (bottom right)
-0.5878f, -0.8090f, // D (bottom left)
};
使用常量简化五角星坐标计算时的cos、sin操作。因为几何上这些点的坐标是固定的。之后可以通过简单的+-*/操作来变换坐标系,以及star的大小。
常量也不会保持得太多,比如a,b,c,d,e的计算是根据A,B,C,D,E来的。
5个内拐点
这里为star引入“胖度系数(star thickness)”的说法,用来控制星星的可爱程度。
很明显,胖度是由a,b,c,d,e五个内点的位置决定的。
但在计算上,这里采取另一种方式:
设置变量thickness来表示肥胖系数,5个内点的位置由原点O和此内点临近的两个外点计算得到。
还是上面的图2,
AE的中点是P,那么e肯定在OP上,如果取OP上的其它点,作为EPA这样的多边形路径(其它五个内点类似)就可以打造出不同肥胖度的星星了。
这里因为原点O是星星的中心,在标准坐标系下,根据胖度系数thickness,结合ABCDE这几个外点,就可以计算出abcde这几个内点了,而且当thickness不同时,星星胖度不同。
根据thickness和ABCDE计算abcde的过程必须是在“标准坐标系”下,也就是X+轴向右,Y+向上,而且O原点是星星中心!!
坐标转换
每一个要显示的star由一个StarModel类来表示,它持有一个星星的坐标信息并完成相应的计算。
其代码是整个RatingStarView关于坐标部分的核心,完整代码见下面的源码地址。
拐点(顶点)表示
星星的顶点可以用一个PointF进行表示,不过这里为了方便将多个点作为一个链表使用,定义了下面的VertexF来保存顶点数据:
class VertexF {
public VertexF() {
}
public VertexF(float x, float y) {
this.x = x;
this.y = y;
}
public float x;
public float y;
public VertexF next;
}
10个拐点的计算
StarModel类使用静态的数组保存ABCDE五个外点的标准坐标系下的坐标初始值。
因为thickness系数必须在标准坐标系下计算,这里选择StarModel的构造函数中接受thickness参数,而且初始化中完成所有10个拐点的计算。
转换到Android坐标系
手机设备下,Android的Y+是向下的,所以需要一个adjustCoordinate()的方法来完成星星坐标系的转换。
同时它还将星星的x,y都变为正数——这样它才是可见的。
注意Android中,childView绘制自身内容时,其使用的x,y坐标单位是pixel,而且是相对其父ViewGroup的相对坐标。
偏移和缩放
RatingStarView在显示若干个star时,需要可以控制其位置和大小。
所以StarModel在标准坐标系转换完为Android下坐标系后(在父布局中的相对坐标),还需要可以被偏移和缩放。
偏移
只需要对10个拐点坐标进行+、-操作即可。
有关Star的大小这里使用height来衡量,因为绘制肯定是完整的星星,这样height和width是有一个比例的。选取height或width作为其大小衡量本身都可以。
缩放
首先以star的height作为衡量,那么在标准坐标系进行转换后可以认为star是具备一个默认的缩放系数的:就是它的高度AD(或AC)线段的垂直距离。
之后要为star设置新的高度时(也就是改变其大小范围——外接矩形边框outerRect),根据高度的变化进行乘除运算即可——要注意的是坐标问题,这个留给写代码时思考。
Android自定义评分控件:RatingStarView的更多相关文章
- Android自定义日历控件(继承系统控件实现)
Android自定义日历控件(继承系统控件实现) 主要步骤 编写布局 继承LinearLayout设置子控件 设置数据 继承TextView实现有圆圈背景的TextView 添加Attribute 添 ...
- Android星星评分控件RatingBar的使用
在Android的开发中,有一个叫做评分控件RatingBar,我们可以使用该控件做等级划分.评分等作用,星星形状显示,也可以半星级别,我们来看一下评分控件如何使用. 布局文件中定义控件以及属性,这里 ...
- android自定义倒计时控件示例
这篇文章主要介绍了Android秒杀倒计时自定义TextView示例,大家参考使用吧 自定义TextView控件TimeTextView代码: 复制代码 代码如下: import android.co ...
- Android自定义组合控件详细示例 (附完整源码)
在我们平时的Android开发中,有时候原生的控件无法满足我们的需求,或者经常用到几个控件组合在一起来使用.这个时候,我们就可以根据自己的需求创建自定义的控件了,一般通过继承View或其子类来实现. ...
- 014 Android 自定义组合控件
1.需求介绍 将已经编写好的布局文件,抽取到一个类中去做管理,下次还需要使用类似布局时,直接使用该组合控件的对象. 优点:可复用. 例如要重复利用以下布局: <RelativeLayout an ...
- Android自定义用户控件简单范例(二)
对于完全由后台定制的控件,并不是很方便其他人的使用,因为我们常常需要看到控件放到xml界面上的效果,并根据效果进行布局的调整,这就需要一个更加标准的控件制作流程: 我们的自定义控件和其他的控件一样,应 ...
- (转)android自定义组合控件
原文地址:http://mypyg.iteye.com/blog/968646 目标:实现textview和ImageButton组合,可以通过Xml设置自定义控件的属性. 1.控件布局:以Linea ...
- android 自定义组合控件 顶部导航栏
在软件开发过程中,经常见到,就是APP 的标题栏样式几乎都是一样的,只是文字不同而已,两边图标不同.为了减少重复代码,提高效率, 方便大家使用,我们把标题栏通过组合的方式定义成一个控件. 例下图: 点 ...
- Android自定义view控件
转载自: http://blog.163.com/ppy2790@126/blog/static/103242241201382210910473/ 开发自定义控件的步骤: 1.了解View的工作原理 ...
随机推荐
- Struts2的validator和WEB-INF下页面交互以及路径问题
当我使用短路校验器时(客户端),在页面下方老是出来 FreeMarker template error!然后我就把我的页面都放在了WEB-INF中,结果很多路径都不对了,因为客户端是没有直接访问Str ...
- iOS开发之延时执行
方法1: performSelector(SEL) withObjects:(id) afterDelay:(NSTimeInterval); 方法2: dispatch_after(dispatch ...
- css gray,grayscale,css变灰兼容大部分浏览器
css gray,grayscale,css变灰兼容大部分浏览器 html { filter: url("data:image/svg+xml;utf8,<svg xmlns=\'ht ...
- 常见排序算法-Python实现
常见排序算法-Python实现 python 排序 算法 1.二分法 python 32行 right = length- : ] ): test_list = [,,,,,, ...
- python服务器环境搭建(3)——参数配置
前面我们已安装好了python服务器运行所需要的相关软件,而最重要最繁琐的就是参数配置,写这篇就踩了好多坑,花了好多时间,遇到了各种各样的问题.好了费话少说,直接进入本篇话题. PS:本人不是专业的运 ...
- java 8 Hashmap深入解析 —— put get 方法源码
每个java程序员都知道,HashMap是java中最重要的集合类之一,也是找工作面试中非常常见的考点,因为HashMap的实现本身确实蕴含了很多精妙的代码设计. 对于普通的程序员,可能仅仅能说出Ha ...
- Object-C定时器,封装GCD定时器的必要性!!! (一)
实际项目开发中经常会遇到延迟某件任务的执行,或者让某件任务周期性的执行.然后也会在某些时候需要取消掉之前延迟执行的任务. iOS中延迟操作有三种解决方案: 1.NSObject的方法:(对象方法) p ...
- 【Egret】Wing3发布移动APP功能,打包APK流程以及会遇到的问题
流程:1.安装好wing 3,然后 插件--Egret项目工具--发布移动APP--Build android native project 2.配置发布环境: Android 1.egret eng ...
- 《JavaScript程序设计》第2课:JS类型系统
JS类型系统可以分为标准类型和对象类型,进一步标准类型又可以分为原始类型和引用类型,而对象类型又可以分为内置对象类型.普通对象类型.自定义对象类型. 1. 标准类型 标准类型共包括了6个分别是:und ...
- AngularJS1.X学习笔记3-内置模板指令
前面学习了数据绑定指令,现在开始学习内置模板指令.看起来有点多,目测比较好理解.OK!开始! 一.ng-repeat 1.基本用法 <!DOCTYPE html> <html lan ...