Android简单的可设置间隔评分条的实现

最近比较忙,有一段时间没有写博客了,之前项目写过一个很简单的评分条,来分享一下:

安卓原生提供了SeekBar可拖动的评分条,不过有的时候并不怎么好用,当只需要去显示评分条(比如几颗星的评分)的情况下,不需要拖动,SeekBar本身没有方法去设置单项之间的间隔,比较普遍的做法就是去修改一下图片,在图片两边适当添加一些距离.用起来不是特别舒服,所以自己实现一下.

代码实现

代码比较简单,就直接贴一下.
先设置一下自定义属性attr:

    <!--普通评分条图片-->
    <attr name="mkNormalDrawable" format="reference"/>
    <!--选中评分条图片-->
    <attr name="mkSelectDrawable" format="reference"/>
    <!--评分项间隔-->
    <attr name="mkInterval" format="dimension"/>
    <!--评分项高度-->
    <attr name="mkHeight" format="dimension"/>
    <!--评分项宽度-->
    <attr name="mkWidth" format="dimension"/>
    <!--评分项宽度-->
    <attr name="mkSize" format="integer"/>
    <declare-styleable name="MarkView">
        <attr name="mkNormalDrawable"/>
        <attr name="mkSelectDrawable"/>
        <attr name="mkInterval"/>
        <attr name="mkHeight"/>
        <attr name="mkWidth"/>
        <attr name="mkSize"/>
    </declare-styleable>

MarkView:

package com.teda.makerunion.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.teda.makerunion.R;
import com.teda.makerunion.utils.LogUtils;

/**
 * 评分条
 * Created by junweiliu on 16/6/22.
 */
public class MarkView extends LinearLayout {

    /**
     * 需要创建的评分图片的个数
     */
    private int childViewCount = 5;
    /**
     * 设置圆点间margin
     */
    private int mInterval;
    /**
     * 当前选中的位置
     */
    private int mCurrentPostion = 3;
    /**
     * 普通显示的图片
     */
    private Bitmap normalBp;
    /**
     * 选中时显示的图片
     */
    private Bitmap selectBp;
    /**
     * 评分单项宽度
     */
    private int mWidth;
    /**
     * 评分单项高度
     */
    private int mHeight;


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

    public MarkView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MarkView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 获取自定义属性
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MarkView);
        childViewCount = ta.getInteger(R.styleable.MarkView_mkSize, 5);
        normalBp = drawableToBitamp(ta.getDrawable(R.styleable.MarkView_mkNormalDrawable));
        selectBp = drawableToBitamp(ta.getDrawable(R.styleable.MarkView_mkSelectDrawable));
        mInterval = ta.getDimensionPixelOffset(R.styleable.MarkView_mkInterval, 3);
        mWidth = ta.getDimensionPixelOffset(R.styleable.MarkView_mkWidth, 0);
        mHeight = ta.getDimensionPixelOffset(R.styleable.MarkView_mkHeight, 0);
        ta.recycle();
        init();
    }

    /**
     * 初始化数据
     */
    private void init() {
        // 处理自定义属性
        if (null == normalBp) {
            normalBp = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.star_dark);
        }
        if (null == selectBp) {
            selectBp = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.star_light);
        }
        if (0 == mWidth) {
            mWidth = Math.max(selectBp.getWidth(), normalBp.getWidth());
        }
        if (0 == mHeight) {
            mHeight = Math.max(selectBp.getWidth(), normalBp.getWidth());
        }
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
        // 如果是wrap_content设置为图片宽高,否则设置为父容器宽高
        setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? sizeWidth : (mWidth + mInterval) * childViewCount
                , (heightMode == MeasureSpec.EXACTLY) ? sizeHeight
                        : mHeight);
    }

    /**
     * 重绘
     *
     * @param canvas
     */
    @Override
    protected void dispatchDraw(Canvas canvas) {
        // 创建指示器圆点
        if (getChildCount() < childViewCount && getChildCount() == 0) {
            for (int i = 0; i < childViewCount; i++) {
                addView(makeMarkItem());
            }
        }
        // 设置默认选中指示器
        setCurrentSteps(mCurrentPostion);
        super.dispatchDraw(canvas);
    }

    /**
     * 创建评分项
     *
     * @return
     */
    private View makeMarkItem() {
        ImageView iv = new ImageView(getContext());
        LinearLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        lp.width = mWidth;
        lp.height = mHeight;
        lp.rightMargin = mInterval;
        iv.setImageBitmap(normalBp);
        iv.setLayoutParams(lp);
        return iv;
    }

    /**
     * 设置当前个数
     *
     * @param num
     */
    public void setStepsNum(int num) {
        this.mCurrentPostion = num;
        setCurrentSteps(mCurrentPostion);
//        invalidate();
    }

    /**
     * 设置当前的选中位置,进行图片替换
     *
     * @param currentSteps
     */
    public void setCurrentSteps(int currentSteps) {
        for (int i = 0; i < getChildCount(); i++) {
            if (i < currentSteps)
                ((ImageView) getChildAt(i)).setImageBitmap(selectBp);
            else
                ((ImageView) getChildAt(i)).setImageBitmap(normalBp);
        }
    }

    /**
     * drawable转bitmap
     *
     * @param drawable
     * @return
     */
    private Bitmap drawableToBitamp(Drawable drawable) {
        if (null == drawable) {
            return null;
        }
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bd = (BitmapDrawable) drawable;
            return bd.getBitmap();
        }
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        drawable.draw(canvas);
        return bitmap;
    }
}

需要注意的是在下边两个地方中的默认图片需要自己提供一下.

  if (null == normalBp) {
            normalBp = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.star_dark);
        }
        if (null == selectBp) {
            selectBp = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.star_light);
        }

用法也比较简单,只需要在用到的地方调用setStepsNum方法即可.设置评分条单项之间间距可以通过设置控件的mkInterval属性来控制.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值