[add] 自定义ratingbar
This commit is contained in:
@@ -0,0 +1,298 @@
|
||||
package com.mogo.module.common.view;
|
||||
|
||||
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 androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.mogo.module.common.R;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class CustomRatingBar extends LinearLayout {
|
||||
private Context mContext;
|
||||
/*
|
||||
是否可点击
|
||||
* */
|
||||
private boolean mClickable;
|
||||
/*
|
||||
* 单元总数(心形/星星)
|
||||
* */
|
||||
private int elementCount;
|
||||
/*
|
||||
* 单元点击事件
|
||||
* */
|
||||
private OnRatingChangeListener mOnRatingBarChangeListener;
|
||||
/*
|
||||
* 每个单元的大小
|
||||
* */
|
||||
private float elementWidth;
|
||||
|
||||
private float elementHeight;
|
||||
|
||||
public float getElementWidth() {
|
||||
return elementWidth;
|
||||
}
|
||||
|
||||
public void setElementWidth(float elementWidth) {
|
||||
this.elementWidth = elementWidth;
|
||||
}
|
||||
|
||||
public float getElementHeight() {
|
||||
return elementHeight;
|
||||
}
|
||||
|
||||
public void setElementHeight(float elementHeight) {
|
||||
this.elementHeight = elementHeight;
|
||||
}
|
||||
|
||||
/*
|
||||
* 每个单元间的距离
|
||||
* */
|
||||
private float elementPadding;
|
||||
/*
|
||||
*单元的显示数量,支持小数点
|
||||
* */
|
||||
private float elementStep;
|
||||
/*
|
||||
* 空白的默认单元图片
|
||||
* */
|
||||
private Drawable elementEmptyDrawable;
|
||||
/*
|
||||
* 选中后的单元图片
|
||||
* */
|
||||
private Drawable elementFillDrawable;
|
||||
/*
|
||||
* 半颗单元图片
|
||||
* */
|
||||
private Drawable elementHarfDrawable;
|
||||
/*
|
||||
* 每次点击单元所增加的量是半个还是整个
|
||||
* */
|
||||
private StepSize stepSize;
|
||||
|
||||
@Override
|
||||
public boolean isClickable() {
|
||||
return mClickable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClickable(boolean clickable) {
|
||||
mClickable = clickable;
|
||||
}
|
||||
|
||||
public int getElementCount() {
|
||||
return elementCount;
|
||||
}
|
||||
|
||||
public void setElementCount(int elementCount) {
|
||||
this.elementCount = elementCount;
|
||||
}
|
||||
|
||||
public OnRatingChangeListener getOnRatingBarChangeListener() {
|
||||
return mOnRatingBarChangeListener;
|
||||
}
|
||||
|
||||
public void setOnRatingChangeListener(OnRatingChangeListener onRatingBarChangeListener) {
|
||||
mOnRatingBarChangeListener = onRatingBarChangeListener;
|
||||
}
|
||||
|
||||
public float getElementPadding() {
|
||||
return elementPadding;
|
||||
}
|
||||
|
||||
public void setElementPadding(float elementPadding) {
|
||||
this.elementPadding = elementPadding;
|
||||
}
|
||||
|
||||
public float getElementStep() {
|
||||
return elementStep;
|
||||
}
|
||||
|
||||
public void setElementStep(float elementStep) {
|
||||
this.elementStep = elementStep;
|
||||
}
|
||||
|
||||
public Drawable getElementEmptyDrawable() {
|
||||
return elementEmptyDrawable;
|
||||
}
|
||||
|
||||
public void setElementEmptyDrawable(Drawable elementEmptyDrawable) {
|
||||
this.elementEmptyDrawable = elementEmptyDrawable;
|
||||
}
|
||||
|
||||
public Drawable getElementFillDrawable() {
|
||||
return elementFillDrawable;
|
||||
}
|
||||
|
||||
public void setElementFillDrawable(Drawable elementFillDrawable) {
|
||||
this.elementFillDrawable = elementFillDrawable;
|
||||
}
|
||||
|
||||
public Drawable getElementHarfDrawable() {
|
||||
return elementHarfDrawable;
|
||||
}
|
||||
|
||||
public void setElementHarfDrawable(Drawable elementHarfDrawable) {
|
||||
this.elementHarfDrawable = elementHarfDrawable;
|
||||
}
|
||||
|
||||
|
||||
public void setStepSize(StepSize stepSize) {
|
||||
this.stepSize = stepSize;
|
||||
}
|
||||
|
||||
public CustomRatingBar(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
setOrientation(LinearLayout.HORIZONTAL);
|
||||
TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomRatingBar);
|
||||
elementWidth = mTypedArray.getDimension(R.styleable.CustomRatingBar_elenmentWidth,
|
||||
context.getResources().getDimension(R.dimen.heart_ratingbar_width));
|
||||
elementHeight = mTypedArray.getDimension(R.styleable.CustomRatingBar_elenmentHeight,
|
||||
context.getResources().getDimension(R.dimen.heart_ratingbar_height));
|
||||
elementPadding = mTypedArray.getDimension(R.styleable.CustomRatingBar_elenmentPadding, 10);
|
||||
|
||||
elementStep = mTypedArray.getFloat(R.styleable.CustomRatingBar_elenmentStep, 1.0f);
|
||||
stepSize = StepSize.fromStep(mTypedArray.getInt(R.styleable.CustomRatingBar_stepSize, 1));
|
||||
elementCount = mTypedArray.getInteger(R.styleable.CustomRatingBar_elenmentCount, 5);
|
||||
stepSize = StepSize.Half;
|
||||
|
||||
Drawable drawable_empty_default = ContextCompat.getDrawable(context, R.drawable.icon_heart_unchoose);
|
||||
Drawable drawable_harf_default = ContextCompat.getDrawable(context, R.drawable.icon_heart_second);
|
||||
Drawable drawable_fill_default = ContextCompat.getDrawable(context, R.drawable.icon_heart_choose);
|
||||
|
||||
Drawable drawable_empty = mTypedArray.getDrawable(R.styleable.CustomRatingBar_elenmentEmpty);
|
||||
Drawable drawable_harf = mTypedArray.getDrawable(R.styleable.CustomRatingBar_elenmentHarf);
|
||||
Drawable drawable_fill = mTypedArray.getDrawable(R.styleable.CustomRatingBar_elenmentFill);
|
||||
|
||||
elementEmptyDrawable = drawable_empty != null ? drawable_empty : drawable_empty_default;
|
||||
elementFillDrawable = drawable_harf != null ? drawable_harf : drawable_fill_default;
|
||||
elementHarfDrawable = drawable_fill != null ? drawable_fill : drawable_harf_default;
|
||||
mClickable = mTypedArray.getBoolean(R.styleable.CustomRatingBar_clickable, false);
|
||||
mTypedArray.recycle();
|
||||
for (int i = 0; i < elementCount; ++i) {
|
||||
final ImageView imageView = getElenmentImageView();
|
||||
imageView.setImageDrawable(elementEmptyDrawable);
|
||||
imageView.setOnClickListener(
|
||||
new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mClickable) {
|
||||
//浮点数的整数部分
|
||||
int fint = (int) elementStep;
|
||||
BigDecimal b1 = new BigDecimal(Float.toString(elementStep));
|
||||
BigDecimal b2 = new BigDecimal(Integer.toString(fint));
|
||||
//浮点数的小数部分
|
||||
float fPoint = b1.subtract(b2).floatValue();
|
||||
if (fPoint == 0) {
|
||||
fint -= 1;
|
||||
}
|
||||
|
||||
if (indexOfChild(v) > fint) {
|
||||
setRating(indexOfChild(v) + 1);
|
||||
} else if (indexOfChild(v) == fint) {
|
||||
if (stepSize == StepSize.Full) {//如果是满星 就不考虑半颗星了
|
||||
return;
|
||||
}
|
||||
//点击之后默认每次先增加一颗星,再次点击变为半颗星
|
||||
if (imageView.getDrawable().getCurrent().getConstantState().
|
||||
equals(elementHarfDrawable.getConstantState())) {
|
||||
setRating(indexOfChild(v) + 1);
|
||||
} else {
|
||||
setRating(indexOfChild(v) + 0.5f);
|
||||
}
|
||||
} else {
|
||||
setRating(indexOfChild(v) + 1f);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
addView(imageView);
|
||||
}
|
||||
setRating(elementStep);
|
||||
}
|
||||
|
||||
private ImageView getElenmentImageView() {
|
||||
ImageView imageView = new ImageView(getContext());
|
||||
LayoutParams layout = new LayoutParams(
|
||||
Math.round(mContext.getResources().getDimension(R.dimen.heart_ratingbar_width)),
|
||||
Math.round(mContext.getResources().getDimension(R.dimen.heart_ratingbar_width)));//设置每个单元格在线性布局的大小
|
||||
layout.setMargins(0, 0, Math.round(elementPadding), 0);//设置每颗星星在线性布局的间距
|
||||
imageView.setLayoutParams(layout);
|
||||
imageView.setAdjustViewBounds(true);
|
||||
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
|
||||
imageView.setImageDrawable(elementEmptyDrawable);
|
||||
imageView.setMinimumWidth((int) elementWidth);
|
||||
imageView.setMaxWidth((int) elementWidth);
|
||||
imageView.setMinimumHeight((int) elementHeight);
|
||||
imageView.setMaxHeight((int) elementHeight);
|
||||
return imageView;
|
||||
}
|
||||
|
||||
public void setRating(float rating) {
|
||||
if (rating > elementCount)
|
||||
rating = elementCount;
|
||||
|
||||
if (mOnRatingBarChangeListener != null) {
|
||||
mOnRatingBarChangeListener.onRatingChange(rating);
|
||||
}
|
||||
this.elementStep = 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(elementFillDrawable);
|
||||
}
|
||||
//设置没有选中的单元
|
||||
for (int i = fint; i < elementCount; i++) {
|
||||
((ImageView) getChildAt(i)).setImageDrawable(elementEmptyDrawable);
|
||||
}
|
||||
//小数点默认增加半个
|
||||
if (fPoint > 0) {
|
||||
((ImageView) getChildAt(fint)).setImageDrawable(elementHarfDrawable);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public interface OnRatingChangeListener {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user