我正在创建一个自定义视图,这是一种圆弧滑块进度视图。我可以根据用户触摸的位置(在x轴上)通过计算扫描绘制更多或更少的弧,我首先执行此操作计算用户沿x轴触摸的百分比.0%将一直向左,100%将一直向右。
我想更进一步,而不是根据用户按下的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;
}
}
答案 0 :(得分:11)
我想仅在用户触摸实际弧时才移动它 画路径
在onTouchEvent()
开始时,您需要检查xPosition
和yPosition
是否符合某些条件。如果是的话,你会做你现在正在做的事情。如果不是,return true
。
<强>条件:强>
我们想检查x,y是否在灰色弧背景中:
让我们计算中心距(x,y)到该点(a,b)的距离:
final dist = distance(x, y, a, b)
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));
}
x,y位于灰色弧背景中,如果y > Y && dist >= r && dist <= R
。
答案 1 :(得分: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
}