【Android 车载 App】实现座椅调节控制十字指针的效果

效果展示

在这里插入图片描述

实现方法

思路

  1. 第一步,画两条十字虚线
  2. 第二步,在每个虚线的末端画出圆角三角形
  3. 第三步,在十字虚线的中间位置画出两个同心圆,一个填充内容,一个描边
  4. 第四步,复写onTouchEvent方法,实现同心圆的移动逻辑

代码

第一步,画两条十字虚线

初始化画笔

        PathEffect pathEffect = new DashPathEffect(new float[]{10f,10f}, 1);
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeWidth(5f);
        linePaint.setColor(Color.GRAY);
        linePaint.setPathEffect(pathEffect);

在onDraw方法中使用画笔,画出两条十字虚线

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawLine(30,getHeight()/2, getWidth()-30,getHeight()/2, linePaint);
        canvas.drawLine(getWidth()/2, 30, getWidth()/2, getHeight()-30, linePaint);
    }

第二步,在每个虚线的末端画出圆角三角形

画三角形需要用到Path的相关知识(这部分内容请同学们自行百度),声明及Path的初始化如下:

	Path upTrianglePath = new Path();
	Path downTrianglePath = new Path();
	Path leftTrianglePath = new Path();
	Path rightTrianglePath = new Path();

    private Path getTrianglePath(int direction) {
        initTrianglePath();
        switch (direction) {
            case 0://return upTrianglePath;
            case 1: // 下
                return downTrianglePath;
            case 2: // 左
                return leftTrianglePath;
            case 3: // 右
                return rightTrianglePath;
            default:
                break;
        }
        return upTrianglePath;
    }

   private void initTrianglePath() {
        upTrianglePath.moveTo(getWidth()/2, 0);
        upTrianglePath.lineTo(getWidth()/2 - 30, 52);
        upTrianglePath.lineTo(getWidth()/2 + 30, 52);
        upTrianglePath.close();

        downTrianglePath.moveTo(getWidth()/2, getHeight());
        downTrianglePath.lineTo(getWidth()/2 - 30, getHeight() - 52);
        downTrianglePath.lineTo(getWidth()/2 + 30, getHeight() - 52);
        downTrianglePath.close();

        leftTrianglePath.moveTo(0, getHeight()/2);
        leftTrianglePath.lineTo(52, getHeight()/2 + 30);
        leftTrianglePath.lineTo(52, getHeight()/2 - 30);
        leftTrianglePath.close();

        rightTrianglePath.moveTo(getWidth(), getHeight()/2);
        rightTrianglePath.lineTo(getWidth() - 52, getHeight()/2 + 30);
        rightTrianglePath.lineTo(getWidth() - 52, getHeight()/2 - 30);
        rightTrianglePath.close();
    }

除了使用 Path 之外,因为我们需要画出圆角三角形,所以还需要对 Paint 对象的 PathEffect 做一下设置:

    private void initPaint() {
//...
        trianglePaint.setStyle(Paint.Style.FILL);
        trianglePaint.setColor(Color.GRAY);
        float radius = 10f;
        CornerPathEffect corEffect = new CornerPathEffect(radius);
        trianglePaint.setPathEffect(corEffect);
//...
    }

然后在 onDraw 方法中画出四个顶点位置的三角形:

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
		//....
        canvas.drawPath(getTrianglePath(0), trianglePaint);
        canvas.drawPath(getTrianglePath(1), trianglePaint);
        canvas.drawPath(getTrianglePath(2), trianglePaint);
        canvas.drawPath(getTrianglePath(3), trianglePaint);
		//....
    }

第三步,在十字虚线的中间位置画出两个同心圆,一个填充内容,一个描边

画圆只需要使用canvas.drawCircle方法即可,但是由于两个圆一个需要填充内容,一个需要描边,所以我们使用两个Paint对象来分别实现对应的效果。
声明Paint对象:

    Paint circlePaint1 = new Paint();
    Paint circlePaint2 = new Paint();
    
    private void initPaint() {
		// ...
        circlePaint1.setStyle(Paint.Style.FILL);// 填充内容
        circlePaint1.setColor(Color.GRAY);
        circlePaint2.setStyle(Paint.Style.STROKE); // 描边
        circlePaint2.setStrokeWidth(14);
        circlePaint2.setColor(Color.GRAY);
    }

然后在 onDraw 方法中画出中心的两个同心圆:

    @Override
    protected void onDraw(Canvas canvas) {
        // ...
        canvas.drawCircle(getCircleX(), getCircleY(), 20, circlePaint1);
        canvas.drawCircle(getCircleX(), getCircleY(), 48, circlePaint2);

    }

第四步,复写onTouchEvent方法,实现同心圆的移动逻辑

复写onTouchEvent方法前,需要先设置clickabletrue,否则我们的View只能接收到 ACTION_DOWN 事件,无法接收到其他事件。

    public SeatAdaptionView(Context context, @Nullable AttributeSet attrs) {
//...
        setClickable(true);
    }

然后复写 onTouchEvent 方法,实现同心圆的移动逻辑,实现的思路是:

  1. ACTION_DOWN 时记录初始触摸点
  2. ACTION_MOVE 时计算X轴与Y轴的偏移值 deltaXdeltaY,比较二者绝对值大小,根据比较结果设定滑动方向。deltaX大,则延X轴滑动,deltaY大则延Y轴滑动。
  3. 根据 deltaX(或deltaY)的值,改变圆心位置,并执行重绘。
  4. ACTION_UP时,恢复到初始状态。
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = event.getAction();

        switch(action) {
            case MotionEvent.ACTION_DOWN:
	            // 1.记录初始触摸点
                touchX = event.getX();
                touchY = event.getY();
                lastX = event.getX();
                lastY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
            	// 2.计算X轴与Y轴的偏移值 `deltaX` 与 `deltaY`
                touchX = event.getX();
                touchY = event.getY();
                float deltaX = lastX - touchX;
                float deltaY = lastY - touchY;
                if (moveDirection == -1) {
                	// 比较二者绝对值大小,根据比较结果设定滑动方向。`deltaX`大,则延X轴滑动,`deltaY`大则延Y轴滑动。
                    if (Math.abs(deltaX) >= Math.abs(deltaY)) {
                        moveDirection = 0;
                    } else {
                        moveDirection = 1;
                    }
                } else if (moveDirection == 0) {
                    // 水平方向移动
                    mDeltaX = deltaX;
                    // 3.根据 `deltaX`(或`deltaY`)的值,改变圆心位置,并执行重绘。
                    invalidate();
                } else {
                    // 垂直方向移动
                    mDeltaY = deltaY;
                    // 根据 `deltaX`(或`deltaY`)的值,改变圆心位置,并执行重绘。
                    invalidate();
                }

                break;
            case MotionEvent.ACTION_UP:
            	// 4.恢复到初始状态。
                touchX = -1;
                touchY = -1;
                moveDirection = -1;
                mDeltaX = 0;
                mDeltaY = 0;
                invalidate();
                break;
            default:
                break;
        }

        Log.d("SeatAdaptionView", "onTouchEvent: Action = " + event.getAction() + " touchX = " + touchX + " touchY = " + touchY);

        return super.onTouchEvent(event);
    }

代码链接

代码链接(github)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值