您的位置:首页 > 移动开发 > Android开发

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

2016-07-26 09:19 441 查看
最近比较忙,有一段时间没有写博客了,之前项目写过一个很简单的评分条,来分享一下:

安卓原生提供了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属性来控制.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 评分条 间隔