Android 自定义 简单的RatingBar

1.效果展示

image.png

image.png

2.效果实现分析

2.1 简单实现,需要两张图片,一张灰色星星,一张黄色星星
2.2 首先绘制五张灰色背景星星,然后重写onTouchEvent()方法,当用户与屏幕进行交互时,在执行MOVE,UP,DOWN时,根据用户手指所在位置距离,算出应对对应几个黄色星星,然后重新绘制。

3.代码实现

3.1 创建CMRatingBarView类,继承至View类
 public class CMRatingBarView extends View {
  private Bitmap cmRatingNormalBitmap, cmRatingFocusBitmap;
  //个数
  private int cmRatingGradeNumber = 5;

  private int cmRatingCurrentNumber = 0;


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

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

  public CMRatingBarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
      super(context, attrs, defStyleAttr);
  }
}
3.2 在values目录下的attrs.xml文件中自定义RatingBar的属性
  
    
    
    

3.3 在布局文件中引用
         
3.4 在CMRatingBar的构造方法中获取自定义的属性
      //获取自定义属性
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CMRatingBarView);

    cmRatingGradeNumber = (int) typedArray.getInt(R.styleable.CMRatingBarView_cmRatingBarGradeNumber, cmRatingGradeNumber);

    int cmRatingNormalId = typedArray.getResourceId(R.styleable.CMRatingBarView_cmRatingBarStartNormal, 0);
    int cmRatingFocusId = typedArray.getResourceId(R.styleable.CMRatingBarView_cmRatingBarStartFocus, 0);
    if (0 == cmRatingNormalId) {
        throw new RuntimeException("请设置默认RatingBar图片");
    }
    if (0 == cmRatingFocusId) {
        throw new RuntimeException("请设置选中RatingBar图片");
    }
    cmRatingNormalBitmap = BitmapFactory.decodeResource(getResources(), cmRatingNormalId);
    cmRatingFocusBitmap = BitmapFactory.decodeResource(getResources(), cmRatingFocusId);
    typedArray.recycle();
3.4 重写onMeasure()方法,从新设置view的宽高
  @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int width = MeasureSpec.getSize(widthMeasureSpec);
    int heigth = MeasureSpec.getSize(heightMeasureSpec);

    width = getPaddingLeft() + (cmRatingNormalBitmap.getWidth() + getPaddingRight()) * cmRatingGradeNumber;
    heigth = cmRatingNormalBitmap.getHeight() + getPaddingTop() + getPaddingBottom();

    setMeasuredDimension(width, heigth);

}
3.5 重写onDray()方法,重新绘制RatingBar
 @Override
protected void onDraw(Canvas canvas) {
    //直接绘制bitmap

    for (int i = 0; i < cmRatingGradeNumber; i++) {
        int x = (cmRatingNormalBitmap.getWidth() + getPaddingRight()) * i;

        if(i < cmRatingCurrentNumber){
            canvas.drawBitmap(cmRatingFocusBitmap, getPaddingLeft() + x, getPaddingTop(), null);
        }else{
            canvas.drawBitmap(cmRatingNormalBitmap, getPaddingLeft() + x, getPaddingTop(), null);
        }
    }
}

cmRatingGradeNumber 是自定义的总的星星数量
cmRatingCurrentNumber是用户选中的星星的数量

3.6 重写onTouchEvent()方法,处理UP,MOVE,DOWN事件
@Override
public boolean onTouchEvent(MotionEvent event) {

    switch (event.getAction()) {

        case MotionEvent.ACTION_MOVE:

            //1.获取手指当前的位置,除以整个的宽度,然后再去画RatingBar
            float cmCurrentWidth = event.getX();
            int cmCurrentNumber = (int) (cmCurrentWidth / cmRatingNormalBitmap.getWidth() + 1);

            Log.e("CMRatingBar 个数",cmCurrentNumber+"个,event.getX()= "+event.getX()+" ! cmRatingNormalBitmap.getWidth() + 1 = "+cmRatingNormalBitmap.getWidth() + 1);

            if(cmCurrentNumber < 0){
                cmCurrentNumber = 0;
            }

            if(cmCurrentNumber > cmRatingGradeNumber){
                cmCurrentNumber= cmRatingGradeNumber;
            }

            if(cmCurrentNumber == cmRatingCurrentNumber){
                return true;
            }



            cmRatingCurrentNumber = cmCurrentNumber;
            invalidate();

            break;
    }

    return true;
}

4 GitHub

Demo 地址 https://github.com/hualianrensheng/CMViewDemo

你可能感兴趣的:(Android 自定义 简单的RatingBar)