Google Maps Android API v2中折线的触摸检测
Posted
技术标签:
【中文标题】Google Maps Android API v2中折线的触摸检测【英文标题】:Touch detection on polyline in Google Maps Android API v2 【发布时间】:2015-06-16 23:15:56 【问题描述】:我想在使用 Google Maps V2 android API 显示的折线上实现 touchListener
。
缩放级别:
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(lat_Lng, 5);
我尝试了以下折线触摸代码:
boolean onpoly = false;
for (Polyline polyline : mPolylines)
for (LatLng polyCoords : polyline.getPoints())
float[] results = new float[1];
Location.distanceBetween(points.latitude, points.longitude, polyCoords.latitude, polyCoords.longitude, results);
if (results[0] < 100 )
onpoly = true;
Marker mark = map.addMarker(new MarkerOptions().position(points).title("AddEvent")
.snippet("" + addressaddexpense).icon(BitmapDescriptorFactory.fromResource(R.drawable.addicon)));
UtilsClass.dropPinEffect(mark);
// end if..
// end for loop
// end for loop
if (onpoly == true)
Toast.makeText(getActivity(), "Poly line detected", Toast.LENGTH_SHORT).show();
// end if
它有效,但并不完美。 除非我放大,否则它不会检测到触摸事件,有时会迫使我在缩放之前点击地图超过 5 次以实现检测。
然后我将前面提到的if
条件从if (results[0] < 100 )
更改为if (results[0] < 150 * (22 - map.getCameraPosition().zoom))
并且功能得到了改进,但它仍然不能一直工作。
注意:我想在任何缩放级别检测折线触摸。
【问题讨论】:
我有以下问题希望您能提供比我目前更好的答案: 1. 发布的代码在哪里?是在onMapClickListener
中吗? dispatchTouchEvent
?别的东西? 2.当你说要检测折线触摸时;您是指点击线路还是还想启用滑动或其他触摸手势?
我在 onMapLongClickListener 中使用了这段代码..
好的,所以请尝试 onMapClickListener (长按实际上旨在执行您所描述的操作,只有在长按不带移动的项目后才会调用它)并查看我的答案: )
【参考方案1】:
试试这个
final List<LatLng> latLngList; // Extract polyline coordinates and put them on this list
private GoogleMap map;
for(int i = 0; i < latLngList.size(); i++)
MarkerOptions mar = new MarkerOptions();
mar.position(new LatLng(latLngList.get(i).latitude, latLngList.get(i).longitude)).icon(BitmapDescriptorFactory.fromResource(R.drawable.trasparent_image)); //this image should be very small in size and transparent
map.addMarker(mar);
map.setOnMarkerClickListener(new OnMarkerClickListener()
@Override
public boolean onMarkerClick(Marker arg0)
for(int i = 0; i < latLngList.size(); i++)
if(latLngList.get(i).latitude == arg0.getPosition().latitude && latLngList.get(i).longitude == arg0.getPosition().longitude)
Toast.makeText(MainActivity.this, "PolyLineClick ", Toast.LENGTH_SHORT).show();
break;
return false;
);
【讨论】:
您只需要一张透明图片并用标记替换它 让我看看这个方法 你的方法是正确的..但是,在这里,折线坐标列表大小将超过五万(50k)。此外,arraylist out of memory 错误来了..我无法将所有折线值存储在一个列表中.. 我建议不要保留平滑路径的所有坐标,只存储steps数组的坐标,它会工作得很好;但是在某处它不会在低缩放级别的情况下消耗点击,但在较高的缩放级别它不会有任何区别 我无法理解 step 数组中的存储坐标。我该如何存储它?我知道普通的arraylist。【参考方案2】:在我的 cmets 中的问题得到解答之前,我想我会尝试通过建议使用 3rd 方库来使它们变得多余; android-maps-utils
要做我认为您可能会尝试做的事情,只需集成库并使用以下行:
PolyUtil.isLocationOnPath(point, polyline.getPoints(), isGeodesic, tolerance);
有关更多信息,您还可以查看似乎适用的thread。
祝你好运。
【讨论】:
我试过这个 royiby。但是,我在这两个参数中遇到错误 isGeodesic,公差。我在哪里可以获得这些参数的值..我在谷歌中搜索并超过了那条线.. 这2个参数是关于你的检测偏好的,你尝试了哪些值? isGeodesic 是一个布尔值 - 因为您正在检测一条线,所以我会同时尝试真假,看看哪个效果最好。容差也是一个关于您希望触摸有多轻以将其关闭的参数,因此我将从 0 开始,这不是容差,因此最轻微的触摸会将其关闭以进行测试。让它运行后,尝试对其进行微调以使其良好但不烦人(我希望你不希望有任何颠簸来设置它)。 我试过这个 roy..PolyUtil.isLocationOnPath(points, mPolylines, true, 0.0) ;但是,我得到了这个错误..... PolyUtil 类型的方法 isLocationOnPath(LatLng, List我认为你的方法是正确的。唯一失败的是距离检查。这是因为操作系统的触摸和缩放级别:
您知道,当您点击屏幕时,传递给应用程序的屏幕点是您手指表面的中心,即与屏幕接触。这意味着,即使看起来你的手指正好在PolyLine
上方,它也可以移动一些像素......
现在是缩放级别的时间,根据其当前值,传递给应用程序的点与PolyLine
之间的距离可能会有很大差异。
因此,if
子句失败,您必须点击多次,直到您的某些点击足够接近PolyLine
。当然,更高的缩放级别会变得更好。
您应该像在编辑的代码中那样包含缩放级别,但要添加一些额外内容:检查您将允许输入if
的“增量”,但在最大缩放级别上。它应该是一个很小的值。然后您只需将其乘以当前缩放级别,并计算此增量如何变化。在您的if
比较中使用此缩放相关值。为了增强它,您可以进行更复杂的计算并从像素距离开始获取此增量。比方说,接受PolyLine
50px 或更小的点击。以米为单位计算此像素距离,再次在最大缩放级别上使用它乘以当前缩放...要进一步增强它,您可以获得此像素距离,这取决于屏幕分辨率和密度。
在这里,您可以找到如何将屏幕像素计算为米:https://***.com/a/13635952/4776540
【讨论】:
【参考方案4】:我通过以下方式实现了类似的东西:
-
使用
map.getProjection().toScreenLocation()
将所有位置转换为屏幕坐标
使用标准距离公式确定点到点(或点到线段,如果您也想检测线段上的点击)的距离,如果该距离小于某个阈值 - 检测到点击。
这里的重点是使用地图投影来获取屏幕坐标。这样,决定取决于屏幕上的实际像素距离,而不取决于缩放级别。
【讨论】:
以上是关于Google Maps Android API v2中折线的触摸检测的主要内容,如果未能解决你的问题,请参考以下文章