原 吉他gay boy 地址:https://github.com/ZBJDSBJ/ScaleRuler
原博客地址:https://blog.csdn.net/zbjdsbj/article/details/51180011
侵删
package com.vortex.rxtest;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.Scroller;
import java.util.ArrayList;
/**
* Created by zoubo on 16/2/26.
* 小数点横向滚动刻度尺
*/
public class DecimalScaleRulerViewextends View {
private ArrayListtimeData =new ArrayList<>();
private int mMinVelocity; //最小滑动距离
private ScrollermScroller;
private VelocityTrackermVelocityTracker;
private int mWidth; //view 宽度
private int mHeight;
private float mValue =10;
private float mMaxValue =24;
private float mMinValue =0;
private int perNumber =12; //两个值之间的 精确度格子
private int mItemSpacing =5; //item 间距
private int mPerSpanValue =5; //每隔的值
private int bigPerSpanValue =perNumber *mPerSpanValue; //一大格的值
private int mMaxLineHeight =40;
private int mMiddleLineHeight =35;
private int mMinLineHeight =35;
private int mLineWidth;
private int mTextMarginTop =5;
private float mTextHeight;
private PaintmTextPaint; // 绘制文本的画笔
private PaintmLinePaint;
private PaintbgPaint;
private int mTotalLine; //共有这么多条线
private int mMaxOffset; //最大偏移量
private float mOffset; // 默认尺起始点在屏幕中心, offset是指尺起始点的偏移值 当前偏移量
private int mLastX, mMove;
private OnValueChangeListenermListener;
public DecimalScaleRulerView(Context context) {
this(context, null);
init(context);
}
public DecimalScaleRulerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
init(context);
}
public DecimalScaleRulerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
protected void init(Context context) {
mScroller =new Scroller(context);
mMinVelocity = ViewConfiguration.get(getContext()).getScaledMinimumFlingVelocity();
mItemSpacing = DrawUtil.dip2px(14);
mLineWidth = DrawUtil.dip2px(1);
mTextMarginTop = DrawUtil.dip2px(11);
mTextPaint =new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextSize(DrawUtil.sp2px(16));
mTextPaint.setColor(0X80222222);
mTextHeight = TextUtil.getFontHeight(mTextPaint);
bgPaint =new Paint();
bgPaint.setStyle(Paint.Style.FILL);
bgPaint.setAntiAlias(true);
bgPaint.setAlpha(200);
bgPaint.setColor(Color.BLUE);
mLinePaint =new Paint(Paint.ANTI_ALIAS_FLAG);
mLinePaint.setStrokeWidth(mLineWidth);
mLinePaint.setColor(0X80222222);
mTotalLine = (int) (mMaxValue *bigPerSpanValue -mMinValue *bigPerSpanValue) /mPerSpanValue +1;
mMaxOffset = -(mTotalLine -1) *mItemSpacing;
mOffset = (mMinValue -mValue) *perNumber *mItemSpacing;
}
public void setParam(int itemSpacing, int maxLineHeight, int middleLineHeight, int minLineHeight, int textMarginTop, int textSize) {
mItemSpacing = itemSpacing;
mMaxLineHeight = maxLineHeight;
mMiddleLineHeight = middleLineHeight;
mMinLineHeight = minLineHeight;
mTextMarginTop = textMarginTop;
mTextPaint.setTextSize(textSize);
}
public void initViewParam(float defaultValue, float minValue, float maxValue, int spanValue) {
this.mValue = defaultValue;
this.mMaxValue = maxValue;
this.mMinValue = minValue;
this.mPerSpanValue = spanValue;
this.mTotalLine = (int) (maxValue *10 - minValue *10) / spanValue +1;
mMaxOffset = -(mTotalLine -1) *mItemSpacing;
mOffset = (minValue - defaultValue) / spanValue *mItemSpacing *10;
invalidate();
setVisibility(VISIBLE);
}
/**
* 设置用于接收结果的监听器
*
* @param listener
*/
public void setValueChangeListener(OnValueChangeListener listener) {
mListener = listener;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w >0 && h >0) {
mWidth = w;
mHeight = h;
}
}
public void setTimeData(ArrayList sData) {
timeData.clear();
timeData.addAll(sData);
postInvalidate();
}
private void DrawBg(Canvas mcanvas,int srcPointX,float mOffset) {
for (TimeModeltimeModel :timeData) {
int start =timeModel.startTime;
int end =timeModel.endTime;
float sPercent = (start / (mMaxValue *bigPerSpanValue)) * Math.abs(mMaxOffset)+srcPointX+mOffset;
float ePercent = (end / (mMaxValue *bigPerSpanValue)) * Math.abs(mMaxOffset)+srcPointX+mOffset;
RectFrect =new RectF(sPercent, 0, ePercent, mHeight-100);
mcanvas.drawRect(rect, bgPaint);
}
}
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
float left, height;
Stringvalue;
int alpha;
float scale;
/**
* 相当于起始点右移了半个屏幕
*/
int srcPointX =mWidth /2; // 默认表尺起始点在屏幕中心
DrawBg(canvas,srcPointX,mOffset);
for (int i =0; i
/**
* 这里相当于移动的不是view 而是坐标原点
* srcPointX是因为在中间,相当于右移正的半个屏幕,然后 移动的距离 mOffset 就是坐标点,从这里
* 开始画整个view
*/
left =srcPointX +mOffset +i *mItemSpacing;
if (left <0 ||left >mWidth) {
continue;
}
if (i %perNumber ==0) {
height =mHeight -mMinLineHeight;
mLinePaint.setColor(Color.BLUE);
}else if (i % (perNumber /2) ==0) {
height =mHeight -mMiddleLineHeight;
mLinePaint.setColor(Color.GREEN);
}else {
mLinePaint.setColor(Color.GRAY);
height =mHeight -mMaxLineHeight;
}
// scale = 1 - Math.abs(left - srcPointX) / srcPointX;
// alpha = (int) (255 * scale * scale);
// mLinePaint.setAlpha(alpha);
canvas.drawLine(left, 0, left, height, mLinePaint);
if (i %perNumber ==0) {// 大指标,要标注文字
value = String.valueOf((int) (mMinValue +i /perNumber));
// mTextPaint.setAlpha(alpha);
canvas.drawText(value, left -mTextPaint.measureText(value) /2,
height +mTextMarginTop +mTextHeight - DrawUtil.dip2px(3), mTextPaint);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
int xPosition = (int) event.getX();
if (mVelocityTracker ==null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
switch (action) {
case MotionEvent.ACTION_DOWN:
mScroller.forceFinished(true);
mLastX =xPosition;
mMove =0;
break;
case MotionEvent.ACTION_MOVE:
mMove = (mLastX -xPosition);
changeMoveAndValue();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
countMoveEnd();
countVelocityTracker();
return false;
// break;
default:
break;
}
mLastX =xPosition;
return true;
}
private void countVelocityTracker() {
mVelocityTracker.computeCurrentVelocity(1000);
float xVelocity =mVelocityTracker.getXVelocity();
if (Math.abs(xVelocity) >mMinVelocity) {
mScroller.fling(0, 0, (int)xVelocity, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
}
}
/**
* mOffset是个负值
*/
private void countMoveEnd() {
mOffset -=mMove;
if (mOffset <=mMaxOffset) {
mOffset =mMaxOffset;
}else if (mOffset >=0) {
mOffset =0;
}
mLastX =0;
mMove =0;
mValue =mMinValue *bigPerSpanValue + Math.round(Math.abs(mOffset) *1.0f /mItemSpacing) *mPerSpanValue;
mOffset = (mMinValue *bigPerSpanValue -mValue) /mPerSpanValue *mItemSpacing; // 矫正位置,保证不会停留在两个相邻刻度之间
notifyValueChange();
postInvalidate();
}
private void changeMoveAndValue() {
mOffset -=mMove;
if (mOffset <=mMaxOffset) {
mOffset =mMaxOffset;
mMove =0;
mScroller.forceFinished(true);
}else if (mOffset >=0) {
mOffset =0;
mMove =0;
mScroller.forceFinished(true);
}
mValue =mMinValue *bigPerSpanValue + Math.round(Math.abs(mOffset) *1.0f /mItemSpacing) *mPerSpanValue;
notifyValueChange();
postInvalidate();
}
private void notifyValueChange() {
if (null !=mListener) {
mListener.onValueChange(mValue);
}
}
public interface OnValueChangeListener {
void onValueChange(float value);
}
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {
if (mScroller.getCurrX() ==mScroller.getFinalX()) {// over
countMoveEnd();
}else {
int xPosition =mScroller.getCurrX();
mMove = (mLastX -xPosition);
changeMoveAndValue();
mLastX =xPosition;
}
}
}
}
网友评论