自定義RatingBar
由於android自帶RatingBar圖示大小 不好調整,不能隨著控制元件大小隨意改變大小,故重新實現了一個
效果圖:
上程式碼:
values目錄下attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<span style="white-space:pre"> </span><declare-styleable name="MyRatingBar">
<eat-comment />
<!-- 尚未選中時的圖示 -->
<attr name="unselect_icon" format="reference" />
<!-- 選中後的圖示 -->
<attr name="select_icon" format="reference" />
<!-- 星星數量 -->
<attr name="star_number" format="integer"/>
<!-- 當前星級 -->
<attr name="current_rating" format="float"/>
<!-- 星星之間的間距 -->
<attr name="star_margin" format="dimension"/>
<!-- 是否可以手動觸控滑動改變值 -->
<attr name="touch_enable" format="boolean"/>
<!-- 總共星級數 -->
<attr name="total_rating" format="float"/>
</declare-styleable>
</resources>
MyRatingBar.java
package com.example.example.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;
import com.example.example.R;
public class MyRatingBar extends ImageView {
/**
* 預設星星(級)數
*/
private final int DEFAULT_STAR_NUMBER = 5;
/**
* 未選中時顯示的圖示資源id
*/
private int unselectIconId;
/**
* 選中後顯示的圖示資源id
*/
private int selectIconId;
/**
* 未選中時顯示的圖示
*/
private Bitmap unSelectIcon;
/**
* 選中後顯示的圖示
*/
private Bitmap selectedIcon;
/**
* 最終顯示 圖片
*/
private Bitmap result;
/**
* 星星數量
*/
private int starNumber;
/**
* 評星之間的間隔距離
*/
private int starMargin;
/**
* 當前星級
*/
private float currentRating;
/**
* 總星級評分
*/
private float totalRating;
/**
* 能否觸控改變星級
*/
private boolean touchEnable;
/**
* 星級變化監聽器
*/
private OnRatingBarChangeListener onRatingBarChangeListener;
public MyRatingBar(Context context) {
super(context);
//System.out.println("getWidth() = "+getWidth() +" getMeasuredWidth()= "+getMeasuredWidth()+" getHeight()= "+getHeight()+" getMeasuredHeight()= "+getMeasuredHeight());
}
public MyRatingBar(Context context, AttributeSet attrs) {
super(context, attrs);
//System.out.println("getWidth() = "+getWidth() +" getMeasuredWidth()= "+getMeasuredWidth()+" getHeight()= "+getHeight()+" getMeasuredHeight()= "+getMeasuredHeight());
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyRatingBar);
selectIconId = ta.getResourceId(R.styleable.MyRatingBar_select_icon, R.drawable.ic_launcher);
unselectIconId = ta.getResourceId(R.styleable.MyRatingBar_unselect_icon, R.drawable.ic_launcher);
starNumber = ta.getInt(R.styleable.MyRatingBar_star_number, DEFAULT_STAR_NUMBER);
starMargin = ta.getDimensionPixelSize(R.styleable.MyRatingBar_star_margin, 0);
currentRating = ta.getFloat(R.styleable.MyRatingBar_current_rating, 0);
totalRating = ta.getFloat(R.styleable.MyRatingBar_total_rating, DEFAULT_STAR_NUMBER);
touchEnable = ta.getBoolean(R.styleable.MyRatingBar_touch_enable, true);
System.out.println("---MyRatingBar(Context context, AttributeSet attrs)---");
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
System.out.println("---onLayout getWidth() = "+getWidth() +" getMeasuredWidth()= "+getMeasuredWidth()+" getHeight()= "+getHeight()+" getMeasuredHeight()= "+getMeasuredHeight());
prepareIcon(currentRating);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
System.out.println("onSizeChanged w="+w+" h="+h+" oldw="+oldw+" oldh="+oldh);
selectedIcon = null;
unSelectIcon = null;
result = null;
prepareIcon(currentRating);
super.onSizeChanged(w, h, oldw, oldh);
}
/**
* 獲取當前星級數值
* @return
*/
public float getCurrentRating() {
return currentRating;
}
/**
* 設定當前星級數值
* @param currentRating 要設定的星級數值
*/
public void setCurrentRating(float currentRating) {
this.currentRating = currentRating;
prepareIcon(currentRating);
if(onRatingBarChangeListener != null){
onRatingBarChangeListener.onRatingChanged(this, currentRating);
}
}
/**
* 獲取當前是否可以滑動來改變星級值
* @return
*/
public boolean isTouchEnable() {
return touchEnable;
}
/**
* 設定當前是否可以滑動來改變星級值
* @param touchEnable
*/
public void setTouchEnable(boolean touchEnable) {
this.touchEnable = touchEnable;
}
public int getStarMargin() {
return starMargin;
}
public void setStarMargin(int starMargin) {
this.starMargin = starMargin;
unSelectIcon = getBitmap(unselectIconId);
selectedIcon = getBitmap(selectIconId);
prepareIcon(currentRating);
}
/**
* 準備相關的狀態圖示
* @param rating 指定的星級指數
*/
public void prepareIcon(float rating){
if(rating > totalRating){
rating = totalRating;
}
if(rating < 0){
rating = 0;
}
rating = rating / totalRating ;
//System.out.println("prepareIcon rating="+rating);
if(unSelectIcon == null){
unSelectIcon = getBitmap(unselectIconId);//BitmapFactory.decodeResource(getResources(), unselectIconId);//
}
if(selectedIcon == null){
selectedIcon = getBitmap(selectIconId); //BitmapFactory.decodeResource(getResources(), selectIconId);//
}
int width = getWidth() == 0 ? unSelectIcon.getWidth() : getWidth();
int height = getHeight() == 0 ? unSelectIcon.getHeight() : getHeight();
if(result == null){
result = Bitmap.createBitmap(width , height , Bitmap.Config.ARGB_8888);
}else {
setBitmapTransparent(result);
}
Canvas canvas = new Canvas(result);
int selectedWidth = (int) (selectedIcon.getWidth()*rating);
Bitmap b1 = null,b2 = null;
if(selectedWidth > 0){
b1 = Bitmap.createBitmap(selectedIcon, 0, 0, selectedWidth, selectedIcon.getHeight());
}
int left = (int) (unSelectIcon.getWidth()*rating);
int unSelectWidth = (int) (unSelectIcon.getWidth()-left);
if(unSelectWidth > 0){
b2 = Bitmap.createBitmap(unSelectIcon, left, 0,unSelectWidth, unSelectIcon.getHeight());
}
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
if(b1 != null){
canvas.drawBitmap(b1, 0, 0, paint );
}
canvas.drawBitmap(b2, (int) (unSelectIcon.getWidth()*rating), 0, paint);
setImageBitmap(result);
}
/**
* 由圖片Id獲取單位星星圖示,並做相應綻放自適應處理
* @param imageId 指定的圖示Id
* @return
*/
protected Bitmap getBitmap(int imageId) {
Bitmap b = BitmapFactory.decodeResource(getResources(), imageId);
int width = getWidth() == 0 ? b.getWidth() : (getWidth()-((starNumber-1)*starMargin))/starNumber;
Bitmap b1 = zoomImg(b, width);
int height = getHeight() == 0 ? b.getHeight() : getHeight();
//(b.getWidth() * starNumber)+(starMargin*(starNumber - 1))
int w = 0;
if(getWidth() == 0){
w = b.getWidth()*starNumber+(starMargin*(starNumber-1));
}else {
w = getWidth();
}
Bitmap result = Bitmap.createBitmap(w, height , b.getConfig());
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
for(int i = 0 ; i < starNumber ; i++ ){
int left = width * i + starMargin*i;
canvas.drawBitmap(b1, left, (height - b1.getHeight())/2, paint );
}
return result;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if(!touchEnable){
return super.dispatchTouchEvent(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//System.out.println("----ACTION_DOWN----");
break;
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float f = x / (getWidth()/totalRating);
String value = String.format("%.1f", f);
f = Float.valueOf(value);
if(f < 0){
f = 0;
}
if(f > totalRating){
f = totalRating;
}
currentRating = f;
if(onRatingBarChangeListener != null){
onRatingBarChangeListener.onRatingChanged(this, f);
}
//System.out.println("----ACTION_MOVE----"+value+" f==="+f);
move((int)x);
break;
case MotionEvent.ACTION_UP:
//System.out.println("----ACTION_UP----");
break;
default:
break;
}
return true;//super.dispatchTouchEvent(event);
}
/**
* 根據滑動座標來更新顯示狀態
* @param x X座標值
*/
private void move(int x) {
if(x <= 0 || x >= getWidth()){
return;
}
if(result == null){
result = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
}else {
//setBitmapTransparent(result);
}
Canvas canvas = new Canvas(result);
canvas.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR);
Bitmap b1 = Bitmap.createBitmap(selectedIcon, 0, 0, x, result.getHeight());
Bitmap b2 = Bitmap.createBitmap(unSelectIcon, x, 0, result.getWidth() - x, result.getHeight());
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
canvas.drawBitmap(b1, 0, 0, paint );
canvas.drawBitmap(b2, x, 0, paint);
setImageBitmap(result);
}
/**
* 處理圖片
* @param bm 所要轉換的bitmap
* @param newWidth新的寬
* @param newHeight新的高
* @return 指定寬高的bitmap
*/
public static Bitmap zoomImg(Bitmap bm, int newWidth ,int newHeight){
// 獲得圖片的寬高
int width = bm.getWidth();
int height = bm.getHeight();
// 計算縮放比例
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 取得想要縮放的matrix引數
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 得到新的圖片 www.2cto.com
Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
return newbm;
}
/**
* 處理圖片
*
* @param bm
* 所要轉換的bitmap
* @param newWidth新的寬
* @param newHeight新的高
* @return 指定寬高的bitmap
*/
public static Bitmap zoomImg(Bitmap bm, int newWidth) {
// 獲得圖片的寬高
int width = bm.getWidth();
int height = bm.getHeight();
// 計算縮放比例
float scaleWidth = ((float) newWidth) / width;
// 取得想要縮放的matrix引數
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleWidth);
// 得到新的圖片 www.2cto.com
Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix,
true);
return newbm;
}
/**
* 把指定的bitmap置為透明
*
* @param b 需要設為透明的bitmap
*/
protected void setBitmapTransparent(Bitmap b) {
for (int i = 0; i < b.getWidth(); i++) {
for (int j = 0; j < b.getHeight(); j++) {
b.setPixel(i, j, Color.TRANSPARENT);
}
}
}
public void setOnRatingBarChangeListener(
OnRatingBarChangeListener onRatingBarChangeListener) {
this.onRatingBarChangeListener = onRatingBarChangeListener;
}
/**
* 星級變動監聽器
* @author 1
*
*/
public interface OnRatingBarChangeListener{
public void onRatingChanged(MyRatingBar ratingBar, float rating);
}
/**
* 僅做測試用,無實際意義
*/
@Deprecated
public void test(){
Bitmap b = Bitmap.createBitmap(result.getWidth(), result.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.YELLOW);
//setBitmapTransparent(result);
//canvas.drawRect(0, 0, result.getWidth(), result.getHeight(), p);
//canvas.drawBitmap(selectedIcon, 0, 0, p);
setImageBitmap(b);
System.out.println("------test-------");
}
}
佈局檔案:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:test="http://schemas.android.com/apk/res/com.example.example"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.example.RatingBarActivity"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<com.example.example.MyRatingBar
android:id="@+id/mrb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
test:select_icon = "@drawable/pingfen1"
test:unselect_icon = "@drawable/pingfen2"
test:star_number = "7"
test:star_margin="10dp"
test:default_rating="4.3"/>
</LinearLayout>
activity.java
public class RatingBarActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rating_bar);
}
}
用到的圖片素材
相關文章
- 自定義簡單的RatingBar
- Android RatingBar自定義替換系統圖片Android
- 紅橙Darren視訊筆記 自定義RatingBar touch事件學習 dp轉px listener監聽筆記事件
- 自定義View:自定義屬性(自定義按鈕實現)View
- 08.Django自定義模板,自定義標籤和自定義過濾器Django過濾器
- 自定義ImageView完成圓形頭像自定義View
- 自定義VIEWView
- 自定義圓環
- 自定義SnackBar
- 自定義useState
- 自定義_ajax
- 自定義Annotation
- 自定義OrderedMap
- 自定義 Drawable
- 自定義UICollectionViewLayoutUIView
- 自定義UITabBarUItabBar
- 自定義scrollbar
- 自定義Drawable
- 自定義ToastAST
- 自定義吐司
- 自定義 tabBartabBar
- 自定義表格
- 自定義 GitGit
- tailwind自定義AI
- android自定義view(自定義數字鍵盤)AndroidView
- vue自定義全域性元件(或自定義外掛)Vue元件
- android自定義View&自定義ViewGroup(下)AndroidView
- android自定義View&自定義ViewGroup(上)AndroidView
- Android自定義控制元件——自定義屬性Android控制元件
- Android 中文 API (40) —— RatingBarAndroidAPI
- netty自定義Decoder用於自定義協議Netty協議
- 4. 自定義控制元件(4) --- 自定義屬性控制元件
- android自定義鍵盤 自定義身份證鍵盤Android
- Android自定義控制元件之自定義屬性Android控制元件
- GridView 自定義模版自定義修改,刪除,分頁View
- 自定義 Artisan 命令
- 自定義ClassLoader
- 自定義QTimeEditQT