自定义RatingBar评分控件

1.介绍

实现类似美团外卖评分供能,系统提供了RatingBar,今天来自定义一波,当做自定义view的一个学习,效果如下,能够滑动或者点击变化星星数量
image.png

2.自定义属性

在values目录下的attrs.xml创建所需要的属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyRatingView">
        <attr name="normalRatingBar" format="reference" />
        <attr name="selectRatingBar" format="reference" />
        <attr name="ratingNum" format="integer" />
        <attr name="bothPadding" format="dimension" />
    </declare-styleable>
</resources>
3.自定义View如下
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.cyq.customview2.R;

/**
 * 自定义评分控件
 */
public class MyRatingView extends View {
    private Bitmap mNormalRatingBar, mSelectRatingBar;
    private int mGrateNumber = 5;
    private int mBothPadding = 5;//默认星星之间间隔为5dp
    private int mCurrentNumber = 0, mSelectNumber = 0;

    public MyRatingView(Context context) {
        this(context, null);
    }

    public MyRatingView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyRatingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyRatingView);

        int mNormalBitmapId = array.getResourceId(R.styleable.MyRatingView_normalRatingBar, 0);
        if (mNormalBitmapId == 0) {
            throw new RuntimeException("未设置属性");
        }
        mNormalRatingBar = BitmapFactory.decodeResource(getResources(), mNormalBitmapId);

        int mSelectBitmapId = array.getResourceId(R.styleable.MyRatingView_selectRatingBar, 0);
        if (mSelectBitmapId == 0) {
            throw new RuntimeException("未设置属性");
        }
        mSelectRatingBar = BitmapFactory.decodeResource(getResources(), mSelectBitmapId);

        mGrateNumber = array.getInt(R.styleable.MyRatingView_ratingNum, mGrateNumber);
        mBothPadding = array.getDimensionPixelSize(R.styleable.MyRatingView_bothPadding, 5);

        array.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int height = mNormalRatingBar.getHeight() + getPaddingTop() + getPaddingBottom();
        int width = mGrateNumber * mNormalRatingBar.getWidth()
                + mBothPadding * (mGrateNumber - 1)
                + getPaddingLeft()
                + getPaddingRight();//暂时还没有设置间隔UP
        //设置测量维度
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        for (int i = 0; i < mGrateNumber; i++) {
            int x = (mNormalRatingBar.getWidth() + mBothPadding) * i + getPaddingLeft();
            int y = getPaddingTop();
            canvas.drawBitmap(mNormalRatingBar, x, y, null);
        }

        for (int i = 0; i < mSelectNumber; i++) {
            int x = (mSelectRatingBar.getWidth() + mBothPadding) * i + getPaddingLeft();
            int y = getPaddingTop();
            canvas.drawBitmap(mSelectRatingBar, x, y, null);
        }

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
                float moveX = event.getX();
                mCurrentNumber = (int) ((moveX - getPaddingLeft()) / (mNormalRatingBar.getWidth() + mBothPadding));
                if (mCurrentNumber < 0)
                    mCurrentNumber = 0;
                if (mCurrentNumber > 0)
                    mCurrentNumber += 1;
                //避免星星数量没变化时重复调用onDraw方法
                if (mCurrentNumber != mSelectNumber) {
                    mSelectNumber = mCurrentNumber;
                    invalidate();
                }
        }
        return true;
    }

    /**
     * 返回评分等级
     *
     * @return
     */
    public int getSelectNumber() {
        return mSelectNumber;
    }
}
XML中使用
 <com.cyq.customview2.page6.MyRatingView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:padding="10dp"
        app:bothPadding="10dp"
        app:normalRatingBar="@drawable/rating_normal_bar"
        app:ratingNum="5"
        app:selectRatingBar="@drawable/rating_select_bar" />
原文地址:https://www.cnblogs.com/chenyangqi/p/9512761.html