前言
之前有使用系統的RatingBar,發現不太靈活
於是自己寫一個
實現效果
原理
原理圖
首先得有兩張評星的圖,找ui妹子切一下
爲了方便定製,我這裏寫死了寬高 即整個控件的高度就是星星的高度
整體控件寬高按照需求寫死
我們還需要幾個自定義屬性,才能將整個RatingBar繪製出來
padding值 即每個星星之間的距離,我這裏五顆星星是居中排版
所以在設置參數時還是需要小小的計算的
每個星星之間的padding值
星星的總顆數
點亮的星星的顆數
點亮星星的樣式
默認未點亮星星的樣式
res/values/attrs
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--評星-->
<declare-styleable name="StarIndicator" >
<attr name="indicator_icon_chose" format="reference"/>
<attr name="indicator_icon_normal" format="reference"/>
<attr name="indicator_margin_left" format="dimension" />
<attr name="indicator_star_size" format="integer" />
<attr name="indicator_star_chose" format="integer"/>
</declare-styleable>
</resources>
這裏的margin_left 就是上面的星星之間的距離padding
主程序代碼
xml
<com.chonghao.evaluatestardemo.widget.StarIndicator
android:id="@+id/star"
android:layout_width="200dp" //寫死整個View寬度
android:layout_height="28dp" //寫死整個View高度,也是星星高度
android:layout_gravity="center_vertical"
app:indicator_icon_chose="@mipmap/home_star_pre" //選中星星圖片
app:indicator_icon_normal="@mipmap/home_star_nor" //未選中星星圖片
app:indicator_margin_left="10dp" //星星間距
app:indicator_star_chose="5" //選中星星個數
app:indicator_star_size="5"/> //星星總個數
自定義View StarIndicator
package com.chonghao.evaluatestardemo.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import com.chonghao.evaluatestardemo.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by ccb on 2017/8/29.
* 評分指示器 自定義控件
*/
public class StarIndicator extends View {
/**
* 選擇的星星 的bitmap
*/
private Bitmap drawable_chose;
/**
* 非選擇的星星 的bitmap
*/
private Bitmap drawable_normal;
/**
* 星星總顆數 的bitmap
*/
private int mStarNumber;
/**
* 選擇的星星顆數 的bitmap
*/
private int mChoseNumber;
/**
* 鄰近星星之間的padding值
*/
private float mPaddingLeft;
/**
* 整個View的高度
*/
private int mHeight;
/**
* 整個View的寬度
*/
private int mWidth;
/**
* 畫筆
*/
private Paint mPaint;
/**
* 最左側星星距離左邊界的距離
*/
private float mLeft0;
/**
* 每個星星定位點 點集合
*/
private List<RectF> mPointList;
/**
* 星星點擊事件回調
*/
private StarChoseListener mStarChoseListener;
public void setStarChoseListener(StarChoseListener starChoseListener) {
mStarChoseListener = starChoseListener;
}
public interface StarChoseListener {
void choseNumber(int num);
}
public StarIndicator(Context context) {
this(context, null);
}
public StarIndicator(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public StarIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StarIndicator, defStyleAttr, 0);
//獲取選中圖片
BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(R.styleable.StarIndicator_indicator_icon_chose);
drawable_chose = drawable.getBitmap();
//獲取選中圖片
BitmapDrawable drawable1 = (BitmapDrawable) a.getDrawable(R.styleable.StarIndicator_indicator_icon_normal);
drawable_normal = drawable1.getBitmap();
//獲取star個數
mStarNumber = a.getInteger(R.styleable.StarIndicator_indicator_star_size, 5);
//選中個數
mChoseNumber = a.getInteger(R.styleable.StarIndicator_indicator_star_chose, 5);
//獲取 間隙
mPaddingLeft = a.getDimension(R.styleable.StarIndicator_indicator_margin_left, 5);
//回收
a.recycle();
initPaint();
Log.d("tag",
mStarNumber + "mStarNumber" +
mChoseNumber + "mChoseNumber" +
mPaddingLeft + "mPaddingLeft" +
drawable_chose + "drawable_chose" +
drawable_normal + "drawable_normal"
);
}
private void initPaint() {
//獲取xml中的屬性
//初始化paint,初始化一些其他內容
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mHeight = getMeasuredHeight();
mWidth = getMeasuredWidth();
Log.d("tag", "mHeight" + mHeight
+ "mWidth" + mWidth
);
//測量控件寬高
//計算文字寬高
mLeft0 = (mWidth - mStarNumber * mHeight - mPaddingLeft * (mStarNumber - 1)) * 0.5f;
mPointList = new ArrayList<>();
for (int i = 0; i < mStarNumber; i++) {
float left = mLeft0 + i * (mPaddingLeft + mHeight);
mPointList.add(new RectF(left, 0, left + mHeight, mHeight));
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//畫icon
for (int i = 0; i < mPointList.size(); i++) {
if (i < mChoseNumber) {
canvas.drawBitmap(drawable_chose, null, mPointList.get(i), mPaint);
} else {
canvas.drawBitmap(drawable_normal, null, mPointList.get(i), mPaint);
}
}
}
public void setChoseNumber(int choseNumber) {
mChoseNumber = choseNumber;
postInvalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
float x = event.getX();
if (x > mWidth) {
x = mWidth;
}
if (x < 0) {
x = 0;
}
int a;
if (x <= mLeft0) {//最左側
setChoseNumber(a = 0);
} else if (x >= (mWidth - mLeft0)) {//最右側 有多少顆 亮多少顆
a = mStarNumber;
setChoseNumber(mStarNumber);
} else {
a = (int) ((x - mLeft0) / (mHeight + mPaddingLeft) + 1);
setChoseNumber(a);
}
if (mStarChoseListener != null) {
mStarChoseListener.choseNumber(a);
}
break;
}
return true;
}
}
MainActivity
StarIndicator star = (StarIndicator) findViewById(R.id.star);
star.setChoseNumber(3); //設置選中個數
//設置監聽
star.setStarChoseListener(new StarIndicator.StarChoseListener() {
@Override
public void choseNumber(int num) {
showToast(num + "");
}
});
好了 做起來還是很簡單的!