1.效果展示
image.pngimage.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;
}
网友评论