項目地址:https://github.com/qingtenglv/ImageRatingView
因為android自帶的RatingBar用起來不是很方便泣洞,于是決定自己寫一個替代品。歡迎大家去github issue奠蹬。
控件介紹:
示意圖
<declare-styleable name="ImageRatingView">
//設(shè)置評分最大值
<attr name="maxCount" format="integer" />
//設(shè)置評分之間的跨度哮笆,示意圖中為0.5
<attr name="minStep" format="float" />
//設(shè)置評分時的圖片
<attr name="frontImage" format="reference"/>
//設(shè)置未評分的圖片(需和評分的圖片等寬等高)
<attr name="backImage" format="reference"/>
//圖片之間的間隔
<attr name="spanSize" format="dimension"/>
//默認(rèn)評分
<attr name="rating" format="float"/>
//是否可觸摸評分
<attr name="touchable" format="boolean"/>
//設(shè)定圖片的寬(layout_width設(shè)置為wrap_content即可)
<attr name="imageWidth" format="dimension"/>
//設(shè)定圖片的高(layout_height設(shè)置為wrap_content即可)
<attr name="imageHeight" format="dimension"/>
</declare-styleable>
在代碼中支持設(shè)定默認(rèn)評分以及獲取評分来颤,還可以通過設(shè)置OnRatingChangedListener
來監(jiān)聽評分的變化。
基本思路:
利用canvas.drawBitmap(bitmap,src,dst,paint)
來繪制評分的圖標(biāo)稠肘。照圖上來講分三部分進(jìn)行繪制:①繪制前三個黃色的星星福铅、②繪制后面三個白色的星星、③第四個星星單獨繪制项阴。
代碼實現(xiàn):
- 繪制前三個黃色的星星
private void drawFront(Canvas canvas) {
//src是指圖片要顯示的部分滑黔,這里為顯示整個星星。
Rect src = new Rect(0, 0, mFront.getWidth(), mFront.getHeight());
for (int i = 0; i < (int) mRating; i++) {
int left = i * (mBitmapDstWidth + mSpanSize);
int right = (i + 1) * mBitmapDstWidth + i * mSpanSize;
//dst指圖片在view中顯示的位置,這里動態(tài)計算出每個星星的坐標(biāo)位置略荡。
Rect dst = new Rect(left, 0, right, mBitmapDstHeight);
canvas.drawBitmap(mFront, src, dst, null);
}
}
- 繪制后三個白色的星星
private void drawBack(Canvas canvas) {
Rect src = new Rect(0, 0, mFront.getWidth(), mFront.getHeight());
//和繪制前三個的主要區(qū)別是這里的起始值不同
for (int i = (int) (mRating + 1); i < mMaxCount; i++) {
//mBitmapDstWidth是圖片指定的寬度
int left = i * (mBitmapDstWidth + mSpanSize);
int right = (i + 1) * mBitmapDstWidth + i * mSpanSize;
Rect dst = new Rect(left, 0, right, mBitmapDstHeight);
canvas.drawBitmap(mBack, src, dst, null);
}
}
- 繪制第四個星星
private void drawLastFront(Canvas canvas) {
//先畫front部分即黃色的部分
//rating小數(shù)點前的值色查。
int rating = (int) mRating;
//算出rating小數(shù)點后的值,圖中實例為0.5
float frontPart = mRating - rating;
int frontWidth = (int) (frontPart * mFront.getWidth());
//這里src的寬度就是圖片的一半
Rect srcFront = new Rect(0, 0, frontWidth, mFront.getHeight());
//位置的起始值和之前的一樣
int leftFront = rating * (mBitmapDstWidth + mSpanSize);
//區(qū)別在結(jié)束值撞芍,按照圖中實例來理解就是3.5*圖片的寬度+3*圖片之間的間隔
int rightFront = (int) (mRating* mBitmapDstWidth + rating * mSpanSize);
Rect dstFront = new Rect(leftFront, 0, rightFront, mBitmapDstHeight);
canvas.drawBitmap(mFront, srcFront, dstFront, null);
//back部分即白色的部分
int backWidth = (int) (frontPart * mFront.getWidth());
Rect srcBack = new Rect(backWidth, 0, mFront.getWidth(), mFront.getHeight());
//位置的起始值即剛才畫前半部分的結(jié)束值
int leftBack = (int) (mRating * mBitmapDstWidth + rating * mSpanSize);
int rightBack = (rating + 1) * mBitmapDstWidth + rating * mSpanSize;
Rect dstBack = new Rect(leftBack, 0, rightBack, mBitmapDstHeight);
canvas.drawBitmap(mBack, srcBack, dstBack, null);
}
其他細(xì)節(jié):
因為本控件支持設(shè)定最小評分的跨度,例如設(shè)置step為0.5跨扮,如果這時傳進(jìn)來3.3分序无,就要四舍五入到3.5。代碼如下:
private void correctedRatingValue() {
if (mRating > mMaxCount) {
mRating = mMaxCount;
} else if (mRating < 0) {
mRating = 0;
}
//最后一個跨度 進(jìn)行四舍五入的判斷
float after = mRating % mMinStep > mMinStep / 2 ? mMinStep : 0;
//除去最后個跨度
float front = mRating - mRating % mMinStep;
mRating = after +front;
}
但在觸摸控件評分時上面的算法就不能用了衡创,舉個例子例如我觸摸得到的評分是3.1帝嗡,那么按照上面的算法會得到3分,最后就顯示為3個星星璃氢。這樣顯示就很怪異哟玷,因為正常情況你的手指觸摸在了星星上就表示這個星星會亮,因此這時候要換一種算法:
private void correctedRatingValueForTouch() {
if (mRating % mMinStep == 0)
return;
mRating = mRating - mRating % mMinStep + mMinStep;
}
最后
歡迎大家使用一也,有問題可以在github或者簡書留言巢寡!謝謝