自定义 view 练手 - 自定义 ratingBar

话说我们终于来到了真正的自定义 view 环节了,用 canvas 来绘制我们想要的一切了。开始嘛,总要有点不一样的,咱们的开始从 自定义 ratingBar 开始,系统的 ratingBar 那是一个蛋星星疼啊,不能调整星星大小,要是替换星星图片资源的话,还容易出问题,不是星星显示不全就是下面长脚了 ~

所以 自定义 ratingBar 是非常有显示意义的,ratingBar 说难不难,说简单也不简单,对于初学者练手及其具有重要意义,通过 自定义 ratingBar 我们可以熟悉 自定义 view 中所有的代码细节,写完我们自己的 ratingBar 后,自定义 view 对于我们来说就不算陌生了。

这是我写的:


自定义 view 练手 - 自定义 ratingBar_第1张图片
ezgif.com-video-to-gif.gif

第一个星星的黑框不要在意,只是表示图片的尺寸范围,项目种已经去掉了。这个 ratingBar 打磨的差不多了,大家可以直接复制过去用滴 ~

项目地址:BW_Libs

我用的是矢量图,矢量图在 4.x 上的兼容太是个问题了,具体请看:

  • android图片系列 (2) - 静态 SVG 图片

项目思路


ratingBar 的思路并不难,就是根据数量画星星,星星一般都是图片,区别是 png 还是矢量图,当然也可以不用图全程用 path 画,但是我是没找到画星星的 paht 路径出来,有心无力啊

我这里的 ratingBar 星星可以调节大小,默认我给了个 24dp,大家在使用时高自适应就行,高根据设置的星星大小走,为了图省事,星星都是正方形的哦

自定义参数没几个,如下:

    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    

基本仿照系统原生的 ratingbar ,但是添加了星星尺寸和间距。图片方面因为要支持半星所以有3种图:全星,半星,没星

绘制上也是简单的很,canvas 每绘制一张图,canvas 位移指定宽度

selectDrawable.draw(canvas)
canvas?.translate((startSize + startSetp).toFloat(), 0f)

ratingBar 中最有难度的就是区分星星是全的还是半的还是没有的了,我是利用一个集合存储每个星星的显示状态,根据设置的评分数,计算全星,半星,没星的分界点,我这里主要有小数就算半星

对评分数取整,评分数要是大于取整的数,那说明有小数,就有半星,那么分界点就是这个取整之后的整数了,然后往星星显示状态的集合里写入相应个数的数据就行

    fun cauculateStartState() {

        startInfoList.clear()

        if (currentStartCount == 0f) {
            (1..maxStartCount).forEach { startInfoList.add(STATE_UNSELECT) }
            return
        }

        var index: Int = currentStartCount.toInt()
        if (index >= 1) (1..index).forEach { startInfoList.add(STATE_SELECT) }

        // 说明有小数位
        if (currentStartCount > index) {
            startInfoList.add(STATE_HALF)
            index += 2
        } else {
            index++
        }

        if (maxStartCount >= index) {
            (index..maxStartCount).forEach { startInfoList.add(STATE_UNSELECT) }
        }
    }

触摸的话也不难,用触摸点的 x 坐标 / 星星大小+分割大小,分析得到 float 值,根据小数位范围判断是全星还是半星

    override fun onTouchEvent(event: MotionEvent?): Boolean {

        if (!canTouch) return false

        if (event?.action == MotionEvent.ACTION_DOWN) {

            if (event.x >= width) {
                setRating(maxStartCount.toFloat())
                return true
            }

            var index_float: Float = event.x / (startSize + startSetp)
            var index_int: Int = index_float.toInt()

            if (index_float <= (index_int + 0.3f)) {
                setRating(index_int.toFloat())
                return true
            }

            if (index_float > (index_int + 0.3f) && index_float < (index_int + 0.7f)) {
                setRating(index_int + 0.5f)
                return true
            }

            if (index_float >= (index_int + 0.7f)) {
                setRating((index_int + 1).toFloat())
                return true
            }
        }

        return true
    }

你可能感兴趣的:(自定义 view 练手 - 自定义 ratingBar)