6

在我的Android应用程序中,我想知道用户点击的点和特定的VectorDrawable组之间的距离。有没有一种简单的方法来测量点与VectorDrawable组之间的距离?

我要像blue一组的距离在VectorDrawable:

<vector android:height="24dp" android:viewportHeight="1052.3622" 
    android:viewportWidth="744.0945" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> 
    <path android:fillColor="#ff0000" 
     android:name="blue" 
     android:pathData="M182.9,349.5m-74.7,0a74.7,74.7 0,1 1,149.3 0a74.7,74.7 0,1 1,-149.3 0" 
     android:strokeAlpha="1" android:strokeColor="#000000" android:strokeWidth="4.23501825"/> 
    <path android:fillColor="#00ff00" 
     android:name="red" 
     android:pathData="M474.3,392.4a84.3,102.9 0,1 0,168.6 0a84.3,102.9 0,1 0,-168.6 0z" 
     android:strokeAlpha="1" android:strokeColor="#000000" android:strokeWidth="5"/>> 
</vector> 

有没有计算在安卓这个距离一个简单的方法?

+4

取决于您的代码可能“直截了当”。 – petey

回答

2

我不解决这个问题肯定存在简单的方法,但是这是可以做到这样的:

解析向量XML,所以你在运行所有这些变量。解析这里没有覆盖,让我们假设你有如下数据结构,我们将与以后的工作:

private static class VectorData { 
    private int width = 24; 
    private int height = 24; 
    private double viewportHeight = 1052.3622; 
    private double viewportWidth = 744.0945; 
    private String path = "M182.9,349.5m-74.7,0a74.7,74.7 0,1 1,149.3 0a74.7,74.7 0,1 1,-149.3 0"; 

    private double scaleVectorX(Context context) { 
     return dpToPx(context, width)/viewportWidth; 
    } 

    private double scaleVectorY(Context context) { 
     return dpToPx(context, height)/viewportHeight; 
    } 

    private static float dpToPx(Context context, float dp) { 
     return dp * context.getResources().getDisplayMetrics().density; 
    } 
} 

正如你看到的所有字段都硬编码为简单起见。

下一步是解析矢量路径数据将其转换为android.graphics.Path:不包括

android.graphics.Path path = android.util.PathParser.createPathFromPathData(vectorData.path); 

android.util.PathParser,但你可以在这里找到来源:https://android.googlesource.com/platform/frameworks/base/+/17e64ffd852f8fe23b8e2e2ff1b62ee742af17a6/core/java/android/util/PathParser.java。不知道它是如何合法复制和使用它。

有了路径,我们需要找到N个点(坐标)。详细点 - 更精确的结果将是与处理速度较慢:

final Collection<Point> points = getPoints(path, iv.getX(), iv.getY(), vectorData); 

private static class Point { 
    private float x; 
    private float y; 

    Point(float x, float y) { 
     this.x = x; 
     this.y = y; 
    } 

    @Override 
    public String toString() { 
     return "Point{" + 
       "x=" + x + 
       ", y=" + y + 
       '}'; 
    } 
} 

private Collection<Point> getPoints(Path path, float viewX, float viewY, VectorData vectorData) { 
    Collection<Point> points = new ArrayList<>(); 
    PathMeasure pm = new PathMeasure(path, false); 
    float length = pm.getLength(); 
    float distance = 0f; 
    int size = N; 
    float speed = length/size; 
    int counter = 0; 
    float[] aCoordinates = new float[2]; 

    while ((distance < length) && (counter < size)) { 
     // get point from the path 
     pm.getPosTan(distance, aCoordinates, null); 
     float pathX = aCoordinates[0]; 
     float pathY = aCoordinates[1]; 

     float x = (float) (vectorData.scaleVectorX(this) * pathX) + viewX; 
     float y = (float) (vectorData.scaleVectorY(this) * pathY) + viewY; 

     points.add(new Point(x, y)); 
     counter++; 
     distance = distance + speed; 
    } 

    return points; 
} 

路径 - 是我们的道路,我们之前得到的,IV - 是矢量容器(ImageView的,例如),我们需要它以调整点的坐标。 vectorData - 是解析我们的矢量之前得到的结构。

现在,我们需要定义区域处理情况下通道被关闭,我们希望把里面的路径单击以0距离:

final Region region = new Region(); 
RectF rectF = new RectF(); 
path.computeBounds(rectF, true); 
region.setPath(path, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom)); 

为了计算如下方法最小距离应使用:

private int getMinDistance(float eventX, float eventY, Collection<Point> pathPoints, Region pathRegion, VectorData vectorData) { 
    int minDistance = Integer.MAX_VALUE; 

    boolean contains = pathRegion.contains((int) (eventX/vectorData.scaleVectorX(this)), (int) (eventY/vectorData.scaleVectorY(this))); 

    if (contains) { 
     minDistance = 0; 
    } else { 
     for (Point point : pathPoints) { 
      int distance = getDistanceBetweenPoints((int) eventX, (int) eventY, (int) point.x, (int) point.y); 
      if (distance < minDistance) { 
       minDistance = distance; 
      } 
     } 
    } 
    return minDistance; 
} 

private int getDistanceBetweenPoints(int x, int y, int x1, int y1) { 
    return (int) Math.sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)); 
} 
0

首先得到点的cordinates这里使用的触摸方式:

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    float x1 = event.getX(); 
    float y1 = event.getY(); 
    return true; 
} 

,因为你知道那里的绘制将显示在屏幕上,你可以指定你的绘制的现在的位置cordinates(x2,y2)的一些值。

或使用绘制的ImageView的与view.getLocationOnScreen(int\[\]),如:

int[] posiXY = new int[2]; 
yourDrawablesImageView.getLocationOnScreen(posiXY); 
int x2 = posiXY[0]; 
int y2 = posiXY[1]; 

然后如果你简单地套用距离公式:

float distance=sqrt((x2−x1)*(x2−x1)+(y2−y1)*(y2−y1)); 

你会得到所需要的距离。

+0

我想这肯定是一个非常简单直接的方法 – anotherGatsby

+0

如何知道VectorDrawable的组将在屏幕上显示?我如何访问这些坐标?我关心到组的距离,而不是整个VectorDrawable。 – Christian

+0

你没有使用ImageView来显示VectorDrawables吗?如果是这样,那么我已经添加了一些代码的答案。 – anotherGatsby

相关问题