自定义视图drawArc,检测用户触摸弧的绘制路径

bru*_*rux 10 java android android-canvas

我正在创建一个自定义视图,这是一种圆弧滑块进度视图.我可以根据用户触摸的位置(在x轴上)通过计算扫描来绘制更多或更少的弧,我通过首先计算百分比来做到这一点用户沿x轴触摸的位置.0%将一直向左,100%将一直向右.

我想更进一步,而不是基于用户按下的x坐标绘制弧,我想让它仅在用户触摸实际弧形绘制路径时移动,因此它更加逼真.我仍然是新的自定义视图,我的数学是有限的,但如果我得到一些提示,我将不胜感激

当用户沿着x轴移动手指在矩形区域上的百分比时,它的外观如何

class ArcProgress extends View {

    Context cx;
    float width;

    float height;
    float center_x, center_y;
    final RectF oval = new RectF();
    final RectF touchArea = new RectF();

    float sweep = 0;
    float left, right;
    int percent = 0;

    public ArcProgress(Context context) {
        super(context);
        cx = context;

    }

    public int getPercentage() {
        return percent;
    }

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

        setBackgroundColor(0xfff0ebde);

        width = (float) getWidth();
        height = (float) getHeight();

        float radius;

        if (width > height) {
            radius = height / 3;
        } else {
            radius = width / 3;
        }

        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(0xffd2c8b6);
        paint.setStrokeWidth(35);

        paint.setStyle(Paint.Style.STROKE);

        center_x = width / 2;
        center_y = height / 2;

        left = center_x - radius;
        float top = center_y - radius;
        right = center_x + radius;
        float bottom = center_y + radius;

        oval.set(left, top, right, bottom);

            //this is the background arc, it remains constant
        canvas.drawArc(oval, 180, 180, false, paint);

        paint.setStrokeWidth(10);
        paint.setColor(0xffe0524d);
            //this is the red arc whichhas its sweep argument manipulated by on touch
        canvas.drawArc(oval, 180, sweep, false, paint);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (event.getAction() == MotionEvent.ACTION_MOVE) {

            float xPosition = event.getX();
            float yPosition = event.getY();
            if (oval.contains(xPosition, yPosition)) {

                float x = xPosition - left;
                float s = x * 100;
                float b = s / oval.width();
                percent = Math.round(b);
                sweep = (180 / 100.0f) * (float) percent;

                invalidate();

            } else {
                if (xPosition < left) {
                    percent = 0;

                    sweep = (180 / 100.0f) * (float) percent;
                    invalidate();
                }
                if (xPosition > right) {
                    percent = 100;

                    sweep = (180 / 100.0f) * (float) percent;
                    invalidate();
                }
            }
        }

        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

Ada*_*zyk 11

我想只在用户触摸实际的弧形绘制路径时才移动它

在开始的onTouchEvent(),你需要检查是否xPositionyPosition正在履行一些条件.如果是的话,你会做你现在正在做的事情.如果没有,return true.

条件:

我们想检查x,y是否在灰色弧背景中:

在此输入图像描述

让我们计算从(x,y)到中心点(a,b)的距离:

final dist = distance(x, y, a, b)
Run Code Online (Sandbox Code Playgroud)

distance() 是点(x,y)和(a,b)之间的简单欧几里德距离:

double distance(int x, int y, int a, int b)
{
    return Math.sqrt((x - a) * (x - a) + (y - b) * (y - b));
}
Run Code Online (Sandbox Code Playgroud)

如果是,则x,y位于该灰色弧背景中y > Y && dist >= r && dist <= R.


Pla*_*ato 9

这对你有用吗?你不需要很多数学.您可以计算触点与弧中心的距离(它是一个圆圈,因此很容易),并与您正在使用的半径进行比较.这将告诉你点是否在弧上(几乎,见下面的完整情况).

Point touchEv = ...; 
Point circleCenter = ...; 

//the radius of the circle you used to draw the arc
float circleRadius = ...; 
//how far from the arc should a touch point treated as it's on the arc
float maxDiff = getResources().getDimension(R.dimen.max_diff_dp);

//calculate the distance of the touch point from the center of your circle
float dist = Math.pow(touchEv.x-circleCenter.x,2) + Math.pow(touchEv.y-  circleCenter.y,2)
dist = Math.sqrt(dist); 

//We also need the bounding rect of the top half of the circle (the visible arc)
Rect topBoundingRect = new Rect(circleCenter.x - circleRadius,
            circleCenter.y - circleRadius, 
            circleCenter.x + circleRadius,
            circleCenter.y);


if (Math.abs(dist - circleRadius)  <= maxDiff  &&
  topBoundingRect.contains(touchEv.x, touchEv.y)) {
  // the user is touching the arc 

}
Run Code Online (Sandbox Code Playgroud)