美文网首页
Android 自定义 简单的RatingBar

Android 自定义 简单的RatingBar

作者: 花椒人生 | 来源:发表于2018-01-24 15:24 被阅读0次

    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的属性
      <declare-styleable name="CMRatingBarView">
        <attr name="cmRatingBarStartNormal" format="reference"></attr>
        <attr name="cmRatingBarStartFocus" format="reference"></attr>
        <attr name="cmRatingBarGradeNumber" format="integer"></attr>
    </declare-styleable>
    
    3.3 在布局文件中引用
             <com.test.cmviewdemo.CMRatingBarView
                android:padding="5dp"
                android:background="@color/colorAccent"
                app:cmRatingBarGradeNumber="5"
                app:cmRatingBarStartFocus="@mipmap/star_selected"
                app:cmRatingBarStartNormal="@mipmap/star_normal"
                android:id="@+id/main_cmShape_CMRatingBar"
                android:layout_margin="10dp"
                android:layout_width="50dp"
                android:layout_height="50dp" />
    
    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

          本文链接:https://www.haomeiwen.com/subject/fisuaxtx.html