您的位置:首页 > 其它

自定义拖拽IndicatorView

2016-06-04 16:39 375 查看

1. 效果图



2. 根据效果,定义需要属性:

其中模式下: 手动不可点击, 风速时: 最低和最高不可点击, 定时模式: 全部可以点击设置.

<declare-styleable name="IndicatorView">
<attr name="units" format="integer|reference"/>
<attr name="lightColor" format="reference|color"/>
<attr name="lightBitmap" format="reference"/>
<attr name="indicators" format="reference|string"/>

<attr name="controlStyle" format="enum">
<enum name="mode" value="0"/>
<enum name="wind" value="1"/>
<enum name="time" value="2"/>
</attr>
</declare-styleable>


private void parserAttrs(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.IndicatorView);
mLightColor = ta.getColor(R.styleable.IndicatorView_lightColor,
Color.argb(0xFF, 0xFF, 0xC1, 0x00));
int resourceId = ta.getResourceId(R.styleable.IndicatorView_lightBitmap, 0);
mLightBitmap = BitmapFactory.decodeResource(context.getResources(), resourceId);
mText = ta.getString(R.styleable.IndicatorView_indicators);
mIndicators = mText.split(",");
mUnits = mText.split(",").length - 1;

int mode = ta.getInt(R.styleable.IndicatorView_controlStyle, TIME);
switch (mode) {
case MODE:
mType = MODE;
break;
case WIND:
mType = WIND;
break;
case TIME:
mType = TIME;
break;
}

ta.recycle();
}


2. 初始化控件的一些默认值:

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mLeftX = getPaddingLeft();
mAvailableWidth = w - getPaddingLeft() - getPaddingRight();
float unit = mAvailableWidth / mUnits;
mThumbX = mLeftX + unit * mPosition;//粘近position

}


3. 测量控件的宽高:

/*简单测量,只支持为match_parent或者固定值*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width;
int height;

final int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec);
final int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec);
final int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
final int measureHeight = MeasureSpec.getSize(heightMeasureSpec);

/*布局width为match_parent或者固定值*/
if (measureWidthMode == MeasureSpec.EXACTLY) {
width = measureWidth;
} else {
width = mDefaultWidth;
}
/*布局height为match_parent或者固定值*/
if (measureHeightMode == MeasureSpec.EXACTLY) {
height = measureHeight;
} else {
height = mDefaultHeight;
}
setMeasuredDimension(width, height);
}


4.绘制thumb, 文本,及其tracker

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawTrack(canvas);
drawIndicatorTexts(canvas);
drawThumb(canvas);
}

/**
* 绘制thumb所在的track
*
* @param canvas
*/
private void drawTrack(Canvas canvas) {
Rect rect = new Rect(mLeftX, getHeight() * 2 / 3 - mTrackHeight / 2, mLeftX + mAvailableWidth,
getHeight() * 2 / 3 + mTrackHeight / 2);
mPaint.setColor(Color.parseColor("#ededed"));
canvas.drawRect(rect, mPaint);
}

/**
* 绘制indicators
*
* @param canvas
*/
private void drawIndicatorTexts(Canvas canvas) {
int count = mUnits;
Paint paint;
for (int i = 0; i <= count; i++) {
final float x = mAvailableWidth / count * i + mLeftX;

if (i == mPosition) {//当前选中的position
paint = mTextPaint;
mTextPaint.setColor(mLightColor);
} else {//没选中的position
paint = mTextPaint;
mTextPaint.setColor(Color.argb(0xFF, 0xBB, 0xBB, 0xBB));
}
paint.getTextBounds(mIndicators[i], 0, mIndicators[i].length(), mTextRect);
String text = mIndicators[i];
canvas.drawText(text, x - mTextRect.width() / 2, getHeight() / 3, paint);
}
}

/**
* 绘制thumb
*
* @param canvas
*/
private void drawThumb(Canvas canvas) {
Bitmap bitmap = mLightBitmap;
mThumbX = getThumbX(mPosition);
if (bitmap != null) {
canvas.drawBitmap(bitmap, mThumbX - bitmap.getWidth() / 2,
getHeight() * 2 / 3 - bitmap.getHeight() / 2, null);
}
}


5. 构建点击事件的监听器:

@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE: {
this.getParent().requestDisallowInterceptTouchEvent(true);
float x = event.getX();
moveThumb(x);
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
if (mListener != null) {
mListener.onPositionChange(mPosition);
}
float x = event.getX();
moveThumb(x);
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
}
return true;
}

private void moveThumb(float x) {
if (mPosition == getPosition(x)) {
return;
}
mPosition = getPosition(x);
switch (mType) {
case MODE:
if (mPosition == 0) {
mPosition = 1;
}
break;
case WIND:
if (mPosition == 0) {
mPosition = 1;
} else if (mPosition == 4) {
mPosition = 3;
}
break;

case TIME:
break;
}
mThumbX = getThumbX(mPosition);
invalidate();
}

/**
* 根据thumb的坐标获取thumb的位置
*
* @param x
* @return
*/
private int getPosition(float x) {
float unitWidth = mAvailableWidth / mUnits;
float originX = (x - mLeftX + unitWidth / 2f) / unitWidth;
return (int) originX;
}

/**
* 根据thumb的位置获取thumb的坐标
*
* @param position
* @return
*/
private float getThumbX(int position) {
float unit = mAvailableWidth / mUnits;
return mLeftX + unit * position;
}


6.保存与恢复自定义view的状态信息:

在屏幕旋转等情况要保存view的状态, 防止一些状态信息丢失,如thumb图标消失.

@Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof Bundle)) {
super.onRestoreInstanceState(state);
return;
}
Bundle bundle = (Bundle) state;
mLightBitmap = bundle.getParcelable("bitmap");
mText = bundle.getString("indicators");
mPosition = bundle.getInt("position");
mThumbX = bundle.getFloat("thumbX");
mType = bundle.getInt("mType");
mTrackHeight = bundle.getInt("trackHeight");
super.onRestoreInstanceState(bundle.getParcelable("instance"));
}

//##### 对外公布的方法###########################//

@Override
protected Parcelable onSaveInstanceState() {

Bundle bundle = new Bundle();
bundle.putParcelable("bitmap", mLightBitmap);
bundle.putInt("position", mPosition);
bundle.putString("indicators", mText);
bundle.putFloat("thumbX", mThumbX);
bundle.putInt("mType", mType);
bundle.putInt("trackHeight", mTrackHeight);
bundle.putParcelable("instance", super.onSaveInstanceState());
return bundle;
}


完整代码:

package ****

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.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;

import com.bugull.yft_airclean.R;

/**
* @ author: showdy
* @ time: 2016/5/21 14:20
* @ des: 用于控件界面的indicatorView
*/
public class IndicatorView extends View {

private static final int MODE = 0;
private static final int WIND = 1;
private static final int TIME = 2;
private OnPositionChangedListener mListener;
private int mUnits;
private int mLightColor;
private Bitmap mLightBitmap;
private String mText;
private Paint mPaint;
private Paint mTextPaint; //文字画笔
private int mDefaultWidth;
private int mDefaultHeight;
private int mLeftX;
private int mAvailableWidth;
private float mThumbX; //thumb的起始横坐标
private int mPosition = 0; //当前位置
private String[] mIndicators;
private Rect mTextRect;
private int mTrackHeight = 0;
private int mType = TIME;
private Context mContext;

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

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

public IndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
mTrackHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4,
context.getResources().getDisplayMetrics());
mDefaultWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 260,
context.getResources().getDisplayMetrics());
mDefaultHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 70,
context.getResources().getDisplayMetrics());
parserAttrs(context, attrs);
initPaint();
}

private void initPaint() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint.setColor(Color.argb(0xFF, 0xBB, 0xBB, 0xBB));
mPaint.setStyle(Paint.Style.FILL);

mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mTextPaint.setColor(Color.argb(0xFF, 0xBB, 0xBB, 0xBB));
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14,
getResources().getDisplayMetrics()));

mTextRect = new Rect();

}

private void parserAttrs(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.IndicatorView);
mLightColor = ta.getColor(R.styleable.IndicatorView_lightColor, Color.argb(0xFF, 0xFF, 0xC1, 0x00));
int resourceId = ta.getResourceId(R.styleable.IndicatorView_lightBitmap, 0);
mLightBitmap = BitmapFactory.decodeResource(context.getResources(), resourceId);
mText = ta.getString(R.styleable.IndicatorView_indicators);
mIndicators = mText.split(",");
mUnits = mText.split(",").length - 1;

int mode = ta.getInt(R.styleable.IndicatorView_controlStyle, TIME);
switch (mode) {
case MODE:
mType = MODE;
break;
case WIND:
mType = WIND;
break;
case TIME:
mType = TIME;
break;
}

ta.recycle();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width;
int height;

final int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec);
final int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec);
final int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
final int measureHeight = MeasureSpec.getSize(heightMeasureSpec);

if (measureWidthMode == MeasureSpec.EXACTLY) {
width = measureWidth;
} else {
width = mDefaultWidth;
}
if (measureHeightMode == MeasureSpec.EXACTLY) {
height = measureHeight;
} else {
height = mDefaultHeight;
}
setMeasuredDimension(width, height);
}

@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mLeftX = getPaddingLeft(); mAvailableWidth = w - getPaddingLeft() - getPaddingRight(); float unit = mAvailableWidth / mUnits; mThumbX = mLeftX + unit * mPosition;//粘近position }
@Override public boolean onTouchEvent(MotionEvent event) { if (!isEnabled()) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: { this.getParent().requestDisallowInterceptTouchEvent(true); float x = event.getX(); moveThumb(x); break; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { if (mListener != null) { mListener.onPositionChange(mPosition); } float x = event.getX(); moveThumb(x); this.getParent().requestDisallowInterceptTouchEvent(false); break; } } return true; } private void moveThumb(float x) { if (mPosition == getPosition(x)) { return; } mPosition = getPosition(x); switch (mType) { case MODE: if (mPosition == 0) { mPosition = 1; } break; case WIND: if (mPosition == 0) { mPosition = 1; } else if (mPosition == 4) { mPosition = 3; } break; case TIME: break; } mThumbX = getThumbX(mPosition); invalidate(); } /** * 根据thumb的坐标获取thumb的位置 * * @param x * @return */ private int getPosition(float x) { float unitWidth = mAvailableWidth / mUnits; float originX = (x - mLeftX + unitWidth / 2f) / unitWidth; return (int) originX; } /** * 根据thumb的位置获取thumb的坐标 * * @param position * @return */ private float getThumbX(int position) { float unit = mAvailableWidth / mUnits; return mLeftX + unit * position; }

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawTrack(canvas);
drawIndicatorTexts(canvas);
drawThumb(canvas);
}

/**
* 绘制thumb所在的track
*
* @param canvas
*/
private void drawTrack(Canvas canvas) {
Rect rect = new Rect(mLeftX, getHeight() * 2 / 3 - mTrackHeight / 2,
mLeftX + mAvailableWidth, getHeight() * 2 / 3 + mTrackHeight / 2);
mPaint.setColor(Color.parseColor("#ededed"));
canvas.drawRect(rect, mPaint);
}

/**
* 绘制indicators
*
* @param canvas
*/
private void drawIndicatorTexts(Canvas canvas) {
int count = mUnits;
Paint paint;
for (int i = 0; i <= count; i++) {
final float x = mAvailableWidth / count * i + mLeftX;

if (i == mPosition) {//当前选中的position
paint = mTextPaint;
mTextPaint.setColor(mLightColor);
} else {//没选中的position
paint = mTextPaint;
mTextPaint.setColor(Color.argb(0xFF, 0xBB, 0xBB, 0xBB));
}
paint.getTextBounds(mIndicators[i], 0, mIndicators[i].length(), mTextRect);
String text = mIndicators[i];
canvas.drawText(text, x - mTextRect.width() / 2, getHeight() / 3, paint);
}
}

/**
* 绘制thumb
*
* @param canvas
*/
private void drawThumb(Canvas canvas) {
Bitmap bitmap = mLightBitmap;
mThumbX = getThumbX(mPosition);
if (bitmap != null) {
canvas.drawBitmap(bitmap, mThumbX - bitmap.getWidth() / 2, getHeight() * 2 / 3 - bitmap.getHeight() / 2, null);
}
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof Bundle)) {
super.onRestoreInstanceState(state);
return;
}
Bundle bundle = (Bundle) state;
mLightBitmap = bundle.getParcelable("bitmap");
mText = bundle.getString("indicators");
mPosition = bundle.getInt("position");
mThumbX = bundle.getFloat("thumbX");
mType = bundle.getInt("mType");
mTrackHeight = bundle.getInt("trackHeight");
super.onRestoreInstanceState(bundle.getParcelable("instance"));
}

//##### 对外公布的方法###########################//

@Override
protected Parcelable onSaveInstanceState() {

Bundle bundle = new Bundle();
bundle.putParcelable("bitmap", mLightBitmap);
bundle.putInt("position", mPosition);
bundle.putString("indicators", mText);
bundle.putFloat("thumbX", mThumbX);
bundle.putInt("mType", mType);
bundle.putInt("trackHeight", mTrackHeight);
bundle.putParcelable("instance", super.onSaveInstanceState());
return bundle;
}

public void setPosition(int position) {
mPosition = position;
invalidate();
}

public void setLightColor(Context context, int resId, int color) {
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId);
mLightBitmap = bitmap;
mLightColor = color;
invalidate();
}

public void setOnPositionChangedListener(OnPositionChangedListener listener) {
mListener = listener;
}

@Override
public void setEnabled(boolean enabled) {
if (!enabled) {
setPosition(0);
setLightColor(mContext, R.mipmap.fsk_thumb_black, Color.parseColor("#bbbbbb"));
}
super.setEnabled(enabled);
}

public interface OnPositionChangedListener {
void onPositionChange(int position);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: