android 刻度尺控件实现

主要实现刻度尺的效果,能够快速滑动刻度,设置刻度间距,刻度值,滑动回调。简单易用

效果图


textureView控件的选择

刻度尺要不停的绘制,所以view是不可取的,这篇文章介绍了textureview的用法,受益匪浅

总结来说:

1.view的绘制在主线程里面,频繁绘制会导致主线程阻塞

2.我们知道一个surfaceview是异步绘制的,不阻塞主线程,但是它不支持平移、缩放、旋转,且很难放在srollview等控件里面



TextureView.SurfaceTextureListener


abstract void onSurfaceTextureAvailable( SurfaceTexture  surface, int width, int height)
Invoked when a   TextureView's SurfaceTexture is ready for use.  
abstract boolean onSurfaceTextureDestroyed( SurfaceTexture  surface)
Invoked when the specified   SurfaceTexture  is about to be destroyed.  //textureview销毁时,可以在这个地方释放一些资源,比如camera
abstract void onSurfaceTextureSizeChanged( SurfaceTexture  surface, int width, int height)
Invoked when the   SurfaceTexture's buffers size changed.
abstract void onSurfaceTextureUpdated( SurfaceTexture  surface)
Invoked when the specified   SurfaceTexture  is updated through   updateTexImage().

@Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        mBorderRectF.set(mBorderPaint.getStrokeWidth(), mBorderPaint.getStrokeWidth(),
                width - mBorderPaint.getStrokeWidth(), height - mBorderPaint.getStrokeWidth());  //设置一块矩形区域,
        mWidth = mBorderRectF.width();  
        dis = (int)(mWidth / allBlockNum);  //每个刻度间距,allBlockNum是小刻度的个数
        refreshCanvas(); 
    }

//刷新视图 
    private void refreshCanvas() {
        if (mBorderRectF.isEmpty()) {
            return;
        }
        Canvas canvas = lockCanvas();
        if(canvas != null) {
            canvas.drawColor(Color.WHITE);
            drawBorder(canvas);
            drawScaleMark(canvas);
            drawMarkPoint(canvas);
        }
        unlockCanvasAndPost(canvas);
    }

画出刻度线:由中间向两边画

//画出所有刻度:从中间向两边画
    private void drawScaleMark(Canvas canvas) {
        int count = 0;
        final int centerX = (int)mBorderRectF.centerX();
        if(mCenterNum > maxNum)
            mCenterNum = maxNum;
        if (mCenterNum < minNum)
            mCenterNum = minNum;
        if(numberListener != null)
            numberListener.onChanged(mCenterNum);

        while(true){
            int left = centerX - dis * count;
            int leftNum = mCenterNum - count * scaleNum;
            int right = centerX + dis * count;
            int rightNum = mCenterNum + count * scaleNum;

            String leftText = String.valueOf(leftNum);
            String rightText = String.valueOf(rightNum);
            //间隔5刻度画文字信息
            if(leftNum % (5*scaleNum) == 0) {
                canvas.drawLine(left, canvas.getHeight() / 2, left, canvas.getHeight() - 1, mScaleMarkPaint);
                mScaleMarkPaint.getTextBounds(leftText, 0, leftText.length(), mTextRect);
                canvas.drawText(leftText, left - mTextRect.centerX(), canvas.getHeight() / 2, mScaleMarkPaint);
            }
            else
                canvas.drawLine(left, canvas.getHeight() * 2 / 3, left, canvas.getHeight() - 1, mScaleMarkPaint);

            if(rightNum % (5*scaleNum) == 0) {
                canvas.drawLine(right, canvas.getHeight() / 2, right, canvas.getHeight() - 1, mScaleMarkPaint);
                mScaleMarkPaint.getTextBounds(rightText, 0, rightText.length(), mTextRect);
                canvas.drawText(rightText, right - mTextRect.centerX(), canvas.getHeight() / 2, mScaleMarkPaint);
            }
            else
                canvas.drawLine(right, canvas.getHeight() * 2 / 3, right, canvas.getHeight() - 1, mScaleMarkPaint);

            count++;
            if(left < 0)
                break;
        }
    }

手势判断

我把手势判断的逻辑代码写在ScaleScroller类中,onTouchEvent用来判断按下,移动和抬起三个手势。GestureDetector.SimpleOnGestureListener中的onFling来处理快速滑动

OnFling在手指快速滑动控件时触发,onfling有四个参数

(注意:onFling只能触发一次,但是快速滑动的效果是要在一定时间内做滚动处理,所以需要通过Scroller类+Handler的方式来帮助实现)

@Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            final int minX = -0x7fffffff;
            final int maxX = 0x7fffffff;
            lastX = 0;
            scroller.fling(0, 0, (int)-velocityX, 0, minX, maxX, 0, 0);  //滚动的距离有速度决定
            handler.sendEmptyMessage(ON_FLING);
            return true;
        }

e1 The first down motion event that started the fling.       //按下时候的event
e2 The move motion event that triggered the current onFling.  //触发快速滑动时的event
velocityX The velocity of this fling measured in pixels per second along the x axis.
velocityY The velocity of this fling measured in pixels per second along the y axis.

private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            boolean isFinished = scroller.computeScrollOffset(); //判断滚动是否结束
            int curX = scroller.getCurrX();  
            int delta = lastX - curX;
            if(listener != null){
                listener.onScroll(delta);
            }
            lastX = curX;
            if(isFinished)
                handler.sendEmptyMessage(ON_FLING);  
            else
                listener.onFinished();
        }
    };


源码地址


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值