【问题标题】:Restricting the area the user can go to on Mapview限制用户在 Mapview 上可以去的区域
【发布时间】:2011-07-21 04:44:06
【问题描述】:

我正在使用自定义版本的地图视图(OSMDroid 版本)。 我在其中使用自定义图块,我只希望用户能够查看我拥有自定义图块的区域。 有没有办法设置边界纬度,这样当他们平移地图时就不会越过这些边界?

【问题讨论】:

    标签: android google-maps openstreetmap osmdroid


    【解决方案1】:

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

    原答案:

    请留意:

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

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

        我有一种我正在使用的解决方案,它工作正常,但肯定会更好,因为地图在跳回之前可能会离屏幕太远! 它使用经纬度并计算出地图的位置,我设置了 4 个坐标,它们大致是地图的 4 个角lat longs 完全离开了屏幕。如果是这样,它会在中途反弹:

        我覆盖了地图视图和地图的 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】:

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

          我最好的线索是添加一个覆盖,它扩展了boolean onScroll(...)。如果返回 true,则取消滚动。

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

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

          【讨论】:

          • @Kevin,显然有人创建了一个包含边界框的项目分支,但我无法尝试,因为我使用的是旧版本的项目,无法更新,也无法解决如何将它与我自己的版本集成.. 我想出了下面的一种解决方案
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-21
          • 2012-10-29
          • 2011-04-02
          • 2014-05-01
          相关资源
          最近更新 更多