RatingBar.java 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. package com.cooleshow.base.widgets;
  2. import android.content.Context;
  3. import android.content.res.TypedArray;
  4. import android.graphics.drawable.Drawable;
  5. import android.util.AttributeSet;
  6. import android.view.View;
  7. import android.widget.ImageView;
  8. import android.widget.LinearLayout;
  9. import com.cooleshow.base.R;
  10. import java.math.BigDecimal;
  11. /**
  12. * 创建日期:2022/5/31 14:03
  13. *
  14. * @author Ryan
  15. * 类说明:
  16. */
  17. public class RatingBar extends LinearLayout {
  18. /**
  19. * 是否可点击
  20. */
  21. private boolean mClickable;
  22. /**
  23. * 星星总数
  24. */
  25. private int starCount;
  26. /**
  27. * 星星的点击事件
  28. */
  29. private OnRatingChangeListener onRatingChangeListener;
  30. /**
  31. * 每个星星的大小
  32. */
  33. private float starImageSize;
  34. /**
  35. * 每个星星的间距
  36. */
  37. private float starPadding;
  38. /**
  39. * 星星的显示数量,支持小数点
  40. */
  41. private float starStep;
  42. /**
  43. * 空白的默认星星图片
  44. */
  45. private Drawable starEmptyDrawable;
  46. /**
  47. * 选中后的星星填充图片
  48. */
  49. private Drawable starFillDrawable;
  50. /**
  51. * 半颗星的图片
  52. */
  53. private Drawable starHalfDrawable;
  54. /**
  55. * 每次点击星星所增加的量是整个还是半个
  56. */
  57. private StepSize stepSize;
  58. /**
  59. * 设置半星的图片资源文件
  60. *
  61. * @param starHalfDrawable
  62. */
  63. public void setStarHalfDrawable(Drawable starHalfDrawable) {
  64. this.starHalfDrawable = starHalfDrawable;
  65. }
  66. /**
  67. * 设置满星的图片资源文件
  68. *
  69. * @param starFillDrawable
  70. */
  71. public void setStarFillDrawable(Drawable starFillDrawable) {
  72. this.starFillDrawable = starFillDrawable;
  73. }
  74. /**
  75. * 设置空白和默认的图片资源文件
  76. *
  77. * @param starEmptyDrawable
  78. */
  79. public void setStarEmptyDrawable(Drawable starEmptyDrawable) {
  80. this.starEmptyDrawable = starEmptyDrawable;
  81. }
  82. /**
  83. * 设置星星是否可以点击操作
  84. *
  85. * @param clickable
  86. */
  87. public void setClickable(boolean clickable) {
  88. this.mClickable = clickable;
  89. }
  90. /**
  91. * 设置星星点击事件
  92. *
  93. * @param onRatingChangeListener
  94. */
  95. public void setOnRatingChangeListener(OnRatingChangeListener onRatingChangeListener) {
  96. this.onRatingChangeListener = onRatingChangeListener;
  97. }
  98. /**
  99. * 设置星星的大小
  100. *
  101. * @param starImageSize
  102. */
  103. public void setStarImageSize(float starImageSize) {
  104. this.starImageSize = starImageSize;
  105. }
  106. public void setStepSize(StepSize stepSize) {
  107. this.stepSize = stepSize;
  108. }
  109. /**
  110. * 构造函数
  111. * 获取xml中设置的资源文件
  112. *
  113. * @param context
  114. * @param attrs
  115. */
  116. public RatingBar(Context context, AttributeSet attrs) {
  117. super(context, attrs);
  118. setOrientation(LinearLayout.HORIZONTAL);
  119. TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RatingBar);
  120. starImageSize = mTypedArray.getDimension(R.styleable.RatingBar_starImageSize, 20);
  121. starPadding = mTypedArray.getDimension(R.styleable.RatingBar_starPadding, 10);
  122. starStep = mTypedArray.getFloat(R.styleable.RatingBar_starStep, 1.0f);
  123. stepSize = StepSize.fromStep(mTypedArray.getInt(R.styleable.RatingBar_stepSize, 1));
  124. starCount = mTypedArray.getInteger(R.styleable.RatingBar_starCount, 5);
  125. starEmptyDrawable = mTypedArray.getDrawable(R.styleable.RatingBar_starEmpty);
  126. starFillDrawable = mTypedArray.getDrawable(R.styleable.RatingBar_starFill);
  127. starHalfDrawable = mTypedArray.getDrawable(R.styleable.RatingBar_starHalf);
  128. mClickable = mTypedArray.getBoolean(R.styleable.RatingBar_clickable, true);
  129. mTypedArray.recycle();
  130. for (int i = 0; i < starCount; ++i) {
  131. final ImageView imageView = getStarImageView();
  132. imageView.setImageDrawable(starEmptyDrawable);
  133. imageView.setOnClickListener(
  134. new OnClickListener() {
  135. @Override
  136. public void onClick(View v) {
  137. if (mClickable) {
  138. //浮点数的整数部分
  139. int fint = (int) starStep;
  140. BigDecimal b1 = new BigDecimal(Float.toString(starStep));
  141. BigDecimal b2 = new BigDecimal(Integer.toString(fint));
  142. //浮点数的小数部分
  143. float fPoint = b1.subtract(b2).floatValue();
  144. if (fPoint == 0) {
  145. fint -= 1;
  146. }
  147. if (indexOfChild(v) > fint) {
  148. setStar(indexOfChild(v) + 1);
  149. } else if (indexOfChild(v) == fint) {
  150. if (stepSize == StepSize.Full) {//如果是满星 就不考虑半颗星了
  151. return;
  152. }
  153. //点击之后默认每次先增加一颗星,再次点击变为半颗星
  154. if (imageView.getDrawable().getCurrent().getConstantState().equals(starHalfDrawable.getConstantState())) {
  155. setStar(indexOfChild(v) + 1);
  156. } else {
  157. setStar(indexOfChild(v) + 0.5f);
  158. }
  159. } else {
  160. setStar(indexOfChild(v) + 1f);
  161. }
  162. }
  163. }
  164. }
  165. );
  166. addView(imageView);
  167. }
  168. setStar(starStep);
  169. }
  170. /**
  171. * 设置每颗星星的参数
  172. *
  173. * @return
  174. */
  175. private ImageView getStarImageView() {
  176. ImageView imageView = new ImageView(getContext());
  177. LinearLayout.LayoutParams layout = new LinearLayout.LayoutParams(
  178. Math.round(starImageSize), Math.round(starImageSize));//设置每颗星星在线性布局的大小
  179. layout.setMargins(0, 0, Math.round(starPadding), 0);//设置每颗星星在线性布局的间距
  180. imageView.setLayoutParams(layout);
  181. imageView.setAdjustViewBounds(true);
  182. imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
  183. imageView.setImageDrawable(starEmptyDrawable);
  184. imageView.setMinimumWidth(10);
  185. imageView.setMaxHeight(10);
  186. return imageView;
  187. }
  188. /**
  189. * 设置星星的个数
  190. *
  191. * @param rating
  192. */
  193. public void setStar(float rating) {
  194. if (onRatingChangeListener != null) {
  195. onRatingChangeListener.onRatingChange(rating);
  196. }
  197. this.starStep = rating;
  198. //浮点数的整数部分
  199. int fint = (int) rating;
  200. BigDecimal b1 = new BigDecimal(Float.toString(rating));
  201. BigDecimal b2 = new BigDecimal(Integer.toString(fint));
  202. //浮点数的小数部分
  203. float fPoint = b1.subtract(b2).floatValue();
  204. //设置选中的星星
  205. for (int i = 0; i < fint; ++i) {
  206. ((ImageView) getChildAt(i)).setImageDrawable(starFillDrawable);
  207. }
  208. //设置没有选中的星星
  209. for (int i = fint; i < starCount; i++) {
  210. ((ImageView) getChildAt(i)).setImageDrawable(starEmptyDrawable);
  211. }
  212. //小数点默认增加半颗星
  213. if (fPoint > 0) {
  214. ((ImageView) getChildAt(fint)).setImageDrawable(starHalfDrawable);
  215. }
  216. }
  217. public float getStarStep() {
  218. return starStep;
  219. }
  220. /**
  221. * 操作星星的点击事件
  222. */
  223. public interface OnRatingChangeListener {
  224. /**
  225. * 选中的星星的个数
  226. *
  227. * @param ratingCount
  228. */
  229. void onRatingChange(float ratingCount);
  230. }
  231. /**
  232. * 星星每次增加的方式整星还是半星,枚举类型
  233. * 类似于View.GONE
  234. */
  235. public enum StepSize {
  236. Half(0), Full(1);
  237. int step;
  238. StepSize(int step) {
  239. this.step = step;
  240. }
  241. public static StepSize fromStep(int step) {
  242. for (StepSize f : values()) {
  243. if (f.step == step) {
  244. return f;
  245. }
  246. }
  247. throw new IllegalArgumentException();
  248. }
  249. }
  250. }