美文网首页
自定义万向轮

自定义万向轮

作者: 钰大人 | 来源:发表于2018-12-13 12:00 被阅读0次

基础知识部分

  • Android的View的坐标系是从左到右,从上到下。左上角坐标(0,0)
  • 自定义style样式
  • onSizeChanged
  • onDraw
  • OnTouchEvent

Code

  • style
    <declare-styleable name="EmbeddedCompassView">
        <attr name="outSideRadiusStrokerColor" format="color" />
        <attr name="arrowColor" format="color" />
        <attr name="stickColor" format="color" />
    </declare-styleable>

   // 处理
    TypedArray arr = getContext().obtainStyledAttributes(attrs, R.styleable.EmbeddedCompassView);
    mOutSideRadiusStrokeColor = arr.getColor(R.styleable.EmbeddedCompassView_outSideRadiusStrokerColor, Color.DKGRAY);
    mArrowColor = arr.getColor(R.styleable.EmbeddedCompassView_arrowColor, Color.DKGRAY);
    mStickColor = arr.getColor(R.styleable.EmbeddedCompassView_stickColor, Color.LTGRAY);
    arr.recycle();
  • onSizeChanged
    mWidth = w; 
    mHeight = h;
    int contW = w - getPaddingLeft() - getPaddingRight();
    int contH = h - getPaddingTop() - getPaddingBottom();
    mCenterX = getPaddingLeft() + contW/2; // 中心点x
    mCenterY = getPaddingTop() + contH/2;  // 中心点y
    mOutsideRadius = (int)(Math.min(w, h) * 0.5 - 4); // 外圆半径
    mThresholdRadius = (int) (mOutsideRadius * 0.98); // 万向轮活动半径
    mStickRadius = (int) (mOutsideRadius * 0.685);    // 万向轮半径

  • onDraw
    canvas.drawCircle(mCenterX, mCenterY, mOutsideRadius, mOutSideCirclePaint); // 绘制外圆

    if (isSticking) { // 滑动
        int offsetMaxDistance = (mThresholdRadius-mStickRadius);
        int offsetCurr = Math.max(Math.abs(positionX-mCenterX), Math.abs(positionY-mCenterY));

        int alpha = Math.max((int)(255*offsetCurr*1.0/offsetMaxDistance), 10);  //万向轮按下色渐变
        mStickCirclePaint.setAlpha(alpha);
        canvas.drawCircle(positionX, positionY, mStickRadius, mStickCirclePaint); // 绘制万向轮
        onDrawArrow(canvas, positionX, positionY); // 绘制箭头
    } else {
        onDrawArrow(canvas, mCenterX, mCenterY); // 绘制箭头
    }

   // onDrawArrow
    Path path = new Path();
    int arrowA = 15;
    int arrowB = 30;

    // left
    path.moveTo(positionX-mStickRadius+arrowB, positionY-arrowA);
    path.lineTo(positionX-mStickRadius+arrowA, positionY);
    path.lineTo(positionX-mStickRadius+arrowB, positionY+arrowA);
    canvas.drawPath(path, mOutSideCirclePaint);

    // right
    path.moveTo(positionX+mStickRadius-arrowB, positionY-arrowA);
    path.lineTo(positionX+mStickRadius-arrowA, positionY);
    path.lineTo(positionX+mStickRadius-arrowB, positionY+arrowA);
    canvas.drawPath(path, mOutSideCirclePaint);

    //top
    path.moveTo(positionX-arrowA, positionY-mStickRadius+arrowB);
    path.lineTo(positionX, positionY-mStickRadius+arrowA);
    path.lineTo(positionX+arrowA, positionY-mStickRadius+arrowB);
    canvas.drawPath(path, mOutSideCirclePaint);

    //bottom
    path.moveTo(positionX-arrowA, positionY+mStickRadius-arrowB);
    path.lineTo(positionX, positionY+mStickRadius-arrowA);
    path.lineTo(positionX+arrowA, positionY+mStickRadius-arrowB);
    canvas.drawPath(path, mOutSideCirclePaint);

滑动点范围[0~(mThresholdRadius-mStickRadius)] & TouchEvent

    // 判断是否落在圆内.
    private boolean isInOutSideCircle(int positionX, int positionY) {
        int pow2 = (int)( Math.pow((positionX-mCenterX), 2) + Math.pow((positionY-mCenterY), 2));
        int distance = (int) Math.sqrt(pow2);
        return ((distance+mStickRadius) <= mThresholdRadius);
    }

    // OnTouchEvent
    // 仅初始点在万向轮活动范围内才做处理,外界进入忽略.
    int downX = (int)event.getX();
    int downY = (int)event.getY();
    super.onTouchEvent(event);

    switch (event.getActionMasked()) {
        case MotionEvent.ACTION_DOWN:
            if (isInOutSideCircle(downX, downY)) {
                isSticking = true;
                positionX = downX;
                positionY = downY;
            }
            break;
        case MotionEvent.ACTION_MOVE:
            if (isSticking) {
                if (isInOutSideCircle(downX, downY)) {
                    positionX = downX;
                    positionY = downY;
                } else {
                    double dist = Math.sqrt((downX - mCenterX) * (downX - mCenterX) + (downY - mCenterY) * (downY - mCenterY));
                    // 格局角度cos来计算,找到最近合适的点.
                    positionX = (int) (((downX - mCenterX) * (mThresholdRadius - mStickRadius)) / dist + mCenterX);
                    positionY = (int) (((downY - mCenterY) * (mThresholdRadius - mStickRadius)) / dist + mCenterY);
                }
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            if (isSticking) {
                isSticking = false;
                invalidate();
            }
            break;
    }

    if (isSticking) {
        invalidate();

        if (listener != null) {
            double dist = Math.sqrt((positionX - mCenterX) * (positionX - mCenterX) + (positionY - mCenterY) * (positionY - mCenterY));
            double angle = Math.acos((positionX-mCenterX)/dist);
            listener.onAngleChanged(angle); // 角度变化通知.[0~pi]
        }
    }
    return true;

已上传GitHub: https://github.com/shuqianlan/weather/tree/master/app/src/main/java/com/ilifesmart/compass

相关文章

  • 万向轮的性能与特性

    万向轮的性能 按材料分:聚氨酯万向轮、灰胶万向轮、尼龙万向轮、金属万向轮等。 用途:适用于安装、桌椅、床柜、沙发等...

  • 自定义万向轮

    基础知识部分 Android的View的坐标系是从左到右,从上到下。左上角坐标(0,0) 自定义style样式 o...

  • 主题 手推车

    今天作品手推车,我们学习了并认识了万向轮,万向轮是可以进行360度的转弯,并学习了360的一半是多少,了解万向轮在...

  • 工业脚轮的选购方向

    工业万向轮的市场也会根据消费者的不同需要有着不同的工业万向轮规格。这种规格就是根据工业万向轮直径的尺寸和工业万向...

  • 怎样提高万向脚轮的灵活性

    影响万向轮推动困难的原因: 1、轮子材料; 2、轴承选择; 3、轮子大小; 4、应用场地; 万向轮灵活性选择: 1...

  • 2020-12-13

    搭建主题:万向轮小车 知识点:认识万向轮结构及应用; 复习车轮结构; 分别使用直角连杆和小曲柄固定轴和底盘。 课堂...

  • 万向脚轮是什么!

    轮子的出现,很好的解决了我们的物品重的烦恼,尤其是万向轮。万向轮在我们的生活当中,占据着不小的作用。平时我们也没有...

  • 一种超载重pu万向轮制造组装件的制作方法

    一种超载重pu万向轮组装件的制作方法技术领域,需要实用新型涉及很多部件,主要涉及旅行箱包的万向轮组装件,这种结构在...

  • 万向轮的基本介绍

    万向轮就是所谓的活动脚轮,它的结构允许水平360度旋转。脚轮是个统称,包括活动脚轮和固定脚轮。固定脚轮没有旋转结构...

  • 合格万向轮的标配

    很多人在选购脚轮时因为对产品质量不了解,在长时间地板环境下使用,脚轮掉皮掉渣,造成地面脏乱,影响整体环境,所以对于...

网友评论

      本文标题:自定义万向轮

      本文链接:https://www.haomeiwen.com/subject/jupvhqtx.html