现在系统已经提供了评分控件,所以我建议还是用系统比较好。我在这里自定义,只是加深对自定义控件的理解,有助于自我提升。
1.还是老套路,自定义属性
需要两张图片资源
<declare-styleable name="RatingBar">
<attr name="starNormal" format="reference"/>
<attr name="starFocus" format="reference"/>
<attr name="gradeNumber" format="integer"/>
</declare-styleable >
创建RatingBar
public class RatingBar extends View {
private Bitmap mStarNormalBitmap, mStarFocusBitmap;
private int mGradeNumber = 5;
public RatingBar(Context context) {
this(context, null);
}
public RatingBar(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public RatingBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RatingBar);
int starNormalId = array.getResourceId(R.styleable.RatingBar_starNormal, 0);
if (starNormalId == 0) {
throw new RuntimeException("请设置属性 starNormal ");
}
mStarNormalBitmap = BitmapFactory.decodeResource(getResources(), starNormalId);
int starFocusId = array.getResourceId(R.styleable.RatingBar_starFocus, 0);
if (starFocusId == 0) {
throw new RuntimeException("请设置属性 starFocus ");
}
mStarFocusBitmap = BitmapFactory.decodeResource(getResources(), starFocusId);
mGradeNumber = array.getInt(R.styleable.RatingBar_gradeNumber, mGradeNumber);
}
2.测量方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height = mStarFocusBitmap.getHeight();
int width = mStarFocusBitmap.getWidth() * mGradeNumber+getPaddingLeft()+getPaddingRight();
setMeasuredDimension(width, height);
}
3.绘制
@Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < mGradeNumber; i++) {
// i*星星的宽度
int x= i * mStarFocusBitmap.getWidth();;
// 结合第二个步骤 触摸的时候mCurrentGrade值是不断变化
if(mCurrentGrade>i){// 1 01
// 当前分数之前
canvas.drawBitmap(mStarFocusBitmap, x, 0, null);
}else{
canvas.drawBitmap(mStarNormalBitmap, x, 0, null);
}
}
}
4.触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
// 移动 按下 抬起 处理逻辑都是一样,判断手指的位置,根据当前位置计算出分数,再去刷新显示
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: // 移动
float moveX = event.getX();//event.getX()相对于当前控件的位置 event.getRawX()获取幕的x位置
// 计算分数
int currentGrade = (int) (moveX/mStarFocusBitmap.getWidth()+1);
// 范围问题
if(currentGrade<0){
currentGrade = 0;
}
if(currentGrade>mGradeNumber){
currentGrade = mGradeNumber;
}
// 分数相同的情况下不要绘制了 , 尽量减少onDraw()的调用
if(currentGrade == mCurrentGrade){
return true;
}
// 再去刷新显示
mCurrentGrade = currentGrade;
invalidate();
break;
}
return true;
}