限制用户可以在Mapview上访问的区域

时间:2011-03-23 10:21:11

标签: android google-maps openstreetmap osmdroid

我正在使用mapview的自定义版本(OSMDroid版本)。 我在其中使用自定义图块,我只希望用户能够查看我有自定义图块的区域。 有没有办法设置边界lat long,所以当它们平移地图时它不会越过这些边界?

4 个答案:

答案 0 :(得分:6)

更新:我知道这是一个老问题,但osmdroid现在有一个setScrollableAreaLimit()方法,可以实现你想要的。还有一个setMinZoomLevel()和setMaxZoomLevel()方法可以轻松限制缩放级别。

原始答案:

请留意:

http://code.google.com/p/osmdroid/issues/detail?id=209

已经创建了一个补丁,很快就会集成。

答案 1 :(得分:3)

这是the osmdroid thread的交叉发布。现在列出了一个BoundedMapView类,它实现了一个很好的补丁。

  

对于那些使用.jar或其他不熟悉的人   补丁,我拼凑了一个支持的MapView的子类   将用户的视图限制在特定区域。

     

如何使用它的详细信息,   如果不明显,可以在   http://www.sieswerda.net/2012/08/15/boundedmapview-a-mapview-with-limits/

答案 2 :(得分:1)

它可以帮助任何人......

我有一种我正在使用的解决方案,它运行正常,但绝对可以更好,因为地图可以在它跳回来之前离屏幕太远了! 它使用lat longs并计算出地图的位置,我设置了4个坐标,这些坐标大致是地图的4个角落,我发现如果你将它们稍微放入地图而不是角落,它会更好地工作,然后我会研究出来lat longs完全离开了屏幕......如果是这样,它会在半途中反弹:

我覆盖了mapview和地图的OnTouch事件

@Override
public boolean onTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_UP) {

        // (only works for north of equator)
        // * map right side (lat) can't go past the left (lat) of screen

        // get geopoints of the 4 corners of the screen
        Projection proj = getProjection();
        GeoPoint screenTopLeft = proj.fromPixels(0, 0);
        GeoPoint screenTopRight = proj.fromPixels(getWidth(), 0);
        GeoPoint screenBottomLeft = proj.fromPixels(0, getHeight());

        double screenTopLat = screenTopLeft.getLatitudeE6() / 1E6;
        double screenBottomLat = screenBottomLeft.getLatitudeE6() / 1E6;
        double screenLeftlong = screenTopLeft.getLongitudeE6() / 1E6;
        double screenRightlong = screenTopRight.getLongitudeE6() / 1E6;

        double mapTopLat = BoundsTopLeftCorner.getLatitudeE6() / 1E6;
        double mapBottomLat = BoundsBottomLeftCorner.getLatitudeE6() / 1E6;
        double mapLeftlong = BoundsTopLeftCorner.getLongitudeE6() / 1E6;
        double mapRightlong = BoundsTopRightCorner.getLongitudeE6() / 1E6;

        // screen bottom greater than map top
        // screen top less than map bottom
        // screen right less than map left
        // screen left greater than map right
        boolean movedLeft = false;
        boolean movedRight = false;
        boolean movedUp = false;
        boolean movedDown = false;

        boolean offscreen = false;
        if (screenBottomLat > mapTopLat) {
            movedUp = true;
            offscreen = true;
        }
        if (screenTopLat < mapBottomLat) {
            movedDown = true;
            offscreen = true;
        }
        if (screenRightlong < mapLeftlong) {
            movedLeft = true;
            offscreen = true;
        }
        if (screenLeftlong > mapRightlong) {
            movedRight = true;
            offscreen = true;
        }

        if (offscreen) {
            // work out on which plane it's been moved off screen (lat/lng)

            if (movedLeft || movedRight) {

                double newBottomLat = screenBottomLat;
                double newTopLat = screenTopLat;

                double centralLat = newBottomLat
                        + ((newTopLat - newBottomLat) / 2);
                if (movedRight)
                    this.getController().setCenter(
                            new GeoPoint(centralLat, mapRightlong));
                else
                    this.getController().setCenter(
                            new GeoPoint(centralLat, mapLeftlong));

            }
            if (movedUp || movedDown) {

                // longs will all remain the same
                double newLeftLong = screenLeftlong;
                double newRightLong = screenRightlong;

                double centralLong = (newRightLong + newLeftLong) / 2;

                if (movedUp)
                    this.getController().setCenter(
                            new GeoPoint(mapTopLat, centralLong));

                else
                    this.getController().setCenter(
                            new GeoPoint(mapBottomLat, centralLong));
            }

        }

    }
    return super.onTouchEvent(ev);
}}

如果你正在考虑使用这个,我应该指出一些事情:

  1. 我不会保证它会适合你的情况,你应该只把它当作一个起点。
  2. 由于我完成了坐标的方式,它只适用于赤道以北的地区(我想)!
  3. 它适用于触摸事件的“动作上升”,因此需要用户将手指从屏幕上移开。这意味着当地图晃动时它完全不准确,因为我无法解决地图停止的地方,因此我通过覆盖投掷事件并且没有做任何事情来关闭投掷......这确实使地图有点混乱!
  4. 如果有人有更好的解决方案或可以改进我的代码,请随意!

答案 3 :(得分:0)

我正在寻找完全相同的东西。

我最好的方法是添加一个展开boolean onScroll(...)的叠加层。如果返回true,则取消滚动。

这正是我想要的,除了一件事:投掷/轻弹。可以使用相同的方法取消投掷事件,但您只能在投掷开始时听到它。

理想情况下,您可以根据computeScroll()(x, y)收听mScroller.getCurX()方法,并限制滚动的mScroller.getCurY()