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中折线的触摸检测的主要内容,如果未能解决你的问题,请参考以下文章