首先这段代码是网上有的不过我进行了修改

package com.sfqj.view;  
   




import com.sfqj.yingsu.R;


import android.annotation.SuppressLint;  
import android.content.Context;  
import android.graphics.Canvas;  
import android.graphics.Color;  
import android.graphics.Paint;  
import android.graphics.drawable.Drawable;  
import android.graphics.drawable.GradientDrawable;  
import android.text.Layout;  
import android.text.TextPaint;  
import android.util.AttributeSet;  
import android.view.MotionEvent;  
import android.view.VelocityTracker;  
import android.view.View;  
import android.view.ViewConfiguration;  
import android.widget.Scroller;  
   
  
   
/** 
 *  
 * @author SunXinxin 
 * @version create:2015年9月17日 
 */ 
@SuppressLint("ClickableViewAccessibility")  
public class RuleView extends View {  
   
    public interface OnValueChangeListener {  
        public void onValueChange(float value);  
    }  
   
    public static final int MOD_TYPE_HALF = 2;  
    public static final int MOD_TYPE_ONE = 36;  
   
    private static final int ITEM_HALF_DIVIDER = 1;  
    private static final int ITEM_ONE_DIVIDER = 1;  
   
    private static final int ITEM_MAX_HEIGHT = 25;  
    private static final int ITEM_MIN_HEIGHT = 10;  
   
    private static final int TEXT_SIZE = 14;  
   
    private float mDensity;  
    public int mValue = 1, mMaxValue = 864, mModType = MOD_TYPE_ONE, mLineDivider = ITEM_HALF_DIVIDER;  //当然这里的值是最重要的我们这里需要精确到秒,不过我写的精确到分,至于秒那就随机数生成凑个效果,误差也不是很大,想读懂源码主要是这些参数的需要理解。我简单的凑了一下并没有深度研究。
    // private int mValue = 50, mMaxValue = 500, mModType = MOD_TYPE_ONE,  
    // mLineDivider = ITEM_ONE_DIVIDER;  
   
    private int mLastX, mMove;  
    private int mWidth, mHeight;  
   
    private int mMinVelocity;  
    private Scroller mScroller;  
    private VelocityTracker mVelocityTracker;  
   
    private OnValueChangeListener mListener;  
   
    @SuppressWarnings("deprecation")  
    public RuleView(Context context, AttributeSet attrs) {  
        super(context, attrs);  
   
        mScroller = new Scroller(getContext());  
        mDensity = getContext().getResources().getDisplayMetrics().density;  
   
        mMinVelocity = ViewConfiguration.get(getContext()).getScaledMinimumFlingVelocity();  
   
        // setBackgroundResource(R.drawable.bg_wheel);  
        setBackgroundDrawable(createBackground());  
    }  
   
    private GradientDrawable createBackground() {  
        float strokeWidth = 4 * mDensity; // 边框宽度  
        float roundRadius = 6 * mDensity; // 圆角半径  
        int strokeColor = Color.parseColor("#FF666666");// 边框颜色  
        // int fillColor = Color.parseColor("#DFDFE0");// 内部填充颜色  
           
        setPadding((int)strokeWidth, (int)strokeWidth, (int)strokeWidth, 0);  
   
        int colors[] = { 0xFF999999, 0xFFFFFFFF, 0xFF999999 };// 分别为开始颜色,中间夜色,结束颜色  
        GradientDrawable bgDrawable = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);// 创建drawable  
        // bgDrawable.setColor(fillColor);  
        bgDrawable.setCornerRadius(roundRadius);  
        bgDrawable.setStroke((int)strokeWidth, strokeColor);  
        // setBackgroundDrawable(gd);  
        return bgDrawable;  
    }  
   
    /** 
     *  
     * 考虑可扩展,但是时间紧迫,只可以支持两种类型效果图中两种类型 
     *  
     * @param value 
     *            初始值 
     * @param maxValue 
     *            最大值 
     * @param model 
     *            刻度盘精度:
 
     *            {@link MOD_TYPE_HALF}
 
     *            {@link MOD_TYPE_ONE}
 
     */ 
    public void initViewParam(int defaultValue, int maxValue, int model) {  
        switch (model) {  
        case MOD_TYPE_HALF:  
            mModType = MOD_TYPE_HALF;  
            mLineDivider = ITEM_HALF_DIVIDER;  
            mValue = defaultValue * 2;  
            mMaxValue = maxValue * 2;  
            break;  
        case MOD_TYPE_ONE:  
            mModType = MOD_TYPE_ONE;  
            mLineDivider = ITEM_ONE_DIVIDER;  
            mValue = defaultValue;  
            mMaxValue = maxValue;  
            break;  
   
        default:  
            break;  
        }  
        invalidate();  
   
        mLastX = 0;  
        mMove = 0;  
        notifyValueChange();  
    }  
   
    /** 
     * 设置用于接收结果的监听器 
     *  
     * @param listener 
     */ 
    public void setValueChangeListener(OnValueChangeListener listener) {  
        mListener = listener;  
    }  
   
    /** 
     * 获取当前刻度值 
     *  
     * @return 
     */ 
    public float getValue() {  
        return mValue;  
    }  
   
    @Override 
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {  
        mWidth = getWidth();  
        mHeight = getHeight();  
        super.onLayout(changed, left, top, right, bottom);  
    }  
   
    @Override 
    protected void onDraw(Canvas canvas) {  
        super.onDraw(canvas);  
   
        drawScaleLine(canvas);  
        // drawWheel(canvas);  
        drawMiddleLine(canvas);  
    }  
   
    private void drawWheel(Canvas canvas) {  
        Drawable wheel = getResources().getDrawable(R.drawable.ic_launcher);  
        wheel.setBounds(0, 0, getWidth(), getHeight());  
        wheel.draw(canvas);  
    }  
   
    /** 
     * 从中间往两边开始画刻度线 
     *  
     * @param canvas 
     */ 
    private void drawScaleLine(Canvas canvas) {  
        canvas.save();  
   
        Paint linePaint = new Paint();  
        linePaint.setStrokeWidth(2);  
        linePaint.setColor(Color.BLACK);  
   
        TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);  
        textPaint.setTextSize(TEXT_SIZE * mDensity);  
   
        int width = mWidth, drawCount = 0;  
        float xPosition = 0, textWidth = Layout.getDesiredWidth("0", textPaint);  
   
        for (int i = 0; drawCount <= 4 * width; i++) {  
            int numSize = String.valueOf(mValue + i).length();  
   
            xPosition = (width / 2 - mMove) + i * mLineDivider * mDensity;  
            if (xPosition + getPaddingRight() < mWidth) {  
                if ((mValue + i) % mModType == 0) {  
                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MAX_HEIGHT, linePaint);  
   
                    if (mValue + i <= mMaxValue) {  
                        switch (mModType) {  
                        case MOD_TYPE_HALF:  
                            canvas.drawText(String.valueOf((mValue + i) / 2), countLeftStart(mValue + i, xPosition, textWidth), getHeight() - textWidth, textPaint);  
                            break;  
                        case MOD_TYPE_ONE:  
                            canvas.drawText(String.valueOf((mValue + i)/36), xPosition - (textWidth * numSize / 2), getHeight() - textWidth, textPaint);  
                            break;  
   
                        default:  
                            break;  
                        }  
                    }  
                } else {  
                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MIN_HEIGHT, linePaint);  
                }  
            }  
   
            xPosition = (width / 2 - mMove) - i * mLineDivider * mDensity;  
            if (xPosition > getPaddingLeft()) {  
                if ((mValue - i) % mModType == 0) {  
                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MAX_HEIGHT, linePaint);  
   
                    if (mValue - i >= 0) {  
                        switch (mModType) {  
                        case MOD_TYPE_HALF:  
                            canvas.drawText(String.valueOf((mValue - i) / 2), countLeftStart(mValue - i, xPosition, textWidth), getHeight() - textWidth, textPaint);  
                            break;  
                        case MOD_TYPE_ONE:  
                            canvas.drawText(String.valueOf((mValue - i)/36), xPosition - (textWidth * numSize / 2), getHeight() - textWidth, textPaint);  
                            break;  
   
                        default:  
                            break;  
                        }  
                    }  
                } else {  
                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MIN_HEIGHT, linePaint);  
                }  
            }  
   
            drawCount += 2 * mLineDivider * mDensity;  
        }  
   
        canvas.restore();  
    }  
   
    /** 
     * 计算没有数字显示位置的辅助方法 
     *  
     * @param value 
     * @param xPosition 
     * @param textWidth 
     * @return 
     */ 
    private float countLeftStart(int value, float xPosition, float textWidth) {  
        float xp = 0f;  
        if (value < 20) {  
            xp = xPosition - (textWidth * 1 / 2);  
        } else {  
            xp = xPosition - (textWidth * 2 / 2);  
        }  
        return xp;  
    }  
   
    /** 
     * 画中间的红色指示线、阴影等。指示线两端简单的用了两个矩形代替 
     *  
     * @param canvas 
     */ 
    private void drawMiddleLine(Canvas canvas) {  
        // TOOD 常量太多,暂时放这,最终会放在类的开始,放远了怕很快忘记  
        int gap = 1, indexWidth = 5, indexTitleWidth = 10, indexTitleHight = 5, shadow = 3;  
        String color = "#66999999";  
   
        canvas.save();  
   
        Paint redPaint = new Paint();  
        redPaint.setStrokeWidth(indexWidth);  
        redPaint.setColor(Color.RED);  
        canvas.drawLine(mWidth / 2, 0, mWidth / 2, mHeight, redPaint);  
   
        Paint ovalPaint = new Paint();  
        ovalPaint.setColor(Color.RED);  
        ovalPaint.setStrokeWidth(indexTitleWidth);  
        canvas.drawLine(mWidth / 2, 0, mWidth / 2, indexTitleHight, ovalPaint);  
        canvas.drawLine(mWidth / 2, mHeight - indexTitleHight, mWidth / 2, mHeight, ovalPaint);  
   
        // RectF ovalRectF = new RectF(mWidth / 2 - 10, 0, mWidth / 2 + 10, 4 *  
        // mDensity); //TODO 椭圆  
        // canvas.drawOval(ovalRectF, ovalPaint);  
        // ovalRectF.set(mWidth / 2 - 10, mHeight - 8 * mDensity, mWidth / 2 +  
        // 10, mHeight); //TODO  
   
        Paint shadowPaint = new Paint();  
        shadowPaint.setStrokeWidth(shadow);  
        shadowPaint.setColor(Color.parseColor(color));  
        canvas.drawLine(mWidth / 2 + gap, 0, mWidth / 2 + gap, mHeight, shadowPaint);  
   
        canvas.restore();  
    }  
   
    @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(event);  
            return false;  
            // break;  
        default:  
            break;  
        }  
   
        mLastX = xPosition;  
        return true;  
    }  
   
    private void countVelocityTracker(MotionEvent event) {  
        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);  
        }  
    }  
   
    private void changeMoveAndValue() {  
        int tValue = (int) (mMove / (mLineDivider * mDensity));  
        if (Math.abs(tValue) > 0) {  
            mValue += tValue;  
            mMove -= tValue * mLineDivider * mDensity;  
            if (mValue <= 0 || mValue > mMaxValue) {  
                mValue = mValue <= 0 ? 0 : mMaxValue;  
                mMove = 0;  
                mScroller.forceFinished(true);  
            }  
            notifyValueChange();  
        }  
        postInvalidate();  
    }  
   
    private void countMoveEnd() {  
        int roundMove = Math.round(mMove / (mLineDivider * mDensity));  
        mValue = mValue + roundMove;  
        mValue = mValue <= 0 ? 0 : mValue;  
        mValue = mValue > mMaxValue ? mMaxValue : mValue;  
   
        mLastX = 0;  
        mMove = 0;  
   
        notifyValueChange();  
        postInvalidate();  
    }  
   
    private void notifyValueChange() {  
        if (null != mListener) {  
            if (mModType == MOD_TYPE_ONE) {  
                mListener.onValueChange(mValue);  
            }  
            if (mModType == MOD_TYPE_HALF) {  
                mListener.onValueChange(mValue / 2f);  
            }  
        }  
    }  
   
    @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;  
            }  
        }  
    }  
}

更多相关文章

  1. android TextView 设置部分文本 边框和样式
  2. android只title背景色随着滚动渐变颜色
  3. android 颜色16进制对应的xml配置值(工具参考)
  4. Android 修改App中默认TextView的字体和颜色
  5. Android修改状态栏颜色
  6. Android 实现不同字体颜色的TextView实现代码
  7. Android控件指定方向加边框
  8. android EditText输入框获得焦点时候边框变为变色
  9. Android 部分内容设置颜色、字体、超链接、图片

随机推荐

  1. 数据库分库分表中间件 Sharding-JDBC 源
  2. 【招聘】杭州阿里招高级前端
  3. 【招聘】上海携程门票业务招中高级前端
  4. 分布式消息队列 RocketMQ 源码分析 ——
  5. 熔断器 Hystrix 源码解析 —— 执行结果
  6. 【第557期】搭建前端私有npm杂记
  7. 【第764期】你不懂JS:this是什么?
  8. 熔断器 Hystrix 源码解析 —— 调试环境
  9. 熔断器 Hystrix 源码解析 —— 命令执行(
  10. string.h中部分函数的实现