自定義評(píng)分控件

1.首先繼承 ViewGroup 實(shí)現(xiàn)相關(guān)的構(gòu)造函數(shù)

public class Grade extends ViewGroup {

    private Context mContext;

    public Grade(Context context) {
        super(context);
        this.mContext = context;
    }

    public Grade(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
}

2.在構(gòu)造函數(shù)中獲取自定義屬性

 public Grade(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        //獲取自定義屬性
        TypedArray typedArray=mContext.obtainStyledAttributes(attrs,R.styleable.Grade);
        isOnclick=typedArray.getBoolean(R.styleable.Grade_isOnclick,false);
        number=typedArray.getInt(R.styleable.Grade_number,5);
        value=typedArray.getInt(R.styleable.Grade_selectValue,0);
        selectImage=typedArray.getResourceId(R.styleable.Grade_selectImage,0);
        noselectImage=typedArray.getResourceId(R.styleable.Grade_noSelectImage,0);
    }

3.接著就初始化一些數(shù)據(jù) 我們先初始化我們選中和沒(méi)選中默認(rèn)的圖片

 /**
     * 初始化Bitmap
     * @param selectImage
     * @param noselectImage
     */
    public void initBitmap(int selectImage,int noselectImage) {
        if (selectImage!=0&&noselectImage!=0){//如果沒(méi)有主動(dòng)設(shè)置選中和沒(méi)選中的圖片的時(shí)候 默認(rèn)使用默認(rèn)的圖片
            yes = BitmapFactory.decodeResource(getResources(), selectImage);
            no = BitmapFactory.decodeResource(getResources(),noselectImage);
        }else {
            yes = BitmapFactory.decodeResource(getResources(), R.mipmap.pingfenyes);
            no = BitmapFactory.decodeResource(getResources(), R.mipmap.pingfen);
        }
    }

4.圖片初始化完成之后 這個(gè)時(shí)候 我們就可以去往 ViewGroup 中去添加我們的子 View 也就是星星的控件

 /**
     * 初始化評(píng)分控件
     */
    public void initImageView() {
        for (int i = 0; i < number; i++) {//將星星添加到View當(dāng)中去
            final ImageView imageView = new ImageView(mContext);
            imageView.setImageBitmap(no);
            imageView.setTag(false);
            addView(imageView);
        }
    }

5.添加完成后 我們就要確定他們的位置了 在 onLayout 方法中去擺放它的位置

  /**
     * 確定擺放的位置
     * @param changed
     * @param l
     * @param t
     * @param r
     * @param b
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        count = getChildCount();
        setSelectvalue(value);

        int right = 0;
        int left = 0;

        //循環(huán)的設(shè)置子view的位置
        for (int i = 0; i < count; i++) {
            ImageView view = (ImageView) getChildAt(i);
            right += no.getWidth();
            view.layout(left, 0, right, no.getHeight());
            left += no.getWidth();

            final int finalI = i;

            if (isOnclick){//設(shè)置是否可點(diǎn)擊
                view.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        setSelectvalue(finalI+1);
                        if (ongradeClickItemListener!=null){
                            ongradeClickItemListener.currentItem(finalI+1);
                        }
                    }
                });
            }
        }
    }

6.確定擺放位置之后 我們接著要處理他們點(diǎn)擊的時(shí)候 選中和不選中的效果 這里我是用循環(huán) 去輪循各個(gè)子 view

/**
     * 設(shè)置選中的邏輯
     * @param value
     */
    public void setSelectvalue(int value){
        if (value>count){//如果主動(dòng)設(shè)置的選中數(shù)值大于星星的數(shù)值 那么做保護(hù)
           Toast.makeText(mContext,"設(shè)定的選擇數(shù)值大于星星的個(gè)數(shù)",Toast.LENGTH_SHORT).show();
            return;
        }

        //循環(huán)的去設(shè)置選中或者不選中
        for (int j=0;j<value;j++){
            ImageView imageView= (ImageView) getChildAt(j);
            imageView.setImageBitmap(yes);
            imageView.setTag(true);
        }
        for (int k=value;k<count;k++){
            ImageView imageView= (ImageView) getChildAt(k);
            imageView.setImageBitmap(no);
            imageView.setTag(false);
        }
    }

好了,基本上到這里,控件就基本上完成了。接著 做一些完善,測(cè)量控件的寬高,對(duì)外提供點(diǎn)擊事件的接口等,完整代碼如下:

package com.example.yinshuai.diyview.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.example.yinshuai.diyview.R;

/**
 * Created by yinshuai on 2017/7/7.
 *  1.可以設(shè)置星星的數(shù)目
 *  2.可以設(shè)置選中的數(shù)目
 *  3.可以替換選中或不選中的圖片
 *  4.定制化高
 */
public class Grade extends ViewGroup {

    private Bitmap yes;//選中的圖片
    private Bitmap no;//沒(méi)選中的圖片
    private Context mContext;
    private int number;//星星的個(gè)數(shù)
    private OnGradeClickItemListener ongradeClickItemListener;
    private int count;//當(dāng)前有多少個(gè)子view
    private int value=0;//當(dāng)前選中的位置
    private boolean isOnclick;//是否可點(diǎn)擊
    private int selectImage;//選中的圖片資源引用
    private int noselectImage;//沒(méi)選中的圖片資源引用

    public Grade(Context context) {
        super(context);
        this.mContext = context;
        initBitmap(0,0);//初始化圖片資源文件
        initImageView();//初始化圖片控件
        setWillNotDraw(false);
    }

    public Grade(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;

        //獲取自定義屬性
        TypedArray typedArray=mContext.obtainStyledAttributes(attrs,R.styleable.Grade);
        isOnclick=typedArray.getBoolean(R.styleable.Grade_isOnclick,false);
        number=typedArray.getInt(R.styleable.Grade_number,5);
        value=typedArray.getInt(R.styleable.Grade_selectValue,0);
        selectImage=typedArray.getResourceId(R.styleable.Grade_selectImage,0);
        noselectImage=typedArray.getResourceId(R.styleable.Grade_noSelectImage,0);

        initBitmap(selectImage,noselectImage);
        initImageView();
        setWillNotDraw(false);
    }

    /**
     * 寬高測(cè)量
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int widthMode=MeasureSpec.getMode(widthMeasureSpec);
        int widthSize=MeasureSpec.getSize(widthMeasureSpec);
        int heightMode=MeasureSpec.getMode(heightMeasureSpec);
        int heightSize=MeasureSpec.getSize(heightMeasureSpec);

        int width;
        int height;

        if (widthMode==MeasureSpec.EXACTLY){
            width=widthSize;
        }else {
            width=no.getWidth()*number;
        }

        if (heightMode==MeasureSpec.EXACTLY){
            height=heightSize;
        }else {
            height=no.getHeight();
        }

        setMeasuredDimension(width,height);
    }

    /**
     * 定義點(diǎn)擊事件接口
     */
    public interface OnGradeClickItemListener {
        void currentItem(int pos);
    }

    /**
     * 對(duì)外提供點(diǎn)擊事件接口
     * @param ongradeClickItemListener
     */
    public void setOnGradeClickItemListener(OnGradeClickItemListener ongradeClickItemListener) {
        this.ongradeClickItemListener = ongradeClickItemListener;
    }

    /**
     * 初始化Bitmap
     * @param selectImage
     * @param noselectImage
     */
    public void initBitmap(int selectImage,int noselectImage) {
        if (selectImage!=0&&noselectImage!=0){//如果沒(méi)有主動(dòng)設(shè)置選中和沒(méi)選中的圖片的時(shí)候 默認(rèn)使用默認(rèn)的圖片
            yes = BitmapFactory.decodeResource(getResources(), selectImage);
            no = BitmapFactory.decodeResource(getResources(),noselectImage);
        }else {
            yes = BitmapFactory.decodeResource(getResources(), R.mipmap.pingfenyes);
            no = BitmapFactory.decodeResource(getResources(), R.mipmap.pingfen);
        }
    }

    /**
     * 初始化評(píng)分控件
     */
    public void initImageView() {
        for (int i = 0; i < number; i++) {//將星星添加到View當(dāng)中去
            final ImageView imageView = new ImageView(mContext);
            imageView.setImageBitmap(no);
            imageView.setTag(false);
            addView(imageView);
        }
    }

    /**
     * 確定擺放的位置
     * @param changed
     * @param l
     * @param t
     * @param r
     * @param b
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        count = getChildCount();
        setSelectvalue(value);

        int right = 0;
        int left = 0;

        //循環(huán)的設(shè)置子view的位置
        for (int i = 0; i < count; i++) {
            ImageView view = (ImageView) getChildAt(i);
            right += no.getWidth();
            view.layout(left, 0, right, no.getHeight());
            left += no.getWidth();

            final int finalI = i;

            if (isOnclick){//設(shè)置是否可點(diǎn)擊
                view.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        setSelectvalue(finalI+1);
                        if (ongradeClickItemListener!=null){
                            ongradeClickItemListener.currentItem(finalI+1);
                        }
                    }
                });
            }
        }
    }

    /**
     * 設(shè)置選中的邏輯
     * @param value
     */
    public void setSelectvalue(int value){
        if (value>count){//如果主動(dòng)設(shè)置的選中數(shù)值大于星星的數(shù)值 那么做保護(hù)
           Toast.makeText(mContext,"設(shè)定的選擇數(shù)值大于星星的個(gè)數(shù)",Toast.LENGTH_SHORT).show();
            return;
        }

        //循環(huán)的去設(shè)置選中或者不選中
        for (int j=0;j<value;j++){
            ImageView imageView= (ImageView) getChildAt(j);
            imageView.setImageBitmap(yes);
            imageView.setTag(true);
        }
        for (int k=value;k<count;k++){
            ImageView imageView= (ImageView) getChildAt(k);
            imageView.setImageBitmap(no);
            imageView.setTag(false);
        }
    }

    /**
     * 對(duì)外提供設(shè)置選擇的接口
     * @param value
     */
    public void setValue(int value){
        this.value=value;
    }

}

github項(xiàng)目地址:GradeView
個(gè)人博客:小白的博客

最終的效果:

Grade.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容