【实际效果图】
1.相关资源:
/**
* 自定义View的几个重要方法步骤:
* 1、构造方法 创建 对象:据使用的那种方式调用那种方法
* 2、获取View的大小 :onMeasure(int,int)
* 3、确定View的位置,view自身有一定的权力,但是决定权在父布局上 : onLayout();
* 4、绘制View的内容:onDraw(Canvas)
*/
//自定义控件---星级评分条(只用于显示,不可拖动)
public class MyRatingBar extends View {
private Paint paint;//画笔
private float rateNum;//当前星级值(0~5)
private int stepSizeType;//步长类型
private Bitmap starYesBitmap;//满星图片
private Bitmap starNoBitmap;//无星图片
private Bitmap starHalfBitmap;//半星图片
//此处的final整数值应该与attr里面的属性枚举值保持一致
public final static int halfStar = 0;//有半星
public final static int fullStar = 1;//无半星
/**
* 在布局文件中使用自定义的view时,调用此构造方法
*/
public MyRatingBar(Context context, AttributeSet attrs) {
super(context, attrs);
//获取自定义属性
TypedArray typeArray = context.obtainStyledAttributes(attrs, R.styleable.MyRatingBar);//获取属性命名空间
rateNum = typeArray.getFloat(R.styleable.MyRatingBar_rateNum, 0);//获取属性值-星级值
stepSizeType = typeArray.getInt(R.styleable.MyRatingBar_stepSizeType, 0);//获取属性值-步长类型
int starYesID = typeArray.getResourceId(R.styleable.MyRatingBar_star_yes, R.drawable.star_yes);
int starNoID = typeArray.getResourceId(R.styleable.MyRatingBar_star_no, R.drawable.star_no);
int starHalfID = typeArray.getResourceId(R.styleable.MyRatingBar_star_half, R.drawable.star_half);
starYesBitmap = BitmapFactory.decodeResource(getResources(), starYesID);
starNoBitmap = BitmapFactory.decodeResource(getResources(), starNoID);
starHalfBitmap = BitmapFactory.decodeResource(getResources(), starHalfID);
initView();
}
/**
* 初始化视图数据
*/
private void initView() {
paint = new Paint();
paint.setAntiAlias(true);//设置抗锯齿
//自定义属性若想属性生效,必须刷新状态
flushState();
}
/**
* 测量View的大小
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(starNoBitmap.getWidth() * 5, starNoBitmap.getHeight() * 1);
}
/**
* 确定View的位置
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
//自定义view的时候,一般来说作用不大,故此处不做任何处理
super.onLayout(changed, left, top, right, bottom);
}
/**
* 绘制View的内容
*/
@Override
protected void onDraw(Canvas canvas) {
int starWidth = starNoBitmap.getWidth();
//无半星
if (stepSizeType == 1) {
int index = (int) (rateNum / 1);
for (int i = 0; i < 5; i++) {
if (i < index) {
canvas.drawBitmap(starYesBitmap, starWidth * i, 0, paint);//设置第i颗星为满星
} else {
canvas.drawBitmap(starNoBitmap, starWidth * i, 0, paint);//设置第i颗星为无星
}
}
}
//有半星
else if (stepSizeType == 0) {
int index = (int) (rateNum / 0.5);
for (int i = 0; i < 5; i++) {
if (i * 2 < index) {
if (i * 2 <= (index - 2)) {
canvas.drawBitmap(starYesBitmap, starWidth * i, 0, paint);//设置第i颗星为满星
} else {
canvas.drawBitmap(starHalfBitmap, starWidth * i, 0, paint);//设置第i颗星为半星
}
} else {
canvas.drawBitmap(starNoBitmap, starWidth * i, 0, paint);//设置第i颗星为无星
}
}
}
}
/**
* 监听手势事件
*
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
/**
* 刷新View的状态
*/
private void flushState() {
//刷新View,因本例子比较简单,所以flushState()没啥用,只是跳到了flushView()而已,不过复杂点的控件的话,还是将刷新状态和刷新视图分开比较好
flushView();
}
/**
* 刷新View的内容
*/
private void flushView() {
//刷新界面,会重新调用onDraw()方法,不在UI线程中刷新界面得使用postInvalidate().
invalidate();
}
public void setRateNum(float rateNum) {
this.rateNum = rateNum;
flushState();
}
public void setStepSizeType(int stepSizeType) {
this.stepSizeType = stepSizeType;
flushState();
}
public void setStarYesBitmap(Bitmap starYesBitmap) {
this.starYesBitmap = starYesBitmap;
flushState();
}
public void setStarNoBitmap(Bitmap starNoBitmap) {
this.starNoBitmap = starNoBitmap;
flushState();
}
public void setStarHalfBitmap(Bitmap starHalfBitmap) {
this.starHalfBitmap = starHalfBitmap;
flushState();
}
}
自定义属性:
<?xml version="1.0" encoding="utf-8"?>图片资源
<resources>
<declare-styleable name="MyRatingBar">
<attr name="rateNum" format="float"/>
<attr name="stepSizeType" >
<enum name="halfStar" value="0" />
<enum name="fullStar" value="1" />
</attr>
<attr name="star_yes" format="reference"/>
<attr name="star_no" format="reference"/>
<attr name="star_half" format="reference"/>
</declare-styleable>
</resources>
2.使用说明:
属性说明:
在XML中设置属性:
在Java中设置属性: