虽然android已经有一个评分控件了,貌似应该就叫做RantingBar吧,具体也记不太清楚了,下面我们来自定义一个评分控件!
先来上个效果图吧!
下面,我们来看一下自定义这个评分控件的步骤吧
1:看需求:首先,从上图可知,需要自定义的属性有五角星的个数,为评分时的五角星图片,评分后的五角星个数,五角星和五角星之间的距离。
2:自定义属性:
<declare-styleable name="CustomRatingBar">
<!-- reference为引用类型 -->
<attr name="originStar" format="reference"/>
<attr name="focusStar" format="reference"/>
<attr name="starNumber" format="integer"/>
<attr name="starInterval" format="dimension"/>
</declare-styleable>
3:在布局文件中引用自定义View
4:在自定义View中获取属性,并设置给到相应的效果
public class CustomRatingBar extends View {
private Bitmap mOriginStar,mFocusStar;
private int mStarNumber = 5;
private int mStarInterval = 10;//px
private int mStars = 0;// 评分
public CustomRatingBar(Context context) {
this(context,null);
}
public CustomRatingBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public CustomRatingBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.CustomRatingBar);
//获取默认评分图片的id
int originResourceId = array.getResourceId(R.styleable.CustomRatingBar_originStar,0);
//当id = 0时,代表未设置,则抛出一个异常
if(originResourceId == 0){
throw new RuntimeException("默认星星图片不能为空");
}
mOriginStar = BitmapFactory.decodeResource(getResources(),originResourceId);
int focusResourceId = array.getResourceId(R.styleable.CustomRatingBar_focusStar,0);
if(focusResourceId == 0){
throw new RuntimeException("选中星星图片不能为空");
}
mFocusStar = BitmapFactory.decodeResource(getResources(),focusResourceId);
//评分星星个数 默认为5个
mStarNumber = array.getInteger(R.styleable.CustomRatingBar_starNumber,mStarNumber);
//星星之间的间距
mStarInterval = (int) array.getDimension(R.styleable.CustomRatingBar_starInterval,mStarInterval);
array.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if(widthMode == MeasureSpec.EXACTLY || heightMode == MeasureSpec.EXACTLY){
throw new RuntimeException("请设置RatingBar的宽度和高度为wrap_content!");
}
int startWidth = mOriginStar.getWidth();
int width = startWidth * mStarNumber + mStarInterval * (mStarNumber-1);
setMeasuredDimension(width,mOriginStar.getHeight());
}
@Override
protected void onDraw(Canvas canvas) {
for(int i = 0;i<mStarNumber;i++){
int x = mOriginStar.getWidth() * i + mStarInterval * i;
if(i<mStars){
canvas.drawBitmap(mFocusStar,x,0,null);
}else{
canvas.drawBitmap(mOriginStar,x,0,null);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
int x = (int) event.getX();
int currentStar = x / (mOriginStar.getWidth() + mStarInterval) + 1;
if(currentStar < 0){
currentStar = 0;
}
if( currentStar > mStarNumber){
currentStar = mStarNumber;
}
//当前后两次的的评分是一样的 这不去刷新
if(currentStar == mStars){
return true;
}
mStars = currentStar;
invalidate();
break;
}
return true;
}
}
最后在Activity中引用就好了!