android github 评分控件_GitHub - wolongalick/PercentRatingBar: 百分比评分控件

news/2024/7/16 8:00:33

PercentRatingBar

百分比评分控件

依赖方式

buildscript {

repositories {

google()

jcenter()

}

}

dependencies {

implementation 'com.wolongalick.widget:PercentRatingBar:1.0.1'

}

快速使用

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

完整使用

android:layout_width="wrap_content"

android:layout_height="wrap_content"

app:ratingSelectedImg="@drawable/selected_star"

app:ratingNotSelectImg="@drawable/not_select_star"

app:ratingSelectedScore="3.7"

app:ratingTotalScore="10"

app:ratingPadding="2dp"

app:ratingIsSupportDrag="true"

app:ratingStep="exactly" />

自定义属性详解

属性名

含义

对应java/kotlin方法

ratingSelectedImg

选中的星星图片资源id

setImageRes(Int, Int)

ratingNotSelectImg

未选中的星星图片资源id

setImageRes(Int, Int)

ratingSelectedScore

选中的星星个数评分(支持小数)

setScore(Float)和getScore()

ratingTotalScore

总分数

setTotalScore(Int)和getTotalScore()

ratingPadding

星星之间的间距,单位px

setRatingPadding(Int)

ratingIsSupportDrag

是否支持拖动

setRatingIsSupportDrag(Boolean)和getRatingIsSupportDrag()

ratingStep

星星步长(full:整颗星、half:半颗星、exactly:精确到具体刻度比例)

setStep(@RatingStep step: Int)

前言

公司的产品需要一个评分控件,并且分数并不仅仅是1.5、2.5这样的,而是要支持1.1、1.9分,并且星星的评分样式也要与分值完全对应

也就是要实现这种效果

我一听就懵逼了,这不是为难我么

不过既然产品既然提了需求,咱也得尽量去实现,否则以后还怎么愉快玩耍

需求描述

支持整颗星、半颗星和按百分比评分

支持滑动和点击评分

支持自定义星星图标和星星间距

支持...好了闭嘴吧...咱都给你实现了

需求分析

首先绘制星星很简单,调用canvas.drawBitmap就可以,多个星星for循环绘制即可

复杂的地方有两处:a.如何绘制残缺星星,b:如果在滑动时,将滑动位置转化为分数

开始写demo

我们先画一颗星看看效果

不过没关系,我们可以换个改为在onMeasure中获取bitmap,并将其作为全局变量存起来(因为要计算星星的宽高以及整体自定义view宽高,所以本身也是需要在onMeasure中写的)

再来绘制五颗星

好,一颗星我们画完了,那么5颗星就for循环呗

override fun onDraw(canvas: Canvas) {

super.onDraw(canvas)

val paint = Paint(Paint.ANTI_ALIAS_FLAG)

//绘制底部灰色星(未选中的)

for (i in 0 until 5) {

canvas.drawBitmap(

staredBitmap,

i * mStarImgWidth.toFloat(),//这里要记得每颗星星要向右偏移,否则5颗星星就重合了

0f,

paint

)

}

}

效果图

绘制背景的5颗灰色的星星也是一样的思路,只是需要先绘制5颗灰色星星,再绘制N颗黄色星星,代码就不贴了

问题来了

但产品要求评分要精确到小数,所以问题来了,当分数为2.7,那么那0.7分的残缺星星该怎么画呢

此时需要用到一个方法:canvas.clipRect(int left, int top, int right, int bottom),该方法是用来裁剪绘制区域的,具体用法我就不赘述了,大家参考这篇博客吧,作者讲得还挺详细的https://www.jianshu.com/p/550d85419121

绘制残缺星星的代码

override fun onDraw(canvas: Canvas) {

super.onDraw(canvas)

val paint = Paint(Paint.ANTI_ALIAS_FLAG)

val fractional = 0.7f

//裁剪半颗星

canvas.clipRect(0, 0, (mStarImgWidth*fractional).toInt(), staredBitmap.height)

canvas.drawBitmap(staredBitmap, left.toFloat(), 0f, paint)

}

效果图

哈哈,到此你们肯定就能够实现如何绘制2.7分的评分了,无非就是以下三步

绘制5颗灰色星星

绘制2颗黄色星星

绘制1颗裁剪0.7倍的黄色星星

在源码中有一处小小的优化,就是灰色星星不用绘制5颗,只需要绘制黄色星星没覆盖的地方,避免浪费

具体代码如下:

好了,现在贴一下目前的代码和效果图

val totalScore=5 //总分写死为5分

val score=2.7f //评分写死为2.7分

override fun onDraw(canvas: Canvas) {

super.onDraw(canvas)

val paint = Paint(Paint.ANTI_ALIAS_FLAG)

//绘制底部灰色星(未选中的)

for (i in score.toInt() until totalScore) {

canvas.drawBitmap(

notStarBitmap, i * (mStarImgWidth.toFloat()), 0f, paint

)

}

val fractional = score-score.toInt()//2.7分:代表残缺星星的评分

//绘制黄色星(选中的整颗星)

for (i in 0 until score.toInt()) {

canvas.drawBitmap(

staredBitmap, i * (mStarImgWidth.toFloat()), 0f, paint

)

}

//计算绘制的左侧位置和右侧位置

val left =

paddingStart + score.toInt() * (mStarImgWidth.toFloat()).toInt()

val right = left + (mStarImgWidth * fractional).toInt()

//裁剪半颗星

canvas.clipRect(left, 0, right, staredBitmap.height)

canvas.drawBitmap(staredBitmap, left.toFloat(), 0f, paint)

}

效果图

实现滑动评分效果

在看代码之前先看一张说明图

解释:

paddingStart:就是官方的android:paddingStart属性,代表左边距

mStarImgWidth:星星的宽度

mRatingPadding:两颗星星的左右间距

mStarImgWidth加mRatingPadding作为一个整体,我将其称为:控件块,代码中的变量名叫做:chunkWidth,(起名字真是个麻烦的事情)

具体逻辑代码

override fun onTouchEvent(event: MotionEvent): Boolean {

if (!mIsSupportDrag) {

return super.onTouchEvent(event)

}

//将星星和间距作为一组控件块

val chunkWidth = mStarImgWidth + mRatingPadding

//计算出包含多少个控件块,也就是占多少颗星,多少分

var newCount = ((event.x - paddingStart.toFloat()) / chunkWidth)

//计算出多滑出的百分比(一组控件块的)

val starPaddingPercent: Float = (newCount - newCount.toInt())

//计算出多滑出的百分比(一颗星的)

var starPercent: Float = chunkWidth * starPaddingPercent / mStarImgWidth

//将一颗星的百分比强制限制到1也就是100%

if (starPercent > 1) {

starPercent = 1f

}

//加上滑出的百分比,得出新的分数

newCount = newCount.toInt() + starPercent

//最后根据步长类型,调整分数

newCount = adjustRatingSelectedCount(newCount)

if (mSelectedCount != newCount) {

onRatingChangeListener(newCount)

}

mSelectedCount = newCount

invalidate()

return true

}

算法讲解

what?算法讲解是不可能讲解的,这辈子都不可能讲解(主要是我表达能力有限,容易让你们失去阅读兴趣,干扰你们思路~)


http://www.niftyadmin.cn/n/2828922.html

相关文章

64位win2008下IIS未开启32位支持导致DLL无法加载问题

部署一个WEB项目,在本机、本地服务器都没有问题,但部署到远程服务器以后,提示有个DLL无法加载:Server Error in / Application.Could not load file or assembly Common.Component.Repository or one of its dependencies. An att…

SparkSQL DataFrames操作

Hive中已经存在emp和dept表: select * from emp; ---------------------------------------------------------------------------- | empno | ename | job | mgr | hiredate | sal | comm | deptno | ------------------------------------…

Brackets 小技巧 | IDE

在HTML里编辑CSS 在HTML文件里,鼠标放到一个要编辑样式的标签上,快捷键CTL E,就可以编辑样式。同样,也可以通过双击HTML元素编辑。 开启DevTool cmd opt I 即可打开自带的开发者工具 实时预览 Brackets支持两种预览方式&#x…

EBS FORM开发步骤

EBS FORM开发步骤(step by step)转载于:https://blog.51cto.com/9966064/1616954

瓦瑟纳尔新规将冲击漏洞市场

本文讲的是瓦瑟纳尔新规将冲击漏洞市场,漏洞奖励已不算是非常新鲜的事物,并渐渐发展成为平常之需。不仅公司企业希望能够从奉公守法的漏洞挖掘人员那里获取信息,找到自身的弱点,另一方面也是大量独立研究人员从厂商和第三方漏洞奖…

GitHub 开官微了,怎么看

北京时间 2015 年 2 月 27 日世界上最大的同性交友网站 GitHub 正式登陆新浪微博,短短几日的功夫,粉丝数量也上万了。作为仅仅针对程序员这么“小众”的群体的一个网站,这个成绩足以说明 GitHub 在中国程序员心中的地位。 GitHub 早在 2012 年…

Horizon View 6.0 基于RDS的应用发布

最近测试VMware Horizon View6.0 新产品,相比较之前版本还是有许多改善,在应用发布这块通过RDS主机实现发布,通过View Client 链接即可显示所发布的应用。本着学习的心态将自己所了解的写出来,如有不足还请各位赐教。Horizon view…

18.1 集群介绍;18.2 keepalived介绍;18.3,18.4,18.5 用keepalived配置高可用集群(上,中,下);...

18.1 集群介绍1. 根据功能划分为两大类:高可用和负载均衡2. 高可用集群通常为两台服务器,一台工作,另外一台作为冗余,当提供服务的机器宕机,冗余将接替继续提供服务3. 实现高可用的开源软件有:heartbeat、k…