自定义标尺控件

示例

示例

功能描述

通过输入的list节点表示标尺刻度,不规定每一个相同,当长度相同,取得的值只能是节点上的值,没有中间值。支持左滑右滑,滑动有动画,并且划过一般自动滑到节点,未满一半返回原节点。

代码

public class RulerView extends View {
    /**屏幕宽度*/
    private int screenWidth;
    /**控件高度*/
    private int viewHeight;
    /**view宽度*/
    private int viewWidth;
    /**m每一小格的长度*/
    private int oneItemValue;
    /**端点节点*/
    private List<String> list =new ArrayList<>();
    /**滑动监听器*/
    private OnRulerChangeListener rulerListener;
    /**滚动计算类*/
    private Scroller              scroller;
    /**手势监听*/
    private GestureDetector       gestureDetector;
    /**偏移量*/
    private int                   offset;
    /**绘制的开始位置*/
    private int                   location;
    /**显示哪个list值*/
    private int                   distanceInteger;
    /**游标颜色*/
    private int                   cursorColor;
    /**刻度颜色*/
    private int                   scaleColor;
    /**刻度字体颜色*/
    private int                   scaleTextColor;
    /**刻度字体大小*/
    private int                   scaleTextSize;
    /**手指抬起时的偏移量*/
    private int                   upOffset;
    /**是否标尺往回走*/
    private boolean               isBack;
    /**字体所处高度比例*/
    private float                 scaleTextHeight;
    /**游标长度比例*/
    private float cursorHeight;

    public void setList(List<String> list) {
        this.list = list;
        invalidate();
    }

    public void setRulerListener(OnRulerChangeListener rulerListener) {
        this.rulerListener = rulerListener;
    }

    public RulerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        WindowManager  windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm            = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(dm);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RulerView);
        cursorColor = typedArray.getColor(R.styleable.RulerView_cursor_color, Color.rgb(255,0,0));
        scaleColor = typedArray.getColor(R.styleable.RulerView_scale_color,Color.argb(255,102,102,102));
        scaleTextColor = typedArray.getColor(R.styleable.RulerView_scale_text_color,Color.argb(255,102,102,102));
        scaleTextSize = typedArray.getDimensionPixelOffset(R.styleable.RulerView_scale_text_size,36);
        scaleTextHeight = typedArray.getFloat(R.styleable.RulerView_scale_text_height,(float)0.25);
        cursorHeight = typedArray.getFloat(R.styleable.RulerView_cursor_height,(float) 0);
        screenWidth = dm.widthPixels;
        oneItemValue = screenWidth/20;
        //滚动计算器
        scroller = new Scroller(context);
        //一定要加,不然只会收到onDown,onShowPress,onLongPress3个事件
        setClickable(true);
        //手势解析
        gestureDetector = new GestureDetector(context, gestureListener);
        //是否允许长点击
        gestureDetector.setIsLongpressEnabled(false);
        location=screenWidth/2;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        viewHeight = MeasureSpec.getSize(heightMeasureSpec);
        if(list.size() == 0){
            list.add("0");
        }
        viewWidth=oneItemValue*(list.size()-1)*5;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        viewWidth=oneItemValue*(list.size()-1)*5;
        drawBottomLine(canvas);
        drawScale(canvas);
        drawCursor(canvas);
    }
    /**绘制刻度*/
    private void drawScale(Canvas canvas) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(3);
        paint.setColor(scaleColor);
        Paint paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintText.setTextSize(scaleTextSize);
        paintText.setColor(scaleTextColor);
        for(int i=0;i <= (list.size()-1)*5;i++){
            int currentLocation=location+i*oneItemValue;
            if(i % 5 == 0){
                String drawStr;
                drawStr = list.get(i/5);
                Rect bounds = new Rect();
                paintText.getTextBounds(drawStr, 0, drawStr.length(), bounds);
                canvas.drawText(drawStr, currentLocation - bounds.width() / 2, viewHeight-viewHeight*scaleTextHeight, paintText);
                canvas.drawLine(currentLocation, viewHeight-viewHeight/5, currentLocation, viewHeight, paint);
            }else{
                canvas.drawLine(currentLocation, viewHeight-viewHeight/8, currentLocation, viewHeight, paint);
            }
        }
    }

    /**绘制游标*/
    private void drawCursor(Canvas canvas) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(3);
        paint.setColor(cursorColor);
        if(scroller.computeScrollOffset()){
            canvas.drawLine(screenWidth/2+scroller.getCurrX(), viewHeight*cursorHeight, screenWidth/2+scroller.getCurrX(), viewHeight, paint);
        }else{
            canvas.drawLine(screenWidth/2+offset, viewHeight*cursorHeight, screenWidth/2+offset, viewHeight, paint);
        }
    }

    /**绘制底部横线*/
    private void drawBottomLine(Canvas canvas) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(3);
        paint.setColor(Color.rgb(102,102,102));
        if(scroller.computeScrollOffset()){
            canvas.drawLine(scroller.getCurrX(),viewHeight,screenWidth+scroller.getCurrX(), viewHeight, paint);
        }else{
            canvas.drawLine(offset, viewHeight, screenWidth+offset, viewHeight, paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        gestureDetector.onTouchEvent(event);
        if(event.getAction() == MotionEvent.ACTION_UP){
            changeValue();
            upOffset = offset;
            offset = distanceInteger *5*oneItemValue;
            if(isBack){
                scroller.startScroll(upOffset,0,-(upOffset-offset),0,1000);
            }else{
                scroller.startScroll(upOffset,0,(offset-upOffset),0,1000);
            }
            invalidate();
        }
        return super.onTouchEvent(event);
    }
    /**改变textView*/
    private void changeValue(){
        distanceInteger= offset/(oneItemValue*5);
        int distanceRemainder = offset % (oneItemValue*5);
        if(distanceRemainder >=oneItemValue*5/2){
            distanceInteger=distanceInteger+1;
            isBack=false;
        }else{
            isBack=true;
        }
        if(rulerListener != null){
            if(distanceInteger >= list.size()){
                distanceInteger = list.size() -1;
            }
            rulerListener.setValue(Integer.valueOf(list.get(distanceInteger)));
        }
    }
    private GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener(){
        /**
         * @param e1 滑动事件的起点(也就是说onDown()的时候)
         * @param e2 当前滑动位置点(手指的位置)
         * @param distanceX 上次滑动(调用onScroll)到这次滑动的X轴的距离px
         * @param distanceY 上次滑动(调用onScroll)到这次滑动的Y轴的距离px
         */
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            if(offset >= viewWidth && distanceX >= 0){
                distanceX =0;
                offset=viewWidth;
            }else if(offset <= 0 && distanceX <= 0){
                distanceX = 0;
                offset =0;
            }
            scroller.forceFinished(true);
            offset=offset+(int)distanceX;
            scrollTo(offset,0);
            return super.onScroll(e1, e2, distanceX, distanceY);
        }

        /***
         * @param e1 拖动动事件的起点(也就是说onDown()的时候)
         * @param e2 onFling()调用时,手指的位置
         * @param velocityX X轴上每秒滑动像素值
         * @param velocityY Y轴上每秒滑动像素值
         * 当拖动速率velocityX或velocityY超过ViewConfiguration.getMinimumFlingVelocity()最小拖动速率时,才会调用onFling(),
         * 也就是如果只拖动一点,或是慢慢的拖动,是不会触发该方法
         */
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            scroller.fling(offset, 0, (int) (-velocityX / 1.5), 0, 0, viewWidth, 0, 0);
            return super.onFling(e1, e2, velocityX, velocityY);

        }
    };
    @Override
    public void computeScroll() {
        super.computeScroll();
        if(scroller.computeScrollOffset()){
            scrollTo(scroller.getCurrX(),0);
            invalidate();
        }else{
            scrollTo(offset,0);
        }
    }
}
public interface OnRulerChangeListener {
    /**设置值*/
    void setValue(int value);
}
<resources>
    <declare-styleable name="RulerView">
        <!--游标的颜色-->
        <attr name="cursor_color" format="color"></attr>
        <!--刻度颜色-->
        <attr name="scale_color" format="color"></attr>
        <!--刻度字体颜色-->
        <attr name="scale_text_color" format="color"></attr>
        <!--刻度字体大小-->
        <attr name="scale_text_size" format="dimension"></attr>
        <!--字体所处高度-->
        <attr name="scale_text_height" format="float"></attr>
        <!--游标长度比例-->
        <attr name="cursor_height" format="float"></attr>
    </declare-styleable>
</resources>

使用

<com.example.RulerView
        android:id="@+id/rulerview"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:layout_marginTop="10dp"
        app:cursor_color="#ff0000"
        app:scale_color="#333333"
        app:scale_text_color="#333333"
        app:scale_text_size="20sp" />
public class MainActivity extends AppCompatActivity implements OnRulerChangeListener {
    TextView  textView;
    RulerView rulerView;
    int       num;
    private int currLocation = 500;
    private List<String> list=new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        list.add(0,"500");
        list.add(1,"1000");
        list.add(2,"1400");
        rulerView = (RulerView) findViewById(R.id.rulerview);
        rulerView.setRulerListener(this);
        rulerView.setList(list);
        textView = (TextView) findViewById(R.id.tvValue);
        textView.setText(currLocation + "");

    }

    @Override
    public void setValue(int value) {
        textView.setText(value+"");
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值