Google 地图中如何使用折线的 setTag 保存自定义数据
How to use setTag of polyline to save custom data in Google Maps
当我点击折线时,我希望时间(自定义对象)显示在 特定 经纬度位置。
代码实现折线
PolylineOptions lineOptions = new PolylineOptions().width(7).color(Color.BLACK).geodesic(true);
for (int i = 0; i < points.size(); i++) {
LatLng latLng1 = new LatLng(Double.parseDouble(points.get(i).getmLatitude()), Double.parseDouble(points.get(i).getmLongitude()));
lineOptions.add(latLng1);
}
if (mPolyline != null) {
mPolyline.remove();
}
mPolyline = mMap.addPolyline(lineOptions);
mPolyline.setClickable(true);
for (int i = 0; i < points.size(); i++) {
//setting tags to be used on ployline click
mPolyline.setTag(points.get(i).getTime());
}
List<PatternItem> pattern = Arrays.asList(
new Gap(15), new Dash(15), new Gap(15));
mPolyline.setPattern(pattern);
mPolyline.setJointType(JointType.ROUND);
现在,当我点击多段线时,我只得到一个对所有人都相同的标签。我想要每个与经纬度相关的多段线位置的唯一标签(自定义对象)
mMap.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() {
@Override
public void onPolylineClick(Polyline polyline) {
Toast.makeText(mContext, (String) polyline.getTag(), Toast.LENGTH_SHORT).show();
}
});
感谢贡献:)
编辑
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
boolean isOnRoute = PolyUtil.isLocationOnPath(latLng, lineOptions.getPoints(), false, 25);
if (isOnRoute) {
for (LocationVo mCoordinates : points) {
double distanceInMeters = SphericalUtil.computeDistanceBetween(latLng, mCoordinates.getmLatLong());
boolean isWithin50m = distanceInMeters < 50;
if (isWithin50m) {
Toast.makeText(mContext, mCoordinates.getTime(), Toast.LENGTH_SHORT).show();
break;
}
}
}
}
});
并非我的所有多段线都符合条件并且在点击时不显示 toast
如果公差为 25 米,您将沿着每条路径段在两侧各 25 米处定义一条走廊。因此,在实施时,所有这些都告诉您点击点位于以路径为中心的走廊中的 某处 - 或者实际上他们点击了多段线,有一些错误空间。
你遇到的问题是你假设你总是在一个点的 50 米以内 - 这是不正确的,而且据我所知也不是你想要的。根据定义,一旦 isOnRoute
为真,您总是希望找到一个点,因为根据定义,他们点击了多段线;这是通过简单地计算从点击点到所有折线点的 all 距离并确定最短距离(一个简单的循环)来完成的(效率低下)
使用 min
逻辑);然后用这一点来敬酒。
现在,如果您真的想限制被认为是 "successful" 的点击,其中成功的点击是 "on the polyline" 和 "near a point",那么您的距离检查将是 使用一些可接受的值添加 - 这实际上是在每个点周围定义一个 "box",尺寸为 50 米(25 x 2)-无论你的距离检查是什么。请注意,这与仅检查每个点周围的半径圆不同,除非所需圆的 半径 等于折线公差。
(另一个微不足道的问题 - 当使用 false
进行测地线然后计算球面距离时你的混合测量系统 - 但不应该成为你的实现的问题。)(如果有帮助,我会添加一张图片稍后。)
修改摘要:"check if user clicks along the polyline" AND "determine closest point along line" AND "display some toast for that point".
所以在isOnRoute
为真后做这个修改:
LocationVo closestPoint = null;
double minDist = -1;
for (LocationVo mCoordinates : points) {
double distanceInMeters = SphericalUtil.computeDistanceBetween(latLng, mCoordinates.getmLatLong());
if (minDist < 0 || distanceInMeters < minDist) {
minDist = distanceInMeters;
closestPoint = mCoordinates;
}
}
if (closestPoint != null) {
Toast.makeText(mContext, closestPoint.getTime(), Toast.LENGTH_SHORT).show();
}
为了实现上面讨论的 "box" 围绕每个点修改一个条件:
if ((distanceInMeters < MAX_DISTANCE_FROM_POINT) && (minDist < 0 || distanceInMeters < minDist)) {
请注意,这意味着在某些情况下,即使他们沿着多段线单击,您也不会敬酒。
当我点击折线时,我希望时间(自定义对象)显示在 特定 经纬度位置。
代码实现折线
PolylineOptions lineOptions = new PolylineOptions().width(7).color(Color.BLACK).geodesic(true);
for (int i = 0; i < points.size(); i++) {
LatLng latLng1 = new LatLng(Double.parseDouble(points.get(i).getmLatitude()), Double.parseDouble(points.get(i).getmLongitude()));
lineOptions.add(latLng1);
}
if (mPolyline != null) {
mPolyline.remove();
}
mPolyline = mMap.addPolyline(lineOptions);
mPolyline.setClickable(true);
for (int i = 0; i < points.size(); i++) {
//setting tags to be used on ployline click
mPolyline.setTag(points.get(i).getTime());
}
List<PatternItem> pattern = Arrays.asList(
new Gap(15), new Dash(15), new Gap(15));
mPolyline.setPattern(pattern);
mPolyline.setJointType(JointType.ROUND);
现在,当我点击多段线时,我只得到一个对所有人都相同的标签。我想要每个与经纬度相关的多段线位置的唯一标签(自定义对象)
mMap.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() {
@Override
public void onPolylineClick(Polyline polyline) {
Toast.makeText(mContext, (String) polyline.getTag(), Toast.LENGTH_SHORT).show();
}
});
感谢贡献:)
编辑
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
boolean isOnRoute = PolyUtil.isLocationOnPath(latLng, lineOptions.getPoints(), false, 25);
if (isOnRoute) {
for (LocationVo mCoordinates : points) {
double distanceInMeters = SphericalUtil.computeDistanceBetween(latLng, mCoordinates.getmLatLong());
boolean isWithin50m = distanceInMeters < 50;
if (isWithin50m) {
Toast.makeText(mContext, mCoordinates.getTime(), Toast.LENGTH_SHORT).show();
break;
}
}
}
}
});
并非我的所有多段线都符合条件并且在点击时不显示 toast
如果公差为 25 米,您将沿着每条路径段在两侧各 25 米处定义一条走廊。因此,在实施时,所有这些都告诉您点击点位于以路径为中心的走廊中的 某处 - 或者实际上他们点击了多段线,有一些错误空间。
你遇到的问题是你假设你总是在一个点的 50 米以内 - 这是不正确的,而且据我所知也不是你想要的。根据定义,一旦 isOnRoute
为真,您总是希望找到一个点,因为根据定义,他们点击了多段线;这是通过简单地计算从点击点到所有折线点的 all 距离并确定最短距离(一个简单的循环)来完成的(效率低下)
使用 min
逻辑);然后用这一点来敬酒。
现在,如果您真的想限制被认为是 "successful" 的点击,其中成功的点击是 "on the polyline" 和 "near a point",那么您的距离检查将是 使用一些可接受的值添加 - 这实际上是在每个点周围定义一个 "box",尺寸为 50 米(25 x 2)-无论你的距离检查是什么。请注意,这与仅检查每个点周围的半径圆不同,除非所需圆的 半径 等于折线公差。
(另一个微不足道的问题 - 当使用 false
进行测地线然后计算球面距离时你的混合测量系统 - 但不应该成为你的实现的问题。)(如果有帮助,我会添加一张图片稍后。)
修改摘要:"check if user clicks along the polyline" AND "determine closest point along line" AND "display some toast for that point".
所以在isOnRoute
为真后做这个修改:
LocationVo closestPoint = null;
double minDist = -1;
for (LocationVo mCoordinates : points) {
double distanceInMeters = SphericalUtil.computeDistanceBetween(latLng, mCoordinates.getmLatLong());
if (minDist < 0 || distanceInMeters < minDist) {
minDist = distanceInMeters;
closestPoint = mCoordinates;
}
}
if (closestPoint != null) {
Toast.makeText(mContext, closestPoint.getTime(), Toast.LENGTH_SHORT).show();
}
为了实现上面讨论的 "box" 围绕每个点修改一个条件:
if ((distanceInMeters < MAX_DISTANCE_FROM_POINT) && (minDist < 0 || distanceInMeters < minDist)) {
请注意,这意味着在某些情况下,即使他们沿着多段线单击,您也不会敬酒。