• PercentRatingBar-百分比评分控件


    PercentRatingBar

    百分比评分控件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-floBwSpe-1662473142682)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/079533118d624aa38e65ec73f3febf37~tplv-k3u1fbpfcp-watermark.image)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wHnlN02u-1662473142683)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d7496e3e0b6d4413b09657d03f85921a~tplv-k3u1fbpfcp-watermark.image)]

    前言

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LJ1nqUd2-1662473142684)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/800d1d17602c468f9511cab4ef258428~tplv-k3u1fbpfcp-watermark.image)]

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cXo3Tp8I-1662473142684)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3d114f8615f642f5adbc87bb26513e39~tplv-k3u1fbpfcp-watermark.image)]

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AmnanZSy-1662473142684)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f57e94a5cf7e42478a131bfbc0811fe8~tplv-k3u1fbpfcp-watermark.image)]

    需求描述

    1. 支持整颗星、半颗星和按百分比评分
    2. 支持滑动和点击评分
    3. 支持自定义星星图标和星星间距
    4. 支持…好了闭嘴吧…咱都给你实现了

    需求分析

    1. 首先绘制星星很简单,调用canvas.drawBitmap就可以,多个星星for循环绘制即可
    2. 复杂的地方有两处:a.如何绘制残缺星星,b:如果在滑动时,将滑动位置转化为分数

    开始写demo

    我们先画一颗星看看效果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rvbUJOzd-1662473142685)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d4013f687fbd4237851d37da82b91911~tplv-k3u1fbpfcp-watermark.image)]

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lPSZKqla-1662473142685)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/74a0cf7f13f74434a6faab1d475ef6e8~tplv-k3u1fbpfcp-watermark.image)]

    再来绘制五颗星

    好,一颗星我们画完了,那么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
            )
        }
    }# PercentRatingBar
    百分比评分控件
    
    ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/079533118d624aa38e65ec73f3febf37~tplv-k3u1fbpfcp-watermark.image)
    
    ![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d7496e3e0b6d4413b09657d03f85921a~tplv-k3u1fbpfcp-watermark.image)
    
    # 前言
    公司的产品需要一个评分控件,并且分数并不仅仅是1.52.5这样的,而是要支持1.11.9分,并且星星的评分样式也要与分值完全对应
    也就是要实现这种效果
    
    ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/800d1d17602c468f9511cab4ef258428~tplv-k3u1fbpfcp-watermark.image)
    
    我一听就懵逼了,这不是为难我么
    
    ![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3d114f8615f642f5adbc87bb26513e39~tplv-k3u1fbpfcp-watermark.image)
    
    不过既然产品既然提了需求,咱也得尽量去实现,否则以后还怎么愉快玩耍
    
    ![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f57e94a5cf7e42478a131bfbc0811fe8~tplv-k3u1fbpfcp-watermark.image)
    
    # 需求描述
    1. 支持整颗星、半颗星和按百分比评分
    2. 支持滑动和点击评分
    3. 支持自定义星星图标和星星间距
    4. 支持...好了闭嘴吧...咱都给你实现了
    
    # 需求分析
    1. 首先绘制星星很简单,调用canvas.drawBitmap就可以,多个星星for循环绘制即可
    2. 复杂的地方有两处:a.如何绘制残缺星星,b:如果在滑动时,将滑动位置转化为分数
    
    # 开始写demo
    
    ## 我们先画一颗星看看效果
    ![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d4013f687fbd4237851d37da82b91911~tplv-k3u1fbpfcp-watermark.image)
    
    不过没关系,我们可以换个改为在onMeasure中获取bitmap,并将其作为全局变量存起来(因为要计算星星的宽高以及整体自定义view宽高,所以本身也是需要在onMeasure中写的)
    
    ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/74a0cf7f13f74434a6faab1d475ef6e8~tplv-k3u1fbpfcp-watermark.image)
    
    ## 再来绘制五颗星
    好,一颗星我们画完了,那么5颗星就for循环呗
    ```kotlin
    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
            )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    效果图[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5BvaoUZH-1662473142686)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3b4a093108694e8ba50aadd2cbcd1261~tplv-k3u1fbpfcp-watermark.image)]

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

    问题来了

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j2fXhpQe-1662473142686)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1ce60ab05c4a49e0853cd87ff95a3951~tplv-k3u1fbpfcp-watermark.image)]

    此时需要用到一个方法: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)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    效果图[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BIBFqDPL-1662473142687)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6866e03a54364a3488ca098f13225a55~tplv-k3u1fbpfcp-watermark.image)]

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

    • 绘制5颗灰色星星
    • 绘制2颗黄色星星
    • 绘制1颗裁剪0.7倍的黄色星星

    在源码中有一处小小的优化,就是灰色星星不用绘制5颗,只需要绘制黄色星星没覆盖的地方,避免浪费
    具体代码如下:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PzeBvzDt-1662473142687)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/479872ba110a40e78946d084eefc6223~tplv-k3u1fbpfcp-watermark.image)]

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

    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)
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    效果图[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LZjhajA8-1662473142688)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/287e25ec22d54331a018ea60d9687125~tplv-k3u1fbpfcp-watermark.image)]

    实现滑动评分效果

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cPsKYeBw-1662473142688)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/39117648e26c40498d4938bb01daed63~tplv-k3u1fbpfcp-watermark.image)]
    解释:

    • 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
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    算法讲解

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zoeIOP74-1662473142689)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8b9aafd49efc421ba09a9317cc293844~tplv-k3u1fbpfcp-watermark.image)]

    完整代码

    PercentRatingBar.kt

    /**
     * @createTime 2020/11/9 10:19
     * @author 崔兴旺
     * @description
     */
    class PercentRatingBar : View {
    
        companion object {
            const val TAG: String = "PercentRatingBar"
    
            const val RATING_STEP_FULL = 0                          //整颗星
            const val RATING_STEP_HALF = 1                          //半颗星
            const val RATING_STEP_EXACTLY = 2                       //精确到具体刻度比例
        }
    
        private val defaultRatingTotalCount = 5                     //默认星星总个数为5星
        private var mStarImgWidth = 0                               //星星宽度
        private var mStarImgHeight = 0                              //星星高度
        private var mContext: Context                               //上下文
        private lateinit var staredBitmap: Bitmap                   //选中的星星bitmap
        private lateinit var notStarBitmap: Bitmap                  //未选中的星星bitmap
    
        private var mTotalScore: Int = defaultRatingTotalCount      //总分数
        private var mSelectedCount: Float = 0f                      //评分(支持小数)
        private var mStep: Int = 1                                  //步长(渲染整颗星、半颗星、根据具体滑动比例)
        private var mSelectedImg = 0                                //选中的星星图片资源id
        private var mNotSelectImg = 0                               //未选中的星星图片资源id
        private var mRatingPadding = 0                              //星星之间的间距,单位px
        private var mIsSupportDrag = true                           //是否支持拖动
    
        var onRatingChangeListener = { ratingValue: Float -> Unit }
    
        constructor(context: Context) : super(context) {
            mContext = context
            initView(null)
        }
    
        constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
            mContext = context
            initView(attrs)
        }
    
        constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
            context, attrs, defStyleAttr
        ) {
            mContext = context
            initView(attrs)
        }
    
        private fun initView(attrs: AttributeSet?) {
            val array = context.obtainStyledAttributes(attrs, R.styleable.PercentRatingBar)
            mSelectedImg = array.getResourceId(
                R.styleable.PercentRatingBar_ratingSelectedImg, R.drawable.selected_star
            )
            mNotSelectImg = array.getResourceId(
                R.styleable.PercentRatingBar_ratingNotSelectImg, R.drawable.not_select_star
            )
            mTotalScore =
                array.getInteger(R.styleable.PercentRatingBar_ratingTotalScore, defaultRatingTotalCount)
            mSelectedCount = array.getFloat(R.styleable.PercentRatingBar_ratingSelectedScore, 0f)
            mRatingPadding = array.getDimensionPixelSize(R.styleable.PercentRatingBar_ratingPadding, 0)
            mStep = array.getInteger(R.styleable.PercentRatingBar_ratingStep, RATING_STEP_FULL)
            mIsSupportDrag = array.getBoolean(R.styleable.PercentRatingBar_ratingIsSupportDrag, true)
    
            array.recycle()
        }
    
        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
        }
    
        override fun onDraw(canvas: Canvas) {
            super.onDraw(canvas)
    
            if (mSelectedCount > mTotalScore) {
                //限制评分,最高只能设置为星星总个数
                mSelectedCount = mTotalScore.toFloat()
            }
    
            val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    
            //绘制底部灰色星(未选中的)
            for (i in mSelectedCount.toInt() until mTotalScore) {
                canvas.drawBitmap(
                    notStarBitmap,
                    paddingStart + i * (mStarImgWidth.toFloat() + mRatingPadding),
                    paddingTop.toFloat(),
                    paint
                )
            }
    
            //绘制黄色星(选中的整颗星)
            for (i in 0 until mSelectedCount.toInt()) {
                canvas.drawBitmap(
                    staredBitmap,
                    paddingStart + i * (mStarImgWidth.toFloat() + mRatingPadding),
                    paddingTop.toFloat(),
                    paint
                )
            }
    
            //绘制半颗星
            val fractional = mSelectedCount - mSelectedCount.toInt()
            if (fractional > 0) {
                val left =
                    paddingStart + mSelectedCount.toInt() * (mStarImgWidth.toFloat() + mRatingPadding).toInt()
                val right = left + (mStarImgWidth * fractional).toInt()
                //裁剪半颗星
                canvas.clipRect(left, paddingTop, right, paddingTop + staredBitmap.height)
                canvas.drawBitmap(staredBitmap, left.toFloat(), paddingTop.toFloat(), paint)
            }
        }
    
        /**
         * 调整选中的星星个数
         */
        private fun adjustRatingSelectedCount(ratingSelectedCount: Float): Float {
            var newRatingSelectedCount: Float
            when (mStep) {
                RATING_STEP_FULL -> {
                    newRatingSelectedCount = ratingSelectedCount.roundToInt().toFloat()
                }
                RATING_STEP_HALF -> {
                    var fractional = ratingSelectedCount - ratingSelectedCount.toInt()
                    fractional = if (fractional <= 0.5) {
                        0f
                    } else {
                        0.5f
                    }
                    newRatingSelectedCount = ratingSelectedCount.toInt() + fractional
                }
                RATING_STEP_EXACTLY -> {
                    newRatingSelectedCount = ratingSelectedCount
                }
                else -> {
                    newRatingSelectedCount = ratingSelectedCount.roundToInt().toFloat()
                }
            }
    
            if (newRatingSelectedCount < 0) {
                newRatingSelectedCount = 0f
            } else if (newRatingSelectedCount > mTotalScore) {
                newRatingSelectedCount = mTotalScore.toFloat()
            }
    
            return newRatingSelectedCount
        }
    
        /**
         * 设置总分数
         */
        fun setTotalScore(value: Int) {
            mTotalScore = value
            requestLayout()
            invalidate()
        }
    
        /**
         * 设置分数
         */
        fun setScore(value: Float) {
            val newValue = adjustRatingSelectedCount(value)
            if (mSelectedCount != newValue) {
                onRatingChangeListener(newValue)
            }
            mSelectedCount = newValue
            invalidate()
        }
    
        /**
         * 设置步长
         * @see PercentRatingBar.RATING_STEP_FULL
         * @see PercentRatingBar.RATING_STEP_HALF
         * @see PercentRatingBar.RATING_STEP_EXACTLY
         */
        fun setStep(@RatingStep ratingStep: Int) {
            mStep = ratingStep
            invalidate()
        }
    
        /**
         * 设置星星图片资源id
         */
        fun setImageRes(selectedImg: Int, notSelectImg: Int) {
            mSelectedImg = selectedImg
            mNotSelectImg = notSelectImg
            requestLayout()
            invalidate()
        }
    
        /**
         * 设置星星间距(单位:px)
         */
        fun setRatingPadding(ratingPadding: Int) {
            mRatingPadding = ratingPadding
            requestLayout()
            invalidate()
        }
    
        /**
         * 获取总分数
         */
        fun getTotalScore(): Int {
            return mTotalScore
        }
    
        /**
         * 获取分数
         */
        fun getScore(): Float {
            return mSelectedCount
        }
    
        /**
         * 设置是否支持拖动(默认支持)
         */
        fun setRatingIsSupportDrag(ratingIsSupportDrag: Boolean) {
            mIsSupportDrag = ratingIsSupportDrag
        }
    
        /**
         * 是否支持拖动(默认支持)
         */
        fun getRatingIsSupportDrag(): Boolean {
            return mIsSupportDrag
        }
    
    
        @Override
        override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
            // 获取宽-测量规则的模式和大小
            val widthSize = MeasureSpec.getSize(widthMeasureSpec)
            // 获取高-测量规则的模式和大小
            val heightSize = MeasureSpec.getSize(heightMeasureSpec)
            staredBitmap = BitmapFactory.decodeResource(resources, mSelectedImg)
            notStarBitmap = BitmapFactory.decodeResource(resources, mNotSelectImg)
            mStarImgWidth = staredBitmap.width
            mStarImgHeight = staredBitmap.height
    
            val mWidth =
                mTotalScore * (mStarImgWidth.toFloat() + mRatingPadding).toInt() - mRatingPadding + paddingStart + paddingEnd
            val mHeight = mStarImgHeight + paddingTop + paddingBottom
    
            // 当布局参数设置为wrap_content时,设置默认值
            if (layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT && getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                setMeasuredDimension(mWidth, mHeight)
                // 宽 / 高任意一个布局参数为= wrap_content时,都设置默认值
            } else if (layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
                setMeasuredDimension(mWidth, heightSize)
            } else if (layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                setMeasuredDimension(widthSize, mHeight)
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279

    ratingview_attr.xml

    <resources>
        <declare-styleable name="PercentRatingBar">
            <attr name="ratingSelectedImg" format="reference"/>     
            <attr name="ratingNotSelectImg" format="reference"/>    
            <attr name="ratingSelectedScore" format="float"/>       
            <attr name="ratingTotalScore" format="integer"/>        
            <attr name="ratingPadding" format="dimension"/>         
            <attr name="ratingIsSupportDrag" format="boolean"/>     
            <attr name="ratingStep" format="enum">                  
                <enum name="full" value="0"/>       
                <enum name="half" value="1"/>       
                <enum name="exactly" value="2"/>    
            attr>
        declare-styleable>
    resources>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    github地址,欢迎star

    https://github.com/wolongalick/PercentRatingBar

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jlHcbkv0-1662473142690)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d6ce4e31a4f1468abc8964a3c6e1be2e~tplv-k3u1fbpfcp-watermark.image)]

  • 相关阅读:
    基于STM32设计的云端健康管理系统(采用阿里云物联网平台)
    【从头构筑C#知识体系】2.1 泛型
    paddle 自定义数据集和预处理
    MATLAB | 绘图复刻(四) | 和弦图+颜色修改+标签旋转
    WinUI 剪裁发布中的一个小坑
    【软件测试】测试人冲破瓶颈?5年,你知道我这5年怎么过的吗......
    猿创征文|2022 年我的开发者工具
    【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割10(测试推理篇)
    C++: multiple and virtual inheritance under the hood
    elementUI+springboot实现导入文件到后端并解析excel(进阶)
  • 原文地址:https://blog.csdn.net/razor1991/article/details/126735025