Android自定義RatingBar,評分控件

前言

之前有使用系統的RatingBar,發現不太靈活
於是自己寫一個

實現效果

效果

原理

原理圖
這裏寫圖片描述
首先得有兩張評星的圖,找ui妹子切一下
爲了方便定製,我這裏寫死了寬高 即整個控件的高度就是星星的高度
整體控件寬高按照需求寫死
我們還需要幾個自定義屬性,才能將整個RatingBar繪製出來
padding值 即每個星星之間的距離,我這裏五顆星星是居中排版
所以在設置參數時還是需要小小的計算的

每個星星之間的padding值
星星的總顆數
點亮的星星的顆數
點亮星星的樣式
默認未點亮星星的樣式

res/values/attrs

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--評星-->
    <declare-styleable name="StarIndicator" >
        <attr name="indicator_icon_chose" format="reference"/>
        <attr name="indicator_icon_normal" format="reference"/>
        <attr name="indicator_margin_left" format="dimension" />
        <attr name="indicator_star_size" format="integer" />
        <attr name="indicator_star_chose" format="integer"/>
    </declare-styleable>
</resources>

這裏的margin_left 就是上面的星星之間的距離padding

主程序代碼

xml

    <com.chonghao.evaluatestardemo.widget.StarIndicator
        android:id="@+id/star"
        android:layout_width="200dp"  //寫死整個View寬度
        android:layout_height="28dp"  //寫死整個View高度,也是星星高度
        android:layout_gravity="center_vertical"  
        app:indicator_icon_chose="@mipmap/home_star_pre" //選中星星圖片
        app:indicator_icon_normal="@mipmap/home_star_nor" //未選中星星圖片
        app:indicator_margin_left="10dp"  //星星間距
        app:indicator_star_chose="5"  //選中星星個數
        app:indicator_star_size="5"/>  //星星總個數

自定義View StarIndicator

package com.chonghao.evaluatestardemo.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.chonghao.evaluatestardemo.R;

import java.util.ArrayList;
import java.util.List;


/**
 * Created by ccb on 2017/8/29.
 * 評分指示器 自定義控件
 */

public class StarIndicator extends View {
    /**
     * 選擇的星星 的bitmap
     */
    private Bitmap drawable_chose;
    /**
     * 非選擇的星星 的bitmap
     */
    private Bitmap drawable_normal;
    /**
     * 星星總顆數 的bitmap
     */
    private int mStarNumber;
    /**
     * 選擇的星星顆數 的bitmap
     */
    private int mChoseNumber;
    /**
     * 鄰近星星之間的padding值
     */
    private float mPaddingLeft;
    /**
     * 整個View的高度
     */
    private int mHeight;
    /**
     * 整個View的寬度
     */
    private int mWidth;
    /**
     * 畫筆
     */
    private Paint mPaint;
    /**
     * 最左側星星距離左邊界的距離
     */
    private float mLeft0;
    /**
     * 每個星星定位點 點集合
     */
    private List<RectF> mPointList;
    /**
     * 星星點擊事件回調
     */
    private StarChoseListener mStarChoseListener;

    public void setStarChoseListener(StarChoseListener starChoseListener) {
        mStarChoseListener = starChoseListener;
    }

    public interface StarChoseListener {
        void choseNumber(int num);
    }

    public StarIndicator(Context context) {
        this(context, null);
    }

    public StarIndicator(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public StarIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StarIndicator, defStyleAttr, 0);
        //獲取選中圖片
        BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(R.styleable.StarIndicator_indicator_icon_chose);
        drawable_chose = drawable.getBitmap();
        //獲取選中圖片
        BitmapDrawable drawable1 = (BitmapDrawable) a.getDrawable(R.styleable.StarIndicator_indicator_icon_normal);
        drawable_normal = drawable1.getBitmap();
        //獲取star個數
        mStarNumber = a.getInteger(R.styleable.StarIndicator_indicator_star_size, 5);
        //選中個數
        mChoseNumber = a.getInteger(R.styleable.StarIndicator_indicator_star_chose, 5);
        //獲取 間隙
        mPaddingLeft = a.getDimension(R.styleable.StarIndicator_indicator_margin_left, 5);
        //回收
        a.recycle();
        initPaint();

        Log.d("tag",
                mStarNumber + "mStarNumber" +
                        mChoseNumber + "mChoseNumber" +
                        mPaddingLeft + "mPaddingLeft" +
                        drawable_chose + "drawable_chose" +
                        drawable_normal + "drawable_normal"
        );
    }

    private void initPaint() {
        //獲取xml中的屬性
        //初始化paint,初始化一些其他內容
        mPaint = new Paint();
        mPaint.setAntiAlias(true);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mHeight = getMeasuredHeight();
        mWidth = getMeasuredWidth();
        Log.d("tag", "mHeight" + mHeight
                + "mWidth" + mWidth
        );
        //測量控件寬高
        //計算文字寬高
        mLeft0 = (mWidth - mStarNumber * mHeight - mPaddingLeft * (mStarNumber - 1)) * 0.5f;
        mPointList = new ArrayList<>();
        for (int i = 0; i < mStarNumber; i++) {
            float left = mLeft0 + i * (mPaddingLeft + mHeight);
            mPointList.add(new RectF(left, 0, left + mHeight, mHeight));
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //畫icon
        for (int i = 0; i < mPointList.size(); i++) {
            if (i < mChoseNumber) {
                canvas.drawBitmap(drawable_chose, null, mPointList.get(i), mPaint);
            } else {
                canvas.drawBitmap(drawable_normal, null, mPointList.get(i), mPaint);
            }
        }
    }


    public void setChoseNumber(int choseNumber) {
        mChoseNumber = choseNumber;
        postInvalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
                float x = event.getX();
                if (x > mWidth) {
                    x = mWidth;
                }
                if (x < 0) {
                    x = 0;
                }

                int a;
                if (x <= mLeft0) {//最左側
                    setChoseNumber(a = 0);
                } else if (x >= (mWidth - mLeft0)) {//最右側  有多少顆 亮多少顆
                    a = mStarNumber;
                    setChoseNumber(mStarNumber);
                } else {
                     a = (int) ((x - mLeft0) / (mHeight + mPaddingLeft) + 1);
                    setChoseNumber(a);
                }
                if (mStarChoseListener != null) {
                    mStarChoseListener.choseNumber(a);
                }
                break;
        }
        return true;
    }
}

MainActivity

      StarIndicator star = (StarIndicator) findViewById(R.id.star);
        star.setChoseNumber(3); //設置選中個數
        //設置監聽
        star.setStarChoseListener(new StarIndicator.StarChoseListener() {
            @Override
            public void choseNumber(int num) {
                showToast(num + "");
            }
        });

好了 做起來還是很簡單的!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章