在Android开发中,我们经常会用到对商家或者商品的评价,运用星星进行打分。然而在Android系统中自带的打分控件,RatingBar特别不好用,间距和大小无法改变。所以,我就自定义了一个特别好用的打分控件。在项目中可以直接使用,特别简单。下面直接上图:

效果图

实现原理

其实就是自定义View继承LinearLayout ,然后里面动态加了五个ImageView。

实现代码,有详细的注释

在attrs中声明的可以在xml中设置的变量

RatingBar源码

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.drawable.Drawable;

import android.util.AttributeSet;

import android.view.View;

import android.widget.ImageView;

import android.widget.LinearLayout;

import com.kejiang.yuandl.R;

import java.math.BigDecimal;

/**

* Created by dylan on 2015/6/11.

* 自定义打分控件RatingBar

* 可以自定义星星大小和间距

* Correction clickEvent from Xml

*/

public class RatingBar extends LinearLayout {

/**

* 是否可点击

*/

private boolean mClickable;

/**

* 星星总数

*/

private int starCount;

/**

* 星星的点击事件

*/

private OnRatingChangeListener onRatingChangeListener;

/**

* 每个星星的大小

*/

private float starImageSize;

/**

* 每个星星的间距

*/

private float starPadding;

/**

* 星星的显示数量,支持小数点

*/

private float starStep;

/**

* 空白的默认星星图片

*/

private Drawable starEmptyDrawable;

/**

* 选中后的星星填充图片

*/

private Drawable starFillDrawable;

/**

* 半颗星的图片

*/

private Drawable starHalfDrawable;

/**

* 每次点击星星所增加的量是整个还是半个

*/

private StepSize stepSize;

/**

* 设置半星的图片资源文件

*

* @param starHalfDrawable

*/

public void setStarHalfDrawable(Drawable starHalfDrawable) {

this.starHalfDrawable = starHalfDrawable;

}

/**

* 设置满星的图片资源文件

*

* @param starFillDrawable

*/

public void setStarFillDrawable(Drawable starFillDrawable) {

this.starFillDrawable = starFillDrawable;

}

/**

* 设置空白和默认的图片资源文件

*

* @param starEmptyDrawable

*/

public void setStarEmptyDrawable(Drawable starEmptyDrawable) {

this.starEmptyDrawable = starEmptyDrawable;

}

/**

* 设置星星是否可以点击操作

*

* @param clickable

*/

public void setClickable(boolean clickable) {

this.mClickable = clickable;

}

/**

* 设置星星点击事件

*

* @param onRatingChangeListener

*/

public void setOnRatingChangeListener(OnRatingChangeListener onRatingChangeListener) {

this.onRatingChangeListener = onRatingChangeListener;

}

/**

* 设置星星的大小

*

* @param starImageSize

*/

public void setStarImageSize(float starImageSize) {

this.starImageSize = starImageSize;

}

public void setStepSize(StepSize stepSize) {

this.stepSize = stepSize;

}

/**

* 构造函数

* 获取xml中设置的资源文件

*

* @param context

* @param attrs

*/

public RatingBar(Context context, AttributeSet attrs) {

super(context, attrs);

setOrientation(LinearLayout.HORIZONTAL);

TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RatingBar);

starImageSize = mTypedArray.getDimension(R.styleable.RatingBar_starImageSize, 20);

starPadding = mTypedArray.getDimension(R.styleable.RatingBar_starPadding, 10);

starStep = mTypedArray.getFloat(R.styleable.RatingBar_starStep, 1.0f);

stepSize = StepSize.fromStep(mTypedArray.getInt(R.styleable.RatingBar_stepSize, 1));

starCount = mTypedArray.getInteger(R.styleable.RatingBar_starCount, 5);

starEmptyDrawable = mTypedArray.getDrawable(R.styleable.RatingBar_starEmpty);

starFillDrawable = mTypedArray.getDrawable(R.styleable.RatingBar_starFill);

starHalfDrawable = mTypedArray.getDrawable(R.styleable.RatingBar_starHalf);

mClickable = mTypedArray.getBoolean(R.styleable.RatingBar_clickable, true);

mTypedArray.recycle();

for (int i = 0; i < starCount; ++i) {

final ImageView imageView = getStarImageView();

imageView.setImageDrawable(starEmptyDrawable);

imageView.setOnClickListener(

new OnClickListener() {

@Override

public void onClick(View v) {

if (mClickable) {

//浮点数的整数部分

int fint = (int) starStep;

BigDecimal b1 = new BigDecimal(Float.toString(starStep));

BigDecimal b2 = new BigDecimal(Integer.toString(fint));

//浮点数的小数部分

float fPoint = b1.subtract(b2).floatValue();

if (fPoint == 0) {

fint -= 1;

}

if (indexOfChild(v) > fint) {

setStar(indexOfChild(v) + 1);

} else if (indexOfChild(v) == fint) {

if (stepSize == StepSize.Full) {//如果是满星 就不考虑半颗星了

return;

}

//点击之后默认每次先增加一颗星,再次点击变为半颗星

if (imageView.getDrawable().getCurrent().getConstantState().equals(starHalfDrawable.getConstantState())) {

setStar(indexOfChild(v) + 1);

} else {

setStar(indexOfChild(v) + 0.5f);

}

} else {

setStar(indexOfChild(v) + 1f);

}

}

}

}

);

addView(imageView);

}

setStar(starStep);

}

/**

* 设置每颗星星的参数

*

* @return

*/

private ImageView getStarImageView() {

ImageView imageView = new ImageView(getContext());

LinearLayout.LayoutParams layout = new LinearLayout.LayoutParams(

Math.round(starImageSize), Math.round(starImageSize));//设置每颗星星在线性布局的大小

layout.setMargins(0, 0, Math.round(starPadding), 0);//设置每颗星星在线性布局的间距

imageView.setLayoutParams(layout);

imageView.setAdjustViewBounds(true);

imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);

imageView.setImageDrawable(starEmptyDrawable);

imageView.setMinimumWidth(10);

imageView.setMaxHeight(10);

return imageView;

}

/**

* 设置星星的个数

*

* @param rating

*/

public void setStar(float rating) {

if (onRatingChangeListener != null) {

onRatingChangeListener.onRatingChange(rating);

}

this.starStep = rating;

//浮点数的整数部分

int fint = (int) rating;

BigDecimal b1 = new BigDecimal(Float.toString(rating));

BigDecimal b2 = new BigDecimal(Integer.toString(fint));

//浮点数的小数部分

float fPoint = b1.subtract(b2).floatValue();

//设置选中的星星

for (int i = 0; i < fint; ++i) {

((ImageView) getChildAt(i)).setImageDrawable(starFillDrawable);

}

//设置没有选中的星星

for (int i = fint; i < starCount; i++) {

((ImageView) getChildAt(i)).setImageDrawable(starEmptyDrawable);

}

//小数点默认增加半颗星

if (fPoint > 0) {

((ImageView) getChildAt(fint)).setImageDrawable(starHalfDrawable);

}

}

/**

* 操作星星的点击事件

*/

public interface OnRatingChangeListener {

/**

* 选中的星星的个数

*

* @param RatingCount

*/

void onRatingChange(float ratingCount);

}

/**

* 星星每次增加的方式整星还是半星,枚举类型

* 类似于View.GONE

*/

public enum StepSize {

Half(0), Full(1);

int step;

StepSize(int step) {

this.step = step;

}

public static StepSize fromStep(int step) {

for (StepSize f : values()) {

if (f.step == step) {

return f;

}

}

throw new IllegalArgumentException();

}

}

}

在xml中的用法

android:id="@+id/rb"

android:layout_width="360dp"

android:layout_height="50dp"

app:starCount="5"

app:starEmpty="@mipmap/star_grey"

app:starFill="@mipmap/star_yellow"

app:starHalf="@mipmap/star_half_yellow"

app:starImageSize="40dp"

app:starPadding="20dp"

app:starStep="1.5"

app:stepSize="Half">

在Activity中的设置

RatingBar ratingBar= (RatingBar) findViewById(R.id.rb);

ratingBar.setClickable(true);//设置可否点击

ratingBar.setStar(2.5f);//设置显示的星星个数

ratingBar.setStepSize(RatingBar.StepSize.Half);//设置每次点击增加一颗星还是半颗星

ratingBar.setOnRatingChangeListener(new RatingBar.OnRatingChangeListener() {

@Override

public void onRatingChange(float ratingCount) {//点击星星变化后选中的个数

Log.d("RatingBar","RatingBar-Count="+ratingCount);

}

});

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐