6

私のAndroid Appでは、ユーザーがクリックするポイントと特定のVectorDrawableグループの間の距離を知りたいと思います。ポイントとVectorDrawableグループ間の距離を簡単に測定できますか?

私はVectorDrawableでblueなどのグループまでの距離たい:

<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> 

は、Androidでこの距離を計算するための簡単な方法はありますか?描画可能なオンスクリーン表示される場所、あなたが知っているので、あなたが描画可能なのpostionのcordinates(X2、Y2)のためのいくつかの値を割り当てることができ

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

+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 path = android.util.PathParser.createPathFromPathData(vectorData.path); 

android.util.PathParserが含まれていませんが、あなたはここにソースを見つけることができます:

次のステップは、android.graphics.Pathに変換ベクトルパスデータを解析することです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を取得します。

などview.getLocationOnScreen(int\[\])であなたのドロウアブルのImageViewのを使用する:あなたは、単に距離の式を適用した場合、その後

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

VectorDrawableを表示するためにImageViewを使用していませんか?もしそうなら、答えに少しのコードを追加しました。 – anotherGatsby

関連する問題