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的更多相关文章

  1. Android自定义日历控件(继承系统控件实现)

    Android自定义日历控件(继承系统控件实现) 主要步骤 编写布局 继承LinearLayout设置子控件 设置数据 继承TextView实现有圆圈背景的TextView 添加Attribute 添 ...

  2. Android星星评分控件RatingBar的使用

    在Android的开发中,有一个叫做评分控件RatingBar,我们可以使用该控件做等级划分.评分等作用,星星形状显示,也可以半星级别,我们来看一下评分控件如何使用. 布局文件中定义控件以及属性,这里 ...

  3. android自定义倒计时控件示例

    这篇文章主要介绍了Android秒杀倒计时自定义TextView示例,大家参考使用吧 自定义TextView控件TimeTextView代码: 复制代码 代码如下: import android.co ...

  4. Android自定义组合控件详细示例 (附完整源码)

    在我们平时的Android开发中,有时候原生的控件无法满足我们的需求,或者经常用到几个控件组合在一起来使用.这个时候,我们就可以根据自己的需求创建自定义的控件了,一般通过继承View或其子类来实现. ...

  5. 014 Android 自定义组合控件

    1.需求介绍 将已经编写好的布局文件,抽取到一个类中去做管理,下次还需要使用类似布局时,直接使用该组合控件的对象. 优点:可复用. 例如要重复利用以下布局: <RelativeLayout an ...

  6. Android自定义用户控件简单范例(二)

    对于完全由后台定制的控件,并不是很方便其他人的使用,因为我们常常需要看到控件放到xml界面上的效果,并根据效果进行布局的调整,这就需要一个更加标准的控件制作流程: 我们的自定义控件和其他的控件一样,应 ...

  7. (转)android自定义组合控件

    原文地址:http://mypyg.iteye.com/blog/968646 目标:实现textview和ImageButton组合,可以通过Xml设置自定义控件的属性. 1.控件布局:以Linea ...

  8. android 自定义组合控件 顶部导航栏

    在软件开发过程中,经常见到,就是APP 的标题栏样式几乎都是一样的,只是文字不同而已,两边图标不同.为了减少重复代码,提高效率, 方便大家使用,我们把标题栏通过组合的方式定义成一个控件. 例下图: 点 ...

  9. Android自定义view控件

    转载自: http://blog.163.com/ppy2790@126/blog/static/103242241201382210910473/ 开发自定义控件的步骤: 1.了解View的工作原理 ...

随机推荐

  1. Struts2的validator和WEB-INF下页面交互以及路径问题

    当我使用短路校验器时(客户端),在页面下方老是出来 FreeMarker template error!然后我就把我的页面都放在了WEB-INF中,结果很多路径都不对了,因为客户端是没有直接访问Str ...

  2. iOS开发之延时执行

    方法1: performSelector(SEL) withObjects:(id) afterDelay:(NSTimeInterval); 方法2: dispatch_after(dispatch ...

  3. css gray,grayscale,css变灰兼容大部分浏览器

    css gray,grayscale,css变灰兼容大部分浏览器 html { filter: url("data:image/svg+xml;utf8,<svg xmlns=\'ht ...

  4. 常见排序算法-Python实现

    常见排序算法-Python实现 python 排序 算法 1.二分法     python    32行 right = length-  :  ]   ):  test_list = [,,,,,, ...

  5. python服务器环境搭建(3)——参数配置

    前面我们已安装好了python服务器运行所需要的相关软件,而最重要最繁琐的就是参数配置,写这篇就踩了好多坑,花了好多时间,遇到了各种各样的问题.好了费话少说,直接进入本篇话题. PS:本人不是专业的运 ...

  6. java 8 Hashmap深入解析 —— put get 方法源码

    每个java程序员都知道,HashMap是java中最重要的集合类之一,也是找工作面试中非常常见的考点,因为HashMap的实现本身确实蕴含了很多精妙的代码设计. 对于普通的程序员,可能仅仅能说出Ha ...

  7. Object-C定时器,封装GCD定时器的必要性!!! (一)

    实际项目开发中经常会遇到延迟某件任务的执行,或者让某件任务周期性的执行.然后也会在某些时候需要取消掉之前延迟执行的任务. iOS中延迟操作有三种解决方案: 1.NSObject的方法:(对象方法) p ...

  8. 【Egret】Wing3发布移动APP功能,打包APK流程以及会遇到的问题

    流程:1.安装好wing 3,然后 插件--Egret项目工具--发布移动APP--Build android native project 2.配置发布环境: Android 1.egret eng ...

  9. 《JavaScript程序设计》第2课:JS类型系统

    JS类型系统可以分为标准类型和对象类型,进一步标准类型又可以分为原始类型和引用类型,而对象类型又可以分为内置对象类型.普通对象类型.自定义对象类型. 1. 标准类型 标准类型共包括了6个分别是:und ...

  10. AngularJS1.X学习笔记3-内置模板指令

    前面学习了数据绑定指令,现在开始学习内置模板指令.看起来有点多,目测比较好理解.OK!开始! 一.ng-repeat 1.基本用法 <!DOCTYPE html> <html lan ...