自定義View畫一個身高測量尺子,能夠理解成一個豎着的尺子java
最近恰好有空,在家裏整理這幾年工做內容,簡單記錄一下,也方便之後本身查閱,最終效果圖以下android
步驟以下:git
首先仍是繼承view,重寫onMeasure()方法github
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); } /** * 測量控件所需寬度 */ public int measureWidth(int widthMeasureSpec) { switch (MeasureSpec.getMode(widthMeasureSpec)) { case MeasureSpec.AT_MOST: case MeasureSpec.UNSPECIFIED: { switch (mOrientation) { case HORIZONTAL: { return mLines * space; } case VERTICAL: default: { float textWidth = mTextPaint.measureText(String.valueOf(mLines / mSetupValue)); float width = textWidth + mLongLineLength + mMarkerWidth + mMarkerSpace + getPaddingLeft() + getPaddingRight(); return (int) width; } } } case MeasureSpec.EXACTLY: default: return MeasureSpec.getSize(widthMeasureSpec); } } /** * 測量控件所需高度 */ public int measureHeight(int heightMeasureSpec) { switch (MeasureSpec.getMode(heightMeasureSpec)) { case MeasureSpec.AT_MOST: case MeasureSpec.UNSPECIFIED: { switch (mOrientation) { case HORIZONTAL: { float height = mTextPaint.getTextSize() + mLongLineLength + mMarkerWidth + mMarkerSpace + getPaddingTop() + getPaddingBottom(); return (int) height; } case VERTICAL: default: { return mLines * space; } } } case MeasureSpec.EXACTLY: default: return MeasureSpec.getSize(heightMeasureSpec); } }
第二步會在onDraw()方法中繪製當前View,此時繪製的view也是初始時的viewcanvas
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); adjustMarker(false); canvas.drawColor(mBackgroundColor); switch (mOrientation) { case VERTICAL: drawVertical(canvas); break; case HORIZONTAL: drawHorizontal(canvas); break; } }
默認狀況下不會調整標記view的位置。固然標記的位置能夠時固定的,也能夠不固定的,固定的話就是滾動尺子的位置數組
畫圖的時候,先畫紅色標尺的位置,而後畫刻度的位置,刻度的位置每10個畫一根長線,就是每10個分爲1組,具體代碼以下:app
/** * 繪製 方向爲垂直方向時的佈局 * * @param canvas 畫布 */ protected void drawVertical(Canvas canvas) { //vertical mode // bottom start position int bottom = getHeight() - getPaddingBottom(); int left = getPaddingLeft(); float maxTextWidth = mTextPaint.measureText(String.valueOf((mLines+mStartLineValue) / mOutSideLine * mSetupValue)); int shakeCenter = (getHeight() >> 1) + getScrollY(); resetLinesArr(); for (int i = 0; i <= mLines; i++) { int value = mStartLineValue + (i * mSetupValue); float lineLength; switch (i % mOutSideLine) { case ZERO: String text = String.valueOf(value); float currentTextWidth = mTextPaint.measureText(text); canvas.drawText(text, left + (maxTextWidth - currentTextWidth) / 2, bottom - i * space, mTextPaint); lineLength = mLongLineLength; break; default: lineLength = mShortLineLength; break; } mLinesArr[i * 4] = left + maxTextWidth; mLinesArr[i * 4 + 1] = bottom - i * space; mLinesArr[i * 4 + 2] = left + maxTextWidth + lineLength; mLinesArr[i * 4 + 3] = bottom - i * space; } //繪製線 canvas.drawLines(mLinesArr, mPaint); //繪製高亮線 canvas.drawLine(left + maxTextWidth, bottom - mCurrentLineIndex * space, left + maxTextWidth + (((mCurrentLineIndex) % mOutSideLine == 0) ? mLongLineLength : mShortLineLength), bottom - mCurrentLineIndex * space, mHighlightPaint); }
第三個比較重要的是觸摸事件,每一次向上或者向下都要重繪刷新當前Viewide
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: if (!mOverScroller.isFinished()) mOverScroller.abortAnimation(); //adjustMarker(true); break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: adjustMarker(true); break; } mGestureDetector.onTouchEvent(event); return true; }
全部具體代碼以下:佈局
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.util.TypedValue; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import com.bingo.customer.R; import java.util.Arrays; /** * 身高體重測量控件 * 這個控件是爲了項目中的身高體重選擇而設計編碼的 * 不適合多數據狀況,由於沒有使用任何的回收機制 * */ public class HeightView extends View { /** * 水平方向 */ public static final int HORIZONTAL = 1; /** * 垂直方向 */ public static final int VERTICAL = 2; public static final int ZERO = 0; /** * 默認的阻尼係數 */ public static final float DEFAULT_RATIO = 2.0f; private static final String TAG = "HeightView"; /** * 阻尼係數,在fling下的阻力,阻力越大就飛的就約慢 */ private float ratio = DEFAULT_RATIO; /** * 須要繪製多少行 */ private int mLines = 240; /** * 突出行 就是長線 那一行 */ private int mOutSideLine = 10; /** * 每一個outSideLine的步進值 * 好比: * 步進值是 5 那麼就是 0,5,10,15,20 * 步進值是 10 那麼就是 0,10,20,30,40 */ private int mSetupValue = 1; /** * 每一個格子的間距 */ private int space; /** * 用於普通繪製的畫筆 */ private Paint mPaint; /** * 繪製文本的畫筆 */ private Paint mTextPaint; /** * 短線的長度 */ private float mShortLineLength; /** * 長線的長度 */ private float mLongLineLength; /** * 高亮畫筆,繪製選中線的 */ private Paint mHighlightPaint; /** * Marker畫筆 */ private Paint mMarkerPaint; /** * scroller 用於滾動的輔助類 */ private OverScroller mOverScroller; /** * 手勢探測器 用於探測手勢 */ private GestureDetector mGestureDetector; /** * 高亮色選擇中的顏色 */ private int mHighLightColor; /** * 文本顏色 */ private int mTextColor; /** * 文本大小 */ private float mTextSize; /** * 高亮的線的寬度 */ private float mHighlightWidth; /** * 普通的線的寬度 */ private float mLineWidth; /** * 線條的顏色 */ private int mLineColor; /** * 上一次是不是fling模式 */ private boolean mPreviousIsFling = false; /** * 開始行 * 若是開始行爲 0,步進值爲10 * 則 0,10,20,30,40 * 若是開始行爲 10,步進值爲10 * 則 100,110,120,130 */ private int mStartLineValue = 0; /** * 用於記錄當前的marker的位置 */ private int mCurrentLineIndex; /** * 保存線位置的數組 */ private float[] mLinesArr = new float[4]; /** * 重力方向 */ private int mOrientation = VERTICAL; /** * 指示器的寬度 */ private int mMarkerWidth = 45; /** * 指示器和長線的距離 */ private int mMarkerSpace = 20; /** * 背景色 */ private int mBackgroundColor = Color.parseColor("#03b7ee"); /** * 標記物路徑 */ private Path mMarkerPath; /** * Marker顏色 */ private int mMarkerColor; private OnItemChangedListener mOnItemChangedListener; public HeightView(Context context) { super(context); init(); } public HeightView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public HeightView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); if (attrs != null) { TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.HeightView, defStyleAttr, 0); mOrientation = attributes.getInt(R.styleable.HeightView_orientation, VERTICAL); mBackgroundColor = attributes.getColor(R.styleable.HeightView_backgroundColor, mBackgroundColor); mTextColor = attributes.getColor(R.styleable.HeightView_textColor, mTextColor); mTextPaint.setColor(mTextColor); mTextSize = attributes.getDimension(R.styleable.HeightView_textSize, mTextSize); mTextPaint.setTextSize(mTextSize); mHighLightColor = attributes.getColor(R.styleable.HeightView_highlightColor, mHighLightColor); mHighlightPaint.setColor(mHighLightColor); mHighlightWidth = attributes.getDimension(R.styleable.HeightView_highlightLineWidth, mHighlightWidth); mHighlightPaint.setStrokeWidth(mHighlightWidth); mMarkerColor = attributes.getColor(R.styleable.HeightView_markerColor, mMarkerColor); mMarkerPaint.setColor(mMarkerColor); mLineColor = attributes.getColor(R.styleable.HeightView_mlineColor, mLineColor); mPaint.setColor(mLineColor); mLineWidth = attributes.getDimension(R.styleable.HeightView_lineWidth, mLineWidth); mPaint.setStrokeWidth(mLineWidth); ratio = attributes.getFloat(R.styleable.HeightView_ratio, ratio); mMarkerSpace = attributes.getDimensionPixelOffset(R.styleable.HeightView_markerSpace, mMarkerSpace); mLines = attributes.getInt(R.styleable.HeightView_lines, mLines); mStartLineValue = attributes.getInt(R.styleable.HeightView_startLineValue, mStartLineValue); mMarkerWidth = attributes.getDimensionPixelOffset(R.styleable.HeightView_markerSize, mMarkerWidth); attributes.recycle(); } } /** * 初始化所需條件 */ private void init() { setLayerType(LAYER_TYPE_HARDWARE, null); space = (int) (getResources().getDisplayMetrics().density * 7); mHighLightColor = Color.parseColor("#1e7d9e"); mTextColor = mMarkerColor = Color.WHITE; mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics()); mShortLineLength = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getResources().getDisplayMetrics()); mLongLineLength = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, getResources().getDisplayMetrics()); mHighlightWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1.5f, getResources().getDisplayMetrics()); mLineWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics()); mMarkerPath = new Path(); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(mLineColor = Color.WHITE); mPaint.setStrokeWidth(mLineWidth); mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextPaint.setTextSize(mTextSize); mTextPaint.setStyle(Paint.Style.FILL); mTextPaint.setColor(mTextColor); mTextPaint.setTextAlign(Paint.Align.CENTER); mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mHighlightPaint.setStyle(Paint.Style.STROKE); mHighlightPaint.setColor(mHighLightColor); mHighlightPaint.setStrokeWidth(mHighlightWidth); mMarkerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mHighlightPaint.setStyle(Paint.Style.FILL); mHighlightPaint.setColor(mMarkerColor); mOverScroller = new OverScroller(getContext()); mGestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { switch (mOrientation) { case VERTICAL: { //往上滾動 if (distanceY > 0) { //最大滾動到Marker位置 int distance = (getHeight() >> 1) - getPaddingBottom()/* - (mStartLineValue) * space*/; if (getScrollY() + distanceY > distance) { scrollTo(0, distance); ViewCompat.postInvalidateOnAnimation(HeightView.this); } else if (getScrollY() + distanceY < distance) { scrollBy(0, (int) distanceY); ViewCompat.postInvalidateOnAnimation(HeightView.this); } //往下滾動 } else if (distanceY < 0) { int minDistance = (mLines * space - (getHeight() >> 1)) + getPaddingBottom(); if (getScrollY() < -minDistance) { scrollTo(0, -minDistance); ViewCompat.postInvalidateOnAnimation(HeightView.this); } else if (getScrollY() > -minDistance) { scrollBy(0, (int) distanceY); ViewCompat.postInvalidateOnAnimation(HeightView.this); } } } break; case HORIZONTAL: { //往左滾動 if (distanceX > 0) { int maxX = (mLines /*+ mStartLineValue*/) * space - (getWidth() >> 1) + getPaddingLeft(); if (getScrollX() + distanceX > maxX) { scrollTo(maxX, 0); ViewCompat.postInvalidateOnAnimation(HeightView.this); } else if (getScrollX() + distanceX <= maxX) { scrollBy((int) distanceX, 0); ViewCompat.postInvalidateOnAnimation(HeightView.this); } //往右滾動 } else if (distanceX < 0) { int minX = -((getWidth() >> 1) - getPaddingLeft()); if (getScrollX() + distanceX < minX) { scrollTo(minX, 0); ViewCompat.postInvalidateOnAnimation(HeightView.this); } else if (getScrollX() + distanceX >= minX) { scrollBy((int) distanceX, 0); ViewCompat.postInvalidateOnAnimation(HeightView.this); } } } break; } return true; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { switch (mOrientation) { case VERTICAL: { int minDistance = ((mLines) * space - (getHeight() >> 1)) + getPaddingBottom(); int maxDistance = (getHeight() >> 1) - getPaddingBottom(); mOverScroller.fling(0, getScrollY(), 0, (int) (-velocityY / ratio), 0, 0, -minDistance, maxDistance, 0, 100); } break; case HORIZONTAL: { int minX = -((getWidth() >> 1) - getPaddingLeft()); int maxX = (mLines /*+ mStartLineValue*/) * space - (getWidth() >> 1) + getPaddingLeft(); mOverScroller.fling(getScrollX(), 0, (int) (-velocityX / ratio), 0, minX, maxX, 0, 0, 100, 0); } break; } ViewCompat.postInvalidateOnAnimation(HeightView.this); return true; } }); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); } /** * 測量控件所需寬度 */ public int measureWidth(int widthMeasureSpec) { switch (MeasureSpec.getMode(widthMeasureSpec)) { case MeasureSpec.AT_MOST: case MeasureSpec.UNSPECIFIED: { switch (mOrientation) { case HORIZONTAL: { return mLines * space; } case VERTICAL: default: { float textWidth = mTextPaint.measureText(String.valueOf(mLines / mSetupValue)); float width = textWidth + mLongLineLength + mMarkerWidth + mMarkerSpace + getPaddingLeft() + getPaddingRight(); return (int) width; } } } case MeasureSpec.EXACTLY: default: return MeasureSpec.getSize(widthMeasureSpec); } } /** * 測量控件所需高度 */ public int measureHeight(int heightMeasureSpec) { switch (MeasureSpec.getMode(heightMeasureSpec)) { case MeasureSpec.AT_MOST: case MeasureSpec.UNSPECIFIED: { switch (mOrientation) { case HORIZONTAL: { float height = mTextPaint.getTextSize() + mLongLineLength + mMarkerWidth + mMarkerSpace + getPaddingTop() + getPaddingBottom(); return (int) height; } case VERTICAL: default: { return mLines * space; } } } case MeasureSpec.EXACTLY: default: return MeasureSpec.getSize(heightMeasureSpec); } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: if (!mOverScroller.isFinished()) mOverScroller.abortAnimation(); //adjustMarker(true); break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: adjustMarker(true); break; } mGestureDetector.onTouchEvent(event); return true; } @Override public boolean performClick() { return super.performClick(); } /** * 調整目前選擇中的條目 */ public void adjustMarker(boolean adjustPosition) { final int previous = mCurrentLineIndex; switch (mOrientation) { case VERTICAL: { int startY = (getHeight() >> 1) - getPaddingBottom(); int scrollY = getScrollY(); int progress = scrollY - startY; mCurrentLineIndex = -progress / space; if (mCurrentLineIndex > mLines) mCurrentLineIndex = mLines; else if (mCurrentLineIndex < 0) mCurrentLineIndex = 0; int expectY = space * -mCurrentLineIndex + startY; if (adjustPosition && scrollY != expectY) { //scrollTo(0, expectY); mOverScroller.startScroll(0, getScrollY(), 0, expectY - scrollY, 0); ViewCompat.postInvalidateOnAnimation(this); } } break; case HORIZONTAL: { int startX = -((getWidth() >> 1) - getPaddingLeft()); int scrollX = getScrollX(); int progress = startX - scrollX; mCurrentLineIndex = -progress / space; if (mCurrentLineIndex > mLines) mCurrentLineIndex = mLines; else if (mCurrentLineIndex < 0) mCurrentLineIndex = 0; int expectX = space * mCurrentLineIndex + startX; if (adjustPosition && scrollX != expectX) { //scrollTo(0, expectY); mOverScroller.startScroll(getScrollX(), 0, expectX - scrollX, 0, 0); ViewCompat.postInvalidateOnAnimation(this); } } break; } if (previous != mCurrentLineIndex) onValueChanged(); } /** * 當值可能發生變化後執行 */ public void onValueChanged() { if (mCurrentLineIndex >= 0 && mCurrentLineIndex <= mLines) { int index = mCurrentLineIndex; int value = mStartLineValue + (index * mSetupValue); if (mOnItemChangedListener != null) mOnItemChangedListener.onItemChanged(index, value); } } @Override public void computeScroll() { if (mOverScroller.computeScrollOffset()) { mPreviousIsFling = true; switch (mOrientation) { case VERTICAL: scrollTo(0, mOverScroller.getCurrY()); break; case HORIZONTAL: scrollTo(mOverScroller.getCurrX(), 0); break; } ViewCompat.postInvalidateOnAnimation(this); } else { if (mPreviousIsFling) { mPreviousIsFling = false; adjustMarker(true); } } } /** * 重置線組 */ private void resetLinesArr() { if (mLinesArr.length < (mLines + 1) * 4) { //須要從新建立數組 mLinesArr = new float[(mLines + 1) * 4]; } else { Arrays.fill(mLinesArr, 0); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); adjustMarker(false); canvas.drawColor(mBackgroundColor); switch (mOrientation) { case VERTICAL: drawVertical(canvas); break; case HORIZONTAL: drawHorizontal(canvas); break; } } /** * 繪製 方向爲垂直方向時的佈局 * * @param canvas 畫布 */ protected void drawVertical(Canvas canvas) { //vertical mode // bottom start position int bottom = getHeight() - getPaddingBottom(); int left = getPaddingLeft(); float maxTextWidth = mTextPaint.measureText(String.valueOf((mLines+mStartLineValue) / mOutSideLine * mSetupValue)); int shakeCenter = (getHeight() >> 1) + getScrollY(); //繪製三角形 //若是想使用圖片,能夠自行繪製圖片 // mMarkerPath.reset(); // mMarkerPath.moveTo(left + maxTextWidth + mLongLineLength + mMarkerSpace, shakeCenter); // mMarkerPath.lineTo(left + maxTextWidth + mLongLineLength + mMarkerSpace + mMarkerWidth, shakeCenter - mMarkerWidth); // mMarkerPath.lineTo(left + maxTextWidth + mLongLineLength + mMarkerSpace + mMarkerWidth, shakeCenter + mMarkerWidth); // mMarkerPath.lineTo(left + maxTextWidth + mLongLineLength + mMarkerSpace, shakeCenter); // canvas.drawPath(mMarkerPath, mMarkerPaint); resetLinesArr(); for (int i = 0; i <= mLines; i++) { int value = mStartLineValue + (i * mSetupValue); float lineLength; switch (i % mOutSideLine) { case ZERO: String text = String.valueOf(value); float currentTextWidth = mTextPaint.measureText(text); canvas.drawText(text, left + (maxTextWidth - currentTextWidth) / 2, bottom - i * space, mTextPaint); lineLength = mLongLineLength; break; default: lineLength = mShortLineLength; break; } mLinesArr[i * 4] = left + maxTextWidth; mLinesArr[i * 4 + 1] = bottom - i * space; mLinesArr[i * 4 + 2] = left + maxTextWidth + lineLength; mLinesArr[i * 4 + 3] = bottom - i * space; } //繪製線 canvas.drawLines(mLinesArr, mPaint); //繪製高亮線 canvas.drawLine(left + maxTextWidth, bottom - mCurrentLineIndex * space, left + maxTextWidth + (((mCurrentLineIndex) % mOutSideLine == 0) ? mLongLineLength : mShortLineLength), bottom - mCurrentLineIndex * space, mHighlightPaint); } /** * 繪製水平方向上的佈局 * * @param canvas 畫布 */ protected void drawHorizontal(Canvas canvas) { //Horizontal mode // bottom position int bottom = getHeight() - getPaddingBottom(); int left = getPaddingLeft(); float maxTextWidth = mTextPaint.measureText(String.valueOf(mLines / mOutSideLine * mSetupValue)); //中心 int shakeCenter = (getWidth() >> 1) + getScrollX(); //三角形頂點 float vertexY = getHeight() - getPaddingBottom() - mTextPaint.getTextSize() - mLongLineLength - mMarkerSpace; //繪製三角形 mMarkerPath.reset(); mMarkerPath.moveTo(shakeCenter, vertexY); mMarkerPath.lineTo(shakeCenter - mMarkerWidth, vertexY - mMarkerWidth); mMarkerPath.lineTo(shakeCenter + mMarkerWidth, vertexY - mMarkerWidth); mMarkerPath.lineTo(shakeCenter, vertexY); canvas.drawPath(mMarkerPath, mMarkerPaint); //驗證線組 resetLinesArr(); //生成線組 for (int i = 0; i <= mLines; i++) { int value = mStartLineValue + (i * mSetupValue); float lineLength; switch (i % mOutSideLine) { case ZERO: String text = String.valueOf(value); canvas.drawText(text, left + i * space, bottom, mTextPaint); lineLength = mLongLineLength; break; default: lineLength = mShortLineLength; break; } /*startX*/ mLinesArr[i * 4] = left + i * space; /*startY*/ mLinesArr[i * 4 + 1] = bottom - mTextPaint.getTextSize(); /*stopX*/ mLinesArr[i * 4 + 2] = left + i * space; /*stopY*/ mLinesArr[i * 4 + 3] = bottom - (mTextPaint.getTextSize() + lineLength); } //繪製線組 canvas.drawLines(mLinesArr, mPaint); // //繪製當前選中的線條 canvas.drawLine(left + mCurrentLineIndex * space, (bottom - mTextPaint.getTextSize()), left + mCurrentLineIndex * space, (bottom - mTextPaint.getTextSize()) - (mCurrentLineIndex % mOutSideLine == 0 ? mLongLineLength : mShortLineLength), mHighlightPaint); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); adjustMarker(true); } public int getLines() { return mLines; } public void setLines(int mLines) { this.mLines = mLines; requestLayout(); } public int getOutSideLine() { return mOutSideLine; } public void setOutSideLine(int mOutSideLine) { this.mOutSideLine = mOutSideLine; invalidate(); } public int getSetupValue() { return mSetupValue; } public void setSetupValue(int mSetupValue) { this.mSetupValue = mSetupValue; invalidate(); } public int getCurrentLineIndex() { return mCurrentLineIndex; } public void setCurrentLineIndex(int currentLineIndex) { int distance = currentLineIndex * space; if (mOverScroller != null && !mOverScroller.isFinished()) mOverScroller.abortAnimation(); switch (mOrientation) { case HORIZONTAL: int startX = (getWidth() >> 1) - getPaddingLeft(); scrollTo(distance - startX, getScrollY()); break; case VERTICAL: int startY = ((getHeight() >> 1) - getPaddingBottom()); scrollTo(getScrollX(), -distance + startY); break; } adjustMarker(true); postInvalidate(); } public int getSpace() { return space; } public void setSpace(int space) { this.space = space; requestLayout(); } public float getShortLineLength() { return mShortLineLength; } public void setShortLineLength(float mShortLineLength) { this.mShortLineLength = mShortLineLength; invalidate(); } public float getLongLineLength() { return mLongLineLength; } public void setLongLineLength(float mLongLineLength) { this.mLongLineLength = mLongLineLength; invalidate(); } public int getHighLightColor() { return mHighLightColor; } public void setHighLightColor(int highLightColor) { this.mHighLightColor = highLightColor; mHighlightPaint.setColor(highLightColor); invalidate(); } public int getTextColor() { return mTextColor; } public void setTextColor(int textColor) { this.mTextColor = textColor; mTextPaint.setColor(textColor); invalidate(); } public float getTextSize() { return mTextSize; } public void setTextSize(float textSize) { this.mTextSize = textSize; mTextPaint.setTextSize(textSize); requestLayout(); } public float getHighlightWidth() { return mHighlightWidth; } public void setHighlightWidth(float highlightWidth) { this.mHighlightWidth = highlightWidth; mHighlightPaint.setStrokeWidth(highlightWidth); requestLayout(); } public float getLineWidth() { return mLineWidth; } public void setLineWidth(float lineWidth) { this.mLineWidth = lineWidth; mPaint.setStrokeWidth(lineWidth); requestLayout(); } public int getLineColor() { return mLineColor; } public void setLineColor(int lineColor) { this.mLineColor = lineColor; mPaint.setColor(lineColor); invalidate(); } public int getStartLineValue() { return mStartLineValue; } public void setStartLineValue(int startLineValue) { this.mStartLineValue = startLineValue; requestLayout(); } public int getOrientation() { return mOrientation; } public void setOrientation(int orientation) { this.mOrientation = orientation; requestLayout(); } public int getMarkerWidth() { return mMarkerWidth; } public void setMarkerWidth(int markerWidth) { this.mMarkerWidth = markerWidth; requestLayout(); } public int getMarkerSpace() { return mMarkerSpace; } public void setMarkerSpace(int markerSpace) { this.mMarkerSpace = markerSpace; requestLayout(); } public int getBackgroundColor() { return mBackgroundColor; } public void setBackgroundColor(int backgroundColor) { this.mBackgroundColor = backgroundColor; invalidate(); } public int getMarkerColor() { return mMarkerColor; } public void setMarkerColor(int markerColor) { this.mMarkerColor = markerColor; mMarkerPaint.setColor(markerColor); invalidate(); } public float getRatio() { return ratio; } /** * 設置阻尼係數 * * @param ratio 須要設置的阻尼係數,默認的是 {@link #DEFAULT_RATIO} */ public void setRatio(float ratio) { this.ratio = ratio; } /** * 設置item變化監聽器 * * @param listener 須要設置item變化監聽器 */ public void setOnItemChangedListener(OnItemChangedListener listener) { this.mOnItemChangedListener = listener; } /** * 條目變化監聽器 */ public interface OnItemChangedListener { /** * 當條目發生變化後調用 * * @param index 當前的選擇中的條目的下表 * @param value 選擇中的條目的值 */ void onItemChanged(int index, int value); } }