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] &lt; 100 ) 更改为if (results[0] &lt; 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, boolean, double) 不适用于参数 (LatLng, List, boolean, double)跨度> map.setOnMapClickListener(new GoogleMap.OnMapClickListener() @Override public void onMapClick(LatLng points) PolyUtil.isLocationOnPath(points, mPolylines, true, 0.0) ; );【参考方案3】:

我认为你的方法是正确的。唯一失败的是距离检查。这是因为操作系统的触摸和缩放级别:

您知道,当您点击屏幕时,传递给应用程序的屏幕点是您手指表面的中心,即与屏幕接触。这意味着,即使看起来你的手指正好在PolyLine 上方,它也可以移动一些像素......

现在是缩放级别的时间,根据其当前值,传递给应用程序的点与PolyLine 之间的距离可能会有很大差异。

因此,if 子句失败,您必须点击多次,直到您的某些点击足够接近PolyLine。当然,更高的缩放级别会变得更好。

您应该像在编辑的代码中那样包含缩放级别,但要添加一些额外内容:检查您将允许输入if 的“增量”,但在最大缩放级别上。它应该是一个很小的值。然后您只需将其乘以当前缩放级别,并计算此增量如何变化。在您的if 比较中使用此缩放相关值。为了增强它,您可以进行更复杂的计算并从像素距离开始获取此增量。比方说,接受PolyLine 50px 或更小的点击。以米为单位计算此像素距离,再次在最大缩放级别上使用它乘以当前缩放...要进一步增强它,您可以获得此像素距离,这取决于屏幕分辨率和密度。

在这里,您可以找到如何将屏幕像素计算为米:https://***.com/a/13635952/4776540

【讨论】:

【参考方案4】:

我通过以下方式实现了类似的东西:

    使用map.getProjection().toScreenLocation()将所有位置转换为屏幕坐标 使用标准距离公式确定点到点(或点到线段,如果您也想检测线段上的点击)的距离,如果该距离小于某个阈值 - 检测到点击。

这里的重点是使用地图投影来获取屏幕坐标。这样,决定取决于屏幕上的实际像素距离,而不取决于缩放级别。

【讨论】:

以上是关于Google Maps Android API v2中折线的触摸检测的主要内容,如果未能解决你的问题,请参考以下文章

Maps SDK for Android v.3.0.0 BETA "是否可以在没有Google Play服务的设备上运行?

Google Maps API v.3.31更新会破坏StageWebView和StageWebViewBridge

Google Maps Android API V2 检查 Google Maps 应用程序是不是被禁用

无法运行 Google Maps Android API Utility Demo

Google Geolocation API 和 Google Maps Android SDK

Android:使用 Google API 获取实时方向,还是与 Google Maps 通信?