记录下
package com.myf.scrollerscalerulerview;
import android.animation.TimeAnimator;
import android.animation.TimeAnimator.TimeListener;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
/**
* 背景可拖拽刻度尺
*
* @author Mengyf
*
*/
@SuppressLint({ "NewApi", "DefaultLocale" })
public class ScaleRulerProgressBar extends View {
/** 绘制刻度线画笔 */
private Paint mPaintRuler;
/** 绘制中间刻度线画笔 */
private Paint mPaintRulerCentralLine;
/** 绘制刻度尺颜色 */
private int mRulerColor = Color.RED;
/** 绘制刻度尺宽度 */
private float mRulerWidth = 4;
/** 进度值 */
private int mProgress = 0;
/** 设置最大值 */
private int mMax = 100;
/** 绘制刻度之间的间距 */
private int mRulerDistance = 10;
/** 刻度线条高度 */
private int mMinLineHeight, mMiddleLineHeight, mMaxLineHeight,mCentralLineHeight;
/** 绘制刻度尺高度 */
private int mRulerHeight = 100;
/** 得到偏移量 */
protected float mOffsetX;
/** 最大偏移 */
protected int mMaxOffset;
/** 设置文字大小 */
private float mTextSize = 30;
/** 是否显示文本 */
private boolean isShowText = false;
/** 记录目标偏移量 */
private float mTargetOffset;
/** 设置动画执行速度 */
private float mAnimSpeed = 1f;
/** 动画 */
private TimeAnimator mTimeAnimator;
private IOnProgressChangeListener mL;
/** 记录上一次的值 */
private int mLastProgress = -1;
/**
* 圆形进度
* @param l
*/
public void setOnProgressChangeListener(IOnProgressChangeListener l) {
mL = l;
}
/**
* 进度值改变监听
* @author ZH-SW-Mengyf
*
*/
public interface IOnProgressChangeListener{
/**
* 环形进度条
* @param rectangularView
* @param progress
*/
void progressChange(ScaleRulerProgressBar rulerProgressBar, int progress,boolean isAniming);
}
/**
* 通知进度改变
* @param progress
* @param isAniming
*/
private void notifyProgressChange(int progress , boolean isAniming) {
if (mL != null) {
if (mLastProgress != progress || !isAniming) {
mLastProgress = progress;
mL.progressChange(this, progress, isAniming);
}
}
}
public ScaleRulerProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public ScaleRulerProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ScaleRulerProgressBar(Context context) {
super(context);
init(context);
}
private void init(Context context) {
setRulerColor(Color.RED);
setRulerWidth(3);
setLineHeight(20, 30, 50, 80);
setTextSize(30);
setShowText(true);
initPaintRuler();
initPaintRulerCentralLine();
}
/**
* 初始化刻度画笔
*/
private void initPaintRuler() {
mPaintRuler = new Paint();
mPaintRuler.setAntiAlias(true);
}
/**
* 绘制中心线
*/
private void initPaintRulerCentralLine() {
mPaintRulerCentralLine = new Paint();
mPaintRulerCentralLine.setAntiAlias(true);
}
/**
* 绘制线颜色
*
* @param lineColor
*/
public void setRulerColor(int rulerColor) {
mRulerColor = rulerColor;
invalidate();
}
/**
* 设置刻度之间的距离
*/
public void setRulerDistance(int rulerDistance) {
mRulerDistance = rulerDistance;
invalidate();
}
/**
* 获取刻度之间的距离
*/
public int getRulerDistance() {
return mRulerDistance;
}
/**
* 绘制刻度尺线宽度
*/
public void setRulerWidth(int rulerWidth) {
mRulerWidth = rulerWidth;
invalidate();
}
/**
* 获取刻度尺线宽度
*
* @return
*/
public float getRulerWidth() {
return mRulerWidth;
}
/**
* 设置最大值
*
* @param max
*/
public void setMax(int max) {
if (max < 0) {
max = 0;
}
if (max != mMax) {
mMax = max;
postInvalidate();
if (mProgress > max) {
mProgress = max;
}
}
}
/**
* 或者最大值
*
* @return
*/
public int getMax() {
return mMax;
}
/**
* 设置进度值
* @param progress
*/
public void setProgress(int progress) {
setProgress(progress, false, true);
}
/**
* 设置进度值
* @param progress
*/
public void setProgress(int progress ,boolean anim) {
setProgress(progress, anim, true);
}
/**
* 设置进度
*
* @param progress
* @param fromUser
* @param refreshProgress
*/
public void setProgress(int progress, boolean anim, boolean refreshProgress) {
if (progress < 0) {
progress = 0;
}
if (progress > mMax) {
progress = mMax;
}
if (progress != mProgress || refreshProgress) {
mProgress = progress;
if (refreshProgress) {
refreshProgress(mProgress, anim);
}
}
}
/**
* 获取进度
*
* @return
*/
public int getProgress() {
return mProgress;
}
/**
* 刷新进度值
*
* @param progress
*/
protected void refreshProgress(int progress , boolean isAnim) {
if (isAnim) {
setAnim(progressToOffsetX(progress));
}else{
mProgress = progress;
refreshOffset(progressToOffsetX(progress));
notifyProgressChange(mProgress, false);
}
}
/**
* 刷新托快的偏移量
* @param offset
*/
protected void refreshOffset(float offset) {
stopAnim();
mOffsetX = getValidOffset(offset);
invalidate();
}
/**
* 设置线高
* @param minLineHeight
* @param middleLineHeight
* @param maxLineHeight
*/
public void setLineHeight(int minLineHeight, int middleLineHeight, int maxLineHeight ,int centralLineHeight) {
mMinLineHeight = minLineHeight;
mMiddleLineHeight = middleLineHeight;
mMaxLineHeight = maxLineHeight;
mCentralLineHeight = centralLineHeight;
invalidate();
}
/**
* 设置文字大小
* @param textSize
*/
public void setTextSize(float textSize ) {
mTextSize = textSize;
invalidate();
}
/**
* 显示文本
* @param showText
*/
public void setShowText(boolean showText) {
isShowText = showText;
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int minimumWidth = getSuggestedMinimumWidth();
final int minimumHeight = getSuggestedMinimumHeight();
int width = measureWidth(minimumWidth, widthMeasureSpec);
int height = measureHeight(minimumHeight, heightMeasureSpec);
setMeasuredDimension(width, height);
}
/**
* 测量宽度
* @param defaultWidth
* @param measureSpec
* @return
*/
private int measureWidth(int defaultWidth, int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.AT_MOST:
defaultWidth = (int) (mRulerDistance * getMax() + mRulerWidth);
break;
case MeasureSpec.EXACTLY:
defaultWidth = specSize;
break;
case MeasureSpec.UNSPECIFIED:
defaultWidth = Math.max(defaultWidth, specSize);
}
return defaultWidth;
}
/**
* 测量高度
* @param defaultHeight
* @param measureSpec
* @return
*/
private int measureHeight(int defaultHeight, int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.AT_MOST:
defaultHeight = mRulerHeight;
break;
case MeasureSpec.EXACTLY:
defaultHeight = specSize;
break;
case MeasureSpec.UNSPECIFIED:
defaultHeight = Math.max(defaultHeight, specSize);
break;
}
return defaultHeight;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaintRuler.setColor(mRulerColor);
mMaxOffset = - (mMax - 1) * mRulerDistance;
// 默认刻度尺起始点在控件宽度中心
int centralPoint = getCentralPoint();
for (int i = 0; i < mMax; i++) {
float startX = centralPoint + i * mRulerDistance + mOffsetX;
float startY = 0;
float stopX = startX;
float stopY;
if (i % 10 == 0) {
stopY = mMaxLineHeight;
drawRulerText(canvas, i, startX, stopY);
}
else if (i % 5 == 0) {
stopY = mMiddleLineHeight;
}
else {
stopY = mMinLineHeight;
}
canvas.drawLine(startX, startY, stopX, stopY, mPaintRuler);
}
drawRulerCentralLine(canvas);
}
/**
* 绘制刻度尺文字
* @param canvas
*/
private void drawRulerText(Canvas canvas,int i, float startX, float stopY) {
if (isShowText) {
String text = String.valueOf(i);
mPaintRuler.setTextSize(mTextSize);
float valueW = mPaintRuler.measureText(text);
canvas.drawText(text, startX - valueW / 2, stopY + mTextSize, mPaintRuler);
}
}
/**
* 获取中心点位置
*
* @return
*/
private int getCentralPoint() {
return getWidth() / 2;
}
/**
* 画中间的红色指示线
*
* @param canvas
*/
private void drawRulerCentralLine(Canvas canvas) {
canvas.save();
mPaintRulerCentralLine.setStrokeWidth(mRulerWidth);
mPaintRulerCentralLine.setColor(mRulerColor);
canvas.drawLine(getCentralPoint(), 0, getCentralPoint(), mCentralLineHeight, mPaintRulerCentralLine);
canvas.restore();
}
/**
* 获取有效的偏移量 这里面的offset和mMaxOffset都是负数
*
* @return
*/
protected float getValidOffset(float offset) {
// 这里的mMaxOffset是最小负数,相当于小值
int min = mMaxOffset;
// 这里的0,相当于最大值了
int max = 0;
if (offset <= min) {
offset = min;
} else if (offset >= max) {
offset = max;
}
return mOffsetX = offset;
}
/**
* 是无效范围
* @param offset
* @return
*/
protected boolean isInvalidOffset(float offset) {
// 这里的mMaxOffset是最小负数,相当于小值
int min = mMaxOffset;
// 这里的0,相当于最大值了
int max = 0;
return offset < min || offset>max;
}
/**
* 将进度值转换为坐标
*
* @param offsetX
* @return
*/
private int progressToOffsetX(int progress) {
return (int) -(getRulerWidth() / 2 + progress * mRulerDistance);
}
/**
* 设置动画效果
* @param offset
*/
@SuppressLint("NewApi")
private void setAnim(final float offset) {
mTargetOffset = offset;
if (mTimeAnimator == null) {
mTimeAnimator = new TimeAnimator();
mTimeAnimator.setTimeListener(new TimeListener() {
@Override
public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
//意思就是传递进来的mTargetOffset值如果大于现有的mThumbOffset,那么就应该自增达到mTargetOffset
if (mTargetOffset > mOffsetX) {
mOffsetX = getTempOffset(true);
mProgress = (int) (Math.abs(mOffsetX / mRulerDistance));
notifyProgressChange(mProgress, true);
//当mThumbOffset在进行自增,等于或者大于了目标值mTargetOffset,就应该停止
if (mTargetOffset <= mOffsetX) {
mOffsetX = mTargetOffset;
notifyProgressChange(mProgress, false);
stopAnim();
}
}
//意思就是传递进来的mTargetOffset值如果小于现有的mThumbOffset,那么就应该自减达到mTargetOffset
else if (mTargetOffset < mOffsetX) {
mOffsetX = getTempOffset(false);
mProgress = (int) (Math.abs(mOffsetX / mRulerDistance));
notifyProgressChange(mProgress, true);
//当mThumbOffset在进行自减,等于或者小于了目标值mTargetOffset,就应该停止
if (mTargetOffset >= mOffsetX) {
mOffsetX = mTargetOffset;
notifyProgressChange(mProgress, false);
stopAnim();
}
}else{
stopAnim();
}
postInvalidate();
}
});
}
startAnim();
}
/**
* 获取临时,自增,或者自减偏移量
* @param isAdd
* @return
*/
private float getTempOffset(boolean isAdd) {
float offset;
if (isAdd) {
offset = mOffsetX + mAnimSpeed;
} else {
offset = mOffsetX - mAnimSpeed;
}
offset = getValidOffset(offset);
return offset;
}
/**
* 开机动画
*/
private void startAnim() {
if (mTimeAnimator != null && !mTimeAnimator.isStarted()) {
mTimeAnimator.start();
}
}
/**
* 结束动画
*/
private void stopAnim() {
if (mTimeAnimator != null && mTimeAnimator.isStarted()) {
mTimeAnimator.end();
}
}
}