由于android自带RatingBar图标大小 不好调整,不能随着控件大小随意改变大小,故重新实现了一个
效果图:
上代码:
values目录下attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<span style="white-space:pre"> </span><declare-styleable name="MyRatingBar">
<eat-comment />
<!-- 尚未选中时的图标 -->
<attr name="unselect_icon" format="reference" />
<!-- 选中后的图标 -->
<attr name="select_icon" format="reference" />
<!-- 星星数量 -->
<attr name="star_number" format="integer"/>
<!-- 当前星级 -->
<attr name="current_rating" format="float"/>
<!-- 星星之间的间距 -->
<attr name="star_margin" format="dimension"/>
<!-- 是否可以手动触摸滑动改变值 -->
<attr name="touch_enable" format="boolean"/>
<!-- 总共星级数 -->
<attr name="total_rating" format="float"/>
</declare-styleable>
</resources>
MyRatingBar.java
package com.example.example.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;
import com.example.example.R;
public class MyRatingBar extends ImageView {
/**
* 默认星星(级)数
*/
private final int DEFAULT_STAR_NUMBER = 5;
/**
* 未选中时显示的图标资源id
*/
private int unselectIconId;
/**
* 选中后显示的图标资源id
*/
private int selectIconId;
/**
* 未选中时显示的图标
*/
private Bitmap unSelectIcon;
/**
* 选中后显示的图标
*/
private Bitmap selectedIcon;
/**
* 最终显示 图片
*/
private Bitmap result;
/**
* 星星数量
*/
private int starNumber;
/**
* 评星之间的间隔距离
*/
private int starMargin;
/**
* 当前星级
*/
private float currentRating;
/**
* 总星级评分
*/
private float totalRating;
/**
* 能否触摸改变星级
*/
private boolean touchEnable;
/**
* 星级变化监听器
*/
private OnRatingBarChangeListener onRatingBarChangeListener;
public MyRatingBar(Context context) {
super(context);
//System.out.println("getWidth() = "+getWidth() +" getMeasuredWidth()= "+getMeasuredWidth()+" getHeight()= "+getHeight()+" getMeasuredHeight()= "+getMeasuredHeight());
}
public MyRatingBar(Context context, AttributeSet attrs) {
super(context, attrs);
//System.out.println("getWidth() = "+getWidth() +" getMeasuredWidth()= "+getMeasuredWidth()+" getHeight()= "+getHeight()+" getMeasuredHeight()= "+getMeasuredHeight());
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyRatingBar);
selectIconId = ta.getResourceId(R.styleable.MyRatingBar_select_icon, R.drawable.ic_launcher);
unselectIconId = ta.getResourceId(R.styleable.MyRatingBar_unselect_icon, R.drawable.ic_launcher);
starNumber = ta.getInt(R.styleable.MyRatingBar_star_number, DEFAULT_STAR_NUMBER);
starMargin = ta.getDimensionPixelSize(R.styleable.MyRatingBar_star_margin, 0);
currentRating = ta.getFloat(R.styleable.MyRatingBar_current_rating, 0);
totalRating = ta.getFloat(R.styleable.MyRatingBar_total_rating, DEFAULT_STAR_NUMBER);
touchEnable = ta.getBoolean(R.styleable.MyRatingBar_touch_enable, true);
System.out.println("---MyRatingBar(Context context, AttributeSet attrs)---");
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
System.out.println("---onLayout getWidth() = "+getWidth() +" getMeasuredWidth()= "+getMeasuredWidth()+" getHeight()= "+getHeight()+" getMeasuredHeight()= "+getMeasuredHeight());
prepareIcon(currentRating);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
System.out.println("onSizeChanged w="+w+" h="+h+" oldw="+oldw+" oldh="+oldh);
selectedIcon = null;
unSelectIcon = null;
result = null;
prepareIcon(currentRating);
super.onSizeChanged(w, h, oldw, oldh);
}
/**
* 获取当前星级数值
* @return
*/
public float getCurrentRating() {
return currentRating;
}
/**
* 设置当前星级数值
* @param currentRating 要设置的星级数值
*/
public void setCurrentRating(float currentRating) {
this.currentRating = currentRating;
prepareIcon(currentRating);
if(onRatingBarChangeListener != null){
onRatingBarChangeListener.onRatingChanged(this, currentRating);
}
}
/**
* 获取当前是否可以滑动来改变星级值
* @return
*/
public boolean isTouchEnable() {
return touchEnable;
}
/**
* 设置当前是否可以滑动来改变星级值
* @param touchEnable
*/
public void setTouchEnable(boolean touchEnable) {
this.touchEnable = touchEnable;
}
public int getStarMargin() {
return starMargin;
}
public void setStarMargin(int starMargin) {
this.starMargin = starMargin;
unSelectIcon = getBitmap(unselectIconId);
selectedIcon = getBitmap(selectIconId);
prepareIcon(currentRating);
}
/**
* 准备相关的状态图标
* @param rating 指定的星级指数
*/
public void prepareIcon(float rating){
if(rating > totalRating){
rating = totalRating;
}
if(rating < 0){
rating = 0;
}
rating = rating / totalRating ;
//System.out.println("prepareIcon rating="+rating);
if(unSelectIcon == null){
unSelectIcon = getBitmap(unselectIconId);//BitmapFactory.decodeResource(getResources(), unselectIconId);//
}
if(selectedIcon == null){
selectedIcon = getBitmap(selectIconId); //BitmapFactory.decodeResource(getResources(), selectIconId);//
}
int width = getWidth() == 0 ? unSelectIcon.getWidth() : getWidth();
int height = getHeight() == 0 ? unSelectIcon.getHeight() : getHeight();
if(result == null){
result = Bitmap.createBitmap(width , height , Bitmap.Config.ARGB_8888);
}else {
setBitmapTransparent(result);
}
Canvas canvas = new Canvas(result);
int selectedWidth = (int) (selectedIcon.getWidth()*rating);
Bitmap b1 = null,b2 = null;
if(selectedWidth > 0){
b1 = Bitmap.createBitmap(selectedIcon, 0, 0, selectedWidth, selectedIcon.getHeight());
}
int left = (int) (unSelectIcon.getWidth()*rating);
int unSelectWidth = (int) (unSelectIcon.getWidth()-left);
if(unSelectWidth > 0){
b2 = Bitmap.createBitmap(unSelectIcon, left, 0,unSelectWidth, unSelectIcon.getHeight());
}
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
if(b1 != null){
canvas.drawBitmap(b1, 0, 0, paint );
}
canvas.drawBitmap(b2, (int) (unSelectIcon.getWidth()*rating), 0, paint);
setImageBitmap(result);
}
/**
* 由图片Id获取单位星星图标,并做相应绽放自适应处理
* @param imageId 指定的图标Id
* @return
*/
protected Bitmap getBitmap(int imageId) {
Bitmap b = BitmapFactory.decodeResource(getResources(), imageId);
int width = getWidth() == 0 ? b.getWidth() : (getWidth()-((starNumber-1)*starMargin))/starNumber;
Bitmap b1 = zoomImg(b, width);
int height = getHeight() == 0 ? b.getHeight() : getHeight();
//(b.getWidth() * starNumber)+(starMargin*(starNumber - 1))
int w = 0;
if(getWidth() == 0){
w = b.getWidth()*starNumber+(starMargin*(starNumber-1));
}else {
w = getWidth();
}
Bitmap result = Bitmap.createBitmap(w, height , b.getConfig());
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
for(int i = 0 ; i < starNumber ; i++ ){
int left = width * i + starMargin*i;
canvas.drawBitmap(b1, left, (height - b1.getHeight())/2, paint );
}
return result;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if(!touchEnable){
return super.dispatchTouchEvent(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//System.out.println("----ACTION_DOWN----");
break;
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float f = x / (getWidth()/totalRating);
String value = String.format("%.1f", f);
f = Float.valueOf(value);
if(f < 0){
f = 0;
}
if(f > totalRating){
f = totalRating;
}
currentRating = f;
if(onRatingBarChangeListener != null){
onRatingBarChangeListener.onRatingChanged(this, f);
}
//System.out.println("----ACTION_MOVE----"+value+" f==="+f);
move((int)x);
break;
case MotionEvent.ACTION_UP:
//System.out.println("----ACTION_UP----");
break;
default:
break;
}
return true;//super.dispatchTouchEvent(event);
}
/**
* 根据滑动坐标来更新显示状态
* @param x X坐标值
*/
private void move(int x) {
if(x <= 0 || x >= getWidth()){
return;
}
if(result == null){
result = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
}else {
//setBitmapTransparent(result);
}
Canvas canvas = new Canvas(result);
canvas.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR);
Bitmap b1 = Bitmap.createBitmap(selectedIcon, 0, 0, x, result.getHeight());
Bitmap b2 = Bitmap.createBitmap(unSelectIcon, x, 0, result.getWidth() - x, result.getHeight());
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
canvas.drawBitmap(b1, 0, 0, paint );
canvas.drawBitmap(b2, x, 0, paint);
setImageBitmap(result);
}
/**
* 处理图片
* @param bm 所要转换的bitmap
* @param newWidth新的宽
* @param newHeight新的高
* @return 指定宽高的bitmap
*/
public static Bitmap zoomImg(Bitmap bm, int newWidth ,int newHeight){
// 获得图片的宽高
int width = bm.getWidth();
int height = bm.getHeight();
// 计算缩放比例
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 取得想要缩放的matrix参数
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 得到新的图片 www.2cto.com
Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
return newbm;
}
/**
* 处理图片
*
* @param bm
* 所要转换的bitmap
* @param newWidth新的宽
* @param newHeight新的高
* @return 指定宽高的bitmap
*/
public static Bitmap zoomImg(Bitmap bm, int newWidth) {
// 获得图片的宽高
int width = bm.getWidth();
int height = bm.getHeight();
// 计算缩放比例
float scaleWidth = ((float) newWidth) / width;
// 取得想要缩放的matrix参数
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleWidth);
// 得到新的图片 www.2cto.com
Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix,
true);
return newbm;
}
/**
* 把指定的bitmap置为透明
*
* @param b 需要设为透明的bitmap
*/
protected void setBitmapTransparent(Bitmap b) {
for (int i = 0; i < b.getWidth(); i++) {
for (int j = 0; j < b.getHeight(); j++) {
b.setPixel(i, j, Color.TRANSPARENT);
}
}
}
public void setOnRatingBarChangeListener(
OnRatingBarChangeListener onRatingBarChangeListener) {
this.onRatingBarChangeListener = onRatingBarChangeListener;
}
/**
* 星级变动监听器
* @author 1
*
*/
public interface OnRatingBarChangeListener{
public void onRatingChanged(MyRatingBar ratingBar, float rating);
}
/**
* 仅做测试用,无实际意义
*/
@Deprecated
public void test(){
Bitmap b = Bitmap.createBitmap(result.getWidth(), result.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.YELLOW);
//setBitmapTransparent(result);
//canvas.drawRect(0, 0, result.getWidth(), result.getHeight(), p);
//canvas.drawBitmap(selectedIcon, 0, 0, p);
setImageBitmap(b);
System.out.println("------test-------");
}
}
布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:test="http://schemas.android.com/apk/res/com.example.example"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.example.RatingBarActivity"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<com.example.example.MyRatingBar
android:id="@+id/mrb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
test:select_icon = "@drawable/pingfen1"
test:unselect_icon = "@drawable/pingfen2"
test:star_number = "7"
test:star_margin="10dp"
test:default_rating="4.3"/>
</LinearLayout>
activity.java
public class RatingBarActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rating_bar);
}
}
用到的图片素材