Android控件封装之RatingBar(三)

Andriod开发的时候,如果在做一些需要评分的应用的时候,通常会使用到RatingBar控件,但是android自带的RatingBar控件比较坑爹,首先控件的大小无法灵活调整,再者样式单一,而且受版本和定制系统的影响,这个时候我们肯定需要自定义RatingBar控件。

自定义RatingBar控件的方式很多,通常有拼星星个数的,在这里,我介绍一种我认为比较好的,比较容易操控的方式:该控件使用分层设计,从上到下,分为星星镂空层、遮罩层、星星背景层3层。

首先星星镂空层是一个星星部分透明的png图片,如下图所以:

5个星星为透明设计,其他区域填充自己应用的主色调

遮罩层是一个未选中状态的颜色条,如果ratingbar分值为0-5分的话,0分表示遮罩层覆盖住控件的所有区域,1分表示遮罩层覆盖住后面4个星星的区域,2分表示遮罩层覆盖住后面3个星星的区域,3分表示遮罩层覆盖住后面2个星星的区域,4分表示遮罩层覆盖住后面1个星星的区域,5分表示遮罩层不遮罩。

星星背景层为星星选中时的png图片

将这3层图片进行一个叠加,然后控制中间的遮罩层就可以控制分值的显示了,具体代码如下:

package cn.emag.utils.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import cn.emag.tools.activity.R;

public class CustomRatingBar extends LinearLayout implements Runnable {

	private static String TAG = "CustomRatingBar";

	private Context context;

	private float score;

	private int weight;

	private static final float TOTAL_SCORE = 5f;

	private boolean start = false, stop = false;

	private View view1, view2;

	private boolean editAble = false, showScore = true;

	private TextView scoreView;

	public View getView1() {
		return view1;
	}

	private LinearLayout.LayoutParams params1, params2;

	public CustomRatingBar(Context context) {
		super(context);
		this.context = context;
		init();
	}

	@SuppressLint("Recycle")
	public CustomRatingBar(Context context, AttributeSet attrs) {
		super(context, attrs);
		if (attrs != null) {
			TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomRatingBar);
			editAble = a.getBoolean(R.styleable.CustomRatingBar_editAble, false);
			showScore = a.getBoolean(R.styleable.CustomRatingBar_showScore, true);
		}
		this.context = context;
		init();
	}

	@SuppressLint("NewApi")
	@SuppressWarnings("deprecation")
	public void init() {
		this.setOrientation(LinearLayout.HORIZONTAL);

		// 设置rating_bar
		RelativeLayout relativeLayout = new RelativeLayout(context);
		relativeLayout.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.rating_bar_star));
		LinearLayout.LayoutParams linearLayoutParams = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.FILL_PARENT);
		linearLayoutParams.weight = 1;
		relativeLayout.setLayoutParams(linearLayoutParams);

		// 设置rating_bar的底层
		LinearLayout linearLayout = new LinearLayout(context);
		RelativeLayout.LayoutParams relativeLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,
		        RelativeLayout.LayoutParams.FILL_PARENT);
		linearLayout.setLayoutParams(relativeLayoutParams);
		linearLayout.setOrientation(LinearLayout.HORIZONTAL);
		params1 = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.FILL_PARENT);
		params1.weight = 0;
		view1 = new View(context);
		view1.setLayoutParams(params1);
		view1.setBackgroundColor(context.getResources().getColor(R.color.alpha_00));
		linearLayout.addView(view1);
		view2 = new View(context);
		params2 = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.FILL_PARENT);
		params2.weight = 100;
		view2.setLayoutParams(params2);
		view2.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.rating_bar_dark_bg));
		linearLayout.addView(view2);
		relativeLayout.addView(linearLayout);

		// 设置rating_bar的表层
		View ratingBar = new View(context);
		ratingBar.setLayoutParams(relativeLayoutParams);
		ratingBar.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.rating_bar));
		relativeLayout.addView(ratingBar);
		relativeLayout.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (editAble) {
					float score = 5 * event.getX() / v.getWidth();
					if (score < 0.25) {
						score = 0f;
					} else if (score < 0.75) {
						score = 0.5f;
					} else if (score < 1.25) {
						score = 1f;
					} else if (score < 1.75) {
						score = 1.5f;
					} else if (score < 2.25) {
						score = 2f;
					} else if (score < 2.75) {
						score = 2.5f;
					} else if (score < 3.25) {
						score = 3f;
					} else if (score < 3.75) {
						score = 3.5f;
					} else if (score < 4.25) {
						score = 4f;
					} else if (score < 4.75) {
						score = 4.5f;
					} else {
						score = 5f;
					}
					params1.weight = 100 * score / 5;
					view1.setLayoutParams(params1);
					params2.weight = 100 - params1.weight;
					view2.setLayoutParams(params2);
					setScoreValue(score);
					Log.i(TAG, "score:" + score);
					return true;
				} else {
					return false;
				}
			}
		});
		addView(relativeLayout);

		// 设置比例

		scoreView = new TextView(context);
		scoreView.setLayoutParams(new LinearLayout.LayoutParams(50, LinearLayout.LayoutParams.FILL_PARENT));
		scoreView.setGravity(Gravity.CENTER);
		scoreView.setBackgroundColor(Color.WHITE);
		if (showScore) {
			scoreView.setVisibility(VISIBLE);
		} else {
			scoreView.setVisibility(GONE);
		}
		addView(scoreView);
	}

	@Override
	public void run() {
		if (editAble) {
			return;
		}
		if (stop) {
			return;
		}
		if (params1.weight >= this.weight) {
			stop = true;
			return;
		}
		params1.weight += 1;
		view1.setLayoutParams(params1);
		params2.weight = 100 - params1.weight;
		view2.setLayoutParams(params2);
		postDelayed(this, 5);
	}

	public float getScore() {
		return score;
	}

	public void setScoreValue(float score) {
		this.score = score;
		this.scoreView.setText(String.valueOf(score));
		postDelayed(this, 5);
	}

	public void setScore(float score) {
		if (this.start) {
			return;
		}
		if (score >= 0 && score <= CustomRatingBar.TOTAL_SCORE) {
			this.score = score;
			this.scoreView.setText(String.valueOf(score));
			this.weight = (int) (score / CustomRatingBar.TOTAL_SCORE * 100);
			Log.i(TAG, "this.weight:" + this.weight);
			if (this.weight % 20 == 2) {// 2->4
				this.weight += 2;
			} else if (this.weight % 20 == 4) {// 4->5
				this.weight += 1;
			} else if (this.weight % 20 == 16) {// 16->15
				this.weight -= 1;
			} else if (this.weight % 20 == 18) {// 18->16
				this.weight -= 2;
			}
			Log.i(TAG, "this.weight%20:" + this.weight);
			this.start = true;
			postDelayed(this, 1000);
		} else {
			this.stop = true;
		}
	}

}


具体layout配置如下:

<cn.emag.utils.view.CustomRatingBar
                android:id="@+id/ratingBar1"
                android:layout_width="fill_parent"
                android:layout_height="50dp"
                android:layout_marginTop="20dp"
                app:editAble="true" >
            </cn.emag.utils.view.CustomRatingBar>


上面用到的 app:editAble="true"属性,是我们自定义属性,用来控制RatingBar是否可以编辑用的,在attr.xml中定义,在layout中配置,在CustomRatingBar.java中获取,attr.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomRatingBar">
        <attr name="editAble" format="boolean" />
        <attr name="showScore" format="boolean" />
    </declare-styleable>

</resources>

我们看到在CustomRatingBar.java中有两行代码

editAble = a.getBoolean(R.styleable.CustomRatingBar_editAble, false);
showScore = a.getBoolean(R.styleable.CustomRatingBar_showScore, true);

这个就是用来接收自定义属性的,这里我们看到除了editAble,还有另外一个属性showScore,这个属性是控制在RatingBar的右侧是否用数字显示分值

到这里整个自定义的RatingBar就完成了,用法也很简单,在activity中

CustomRatingBar ratingBar1 = (CustomRatingBar) this.findViewById(R.id.ratingBar1);
ratingBar1.setScore(4.1f);

这个是初始化分值,获取值的时候用ratingBar1.getScore();

 

图片资源请到我的资源里面去下载,地址:http://download.csdn.net/detail/lihui_shine/5666411

最后大家可以根据自己所需要的样式去修改几个图片


 
 

AndroidRatingBar 控件是一种用户评分控件,可以在应用中显示一组星形图标,用户可以通过点击星形图标来为应用或产品进行评分。RatingBar 控件通常用于应用市场或评估应用的功能中。 RatingBar 控件有以下属性: - android:numStars:指定 RatingBar 中星形图标的数量。 - android:rating:指定 RatingBar 的当前评分值。 - android:stepSize:指定评分的步长,例如设置为 0.5,则评分只能是整数或半数(例如 3.0、3.5、4.0 等)。 - android:isIndicator:指定 RatingBar 是否是只读的,即用户是否可以更改评分值。 RatingBar 控件还可以通过监听器来检测评分值的变化。例如,可以使用 OnRatingBarChangeListener 监听器来在评分值发生更改时执行自定义操作。 以下是 RatingBar 控件的示例代码: ``` <RatingBar android:id="@+id/ratingBar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:numStars="5" android:stepSize="0.5" android:rating="3.0" android:isIndicator="false" /> ``` 在代码中,可以使用 setRating() 方法来动态设置评分值,例如: ``` RatingBar ratingBar = (RatingBar) findViewById(R.id.ratingBar); ratingBar.setRating(4.5f); ``` 在监听器中,可以使用 getRating() 方法来获取当前的评分值,例如: ``` RatingBar ratingBar = (RatingBar) findViewById(R.id.ratingBar); ratingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() { @Override public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { Log.d("MyApp", "Rating changed to " + rating); } }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值