मैं हल करने के लिए इस मुद्दे को मौजूद है यकीन है कि आसान तरीका नहीं कर रहा हूँ, लेकिन यह इस तरह किया जा सकता है:
पार्स वेक्टर एक्सएमएल ताकि आप क्रम में उन सभी चर है। पार्सिंग यहाँ शामिल नहीं है, मान लीजिए कि आप डेटा संरचना है कि हम बाद में साथ काम करेंगे निम्नलिखित है मान लें:
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;
}
}
जैसा कि आप देख सभी क्षेत्रों सादगी के लिए hardcoded कर रहे हैं।
अगला चरण वेक्टर पथ यह 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। यह सुनिश्चित नहीं है कि प्रतिलिपि बनाना और इसका उपयोग करना कितना कानूनी है।
पथ होने के बाद हमें एन अंक (निर्देशांक) ढूंढने की आवश्यकता होगी। अधिक अंक - अधिक सटीक परिणाम होगा और धीमी प्रसंस्करण:
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) वेक्टर कंटेनर है, हम आदेश अंक निर्देशांक समायोजित करने के लिए इसकी आवश्यकता है । वेक्टरडाटा - संरचना है जिसे हमने अपने वेक्टर को पार्स करने से पहले प्राप्त किया था।
अब हम इस मामले में जहां पथ बंद कर दिया है संभाल करने के लिए क्षेत्र परिभाषित करने की जरूरत है और हम 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));
}
इस पर निर्भर करता है कि आपका कोड "सीधा" कैसे हो सकता है। – petey