当前位置: 移动技术网 > 移动技术>移动开发>Android > Android自定义View之自定义评价打分控件RatingBar实现自定义星星大小和间距

Android自定义View之自定义评价打分控件RatingBar实现自定义星星大小和间距

2019年07月24日  | 移动技术网移动技术  | 我要评论

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

效果图

这里写图片描述

实现原理

其实就是自定义view继承linearlayout ,然后里面动态加了五个imageview。

实现代码,有详细的注释

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

<declare-styleable name="ratingbar">
<!--尺寸值-->
<attr name="starimagesize" format="dimension" />
<!--星星间距-->
<attr name="starpadding" format="dimension" />
<!--星星总数-->
<attr name="starcount" format="integer" />
<!--空白的星星资源文件值-->
<attr name="starempty" format="reference" />
<!--满星资源文件值-->
<attr name="starfill" format="reference" />
<!--半星资源文件值-->
<attr name="starhalf" format="reference" />
<!--是否可点击boolean值-->
<attr name="clickable" format="boolean" />
<!--当前进度float值-->
<attr name="starstep" format="float" />
<!--每次进度方式的值,整星还是半星-->
<attr name="stepsize">
<enum name="half" value="0" />
<enum name="full" value="1" />
</attr>
</declare-styleable>

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中的用法

<com.kejiang.yuandl.view.ratingbar
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"></com.kejiang.yuandl.view.ratingbar>

在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);
}
});

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网