【问题标题】:Android maps V2 newLatLngBounds with bearingAndroid 使用方位映射 V2 newLatLngBounds
【发布时间】:2013-01-15 21:10:11
【问题描述】:

我正在使用具有此布局的新 Android 地图 V2:

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:map="http://schemas.android.com/apk/res-auto"
  android:id="@+id/map"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  class="com.google.android.gms.maps.SupportMapFragment"
  map:cameraBearing="270"/>

我正在尝试使用方法 newLatLngBounds (LatLngBounds bounds, int padding) 来缩放和查看地图中的所有标记,但是相机方位角设置为 0。

谷歌开发者文档上的描述说:

public static CameraUpdate newLatLngBounds (LatLngBounds bounds, int 填充)(...)。返回的 CameraUpdate 的方位角为 0 和 倾斜 0. (...)"。

如何更改方位值?

我尝试在调用 newLatLngBounds 后以编程方式设置新方位,如下所示:

mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100));
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
.target(mMap.getCameraPosition().target)
.zoom(mMap.getCameraPosition().zoom)
.bearing(270)
.build()));

但是当我这样做时,一些标记不会出现。

【问题讨论】:

  • @Mike-Bell 不,我没有。我认为当前的android地图库是不可能的。

标签: android android-maps-v2


【解决方案1】:

是的,你可以! 只需使用: https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap#animateCamera(com.google.android.gms.maps.CameraUpdate, int, com.google.android.gms.maps.GoogleMap.CancelableCallback)

并实现一个 CancelableCallback 并放入 onFinish() 方法: https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.CancelableCallback#onFinish()

更换轴承的代码。 当然,你不会得到一个动画,而是两个动画链,但它会起作用!

mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100)/*,DURATION_IN_MS_IF_NEEDED*/,new GoogleMap.CancelableCallback(){
    @Override
    public void onCancel() {
        //DO SOMETHING HERE IF YOU WANT TO REACT TO A USER TOUCH WHILE ANIMATING
    }
    @Override
    public void onFinish() {
        mMap.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
/*.target(mMap.getCameraPosition().target)
.zoom(mMap.getCameraPosition().zoom)*/
.bearing(270)
.build()));
    }
});

我认为您不需要定位和缩放,我将它们注释掉,因为它应该由之前的动画管理

编辑 更好地查看API,我有一个可以工作的方法(我现在无法测试它,请看一下: 拥有 LatLngBounds 您可以获得最适合该区域的缩放级别(它取决于设备尺寸,因此您必须在运行时获取视图尺寸),然后,当您进行缩放时(您还有LatLngBounds),您可以使用一个独特的动画进行相机更新: https://developers.google.com/android/reference/com/google/android/gms/maps/model/CameraPosition,构造函数允许设置值,或者您可以使用之前看到的构建器。

你可以在网上找到各种方法来做到这一点,例如(只是在网上快速搜索得到一个javascript版本https://stackoverflow.com/a/13274361/4120431

希望这可以帮助您解决问题!

【讨论】:

  • 这个问题的重点是创建一个同时做这两件事的地图动画
  • 它把两件事都串联起来。没有其他方法可以同时进行!
  • 我还需要查看所有标记,这就是我使用 newLatLngBound() 的原因。如果我改变方位而不是缩放一些标记将在该动画之后隐藏。
  • @pedroca 如果您取消目标和缩放,代码是否有效?
  • 当我们将目标设为空时应用程序崩溃
【解决方案2】:

我有一个替代方案,我遇到了同样的问题。我将展示如何将边界转换为缩放,然后我们将简单地使用 CameraPosition.builder() 来创建正确的位置。

private static final double LN2 = 0.6931471805599453;
    private static final int WORLD_PX_HEIGHT = 256;
    private static final int WORLD_PX_WIDTH = 256;
    private static final int ZOOM_MAX = 21;

    public int getBoundsZoomLevel(LatLngBounds bounds, int mapWidthPx, int mapHeightPx){

        LatLng ne = bounds.northeast;
        LatLng sw = bounds.southwest;

        double latFraction = (latRad(ne.latitude) - latRad(sw.latitude)) / Math.PI;

        double lngDiff = ne.longitude - sw.longitude;
        double lngFraction = ((lngDiff < 0) ? (lngDiff + 360) : lngDiff) / 360;

        double latZoom = zoom(mapHeightPx, WORLD_PX_HEIGHT, latFraction);
        double lngZoom = zoom(mapWidthPx, WORLD_PX_WIDTH, lngFraction);

        int result = Math.min((int)latZoom, (int)lngZoom);
        return Math.min(result, ZOOM_MAX);
    }

    private double latRad(double lat) {
        double sin = Math.sin(lat * Math.PI / 180);
        double radX2 = Math.log((1 + sin) / (1 - sin)) / 2;
        return Math.max(Math.min(radX2, Math.PI), -Math.PI) / 2;
    }
    private double zoom(int mapPx, int worldPx, double fraction) {
        return Math.floor(Math.log(mapPx / worldPx / fraction) / LN2);
    }

然后您可以使用此代码并添加带有边界的方位/和/或倾斜:

            LatLngBounds bounds = LatLngBounds.builder()
                    .include(swCorner)
                    .include(neCorner).build();
            CameraPosition cp = new CameraPosition.Builder()
                    .bearing(randomBearing())
                    .tilt(randomTilt())
                    .target(latLng)
                    .zoom(getBoundsZoomLevel(bounds, findViewById(R.id.map).getMeasuredWidth(), findViewById(R.id.map).getMeasuredHeight()))
                    .build();
            CameraUpdate cu = CameraUpdateFactory.newCameraPosition(cp);
            mMap.animateCamera(cu);

这将起作用(您必须将 mMap 更改为您的实际地图变量,并将 id 更改为您的地图 ID)。

祝你好运!我从帖子中得到了 boundZoomLevel:How do I determine the zoom level of a LatLngBounds before using map.fitBounds? 如果你有时间,也去喜欢那个答案!

【讨论】:

  • 这很棒;谢谢!但我想知道两件事。我认为 WORLD_PX 常量实际上是 256 dp,而视图尺寸被返回为 px,这可能会导致缩放错误。此外,在旋转之后,边界的“角”可能会从地图上旋转。理想情况下,坐标旋转应该在确定边界之前发生。 (而且我不确定 Math.floor 是必要的还是有益的。)
  • Peter 是正确的,WORLD PX 需要更正密度 => (int) (GLOBE_WIDTH * context.getResources().getDisplayMetrics().density)
  • @Jordy 你能澄清一下吗,我写这篇文章已经很长时间了,我真的不记得我在做什么了。应该更换哪个PX?这个变量的宽度和高度?
  • 我已经添加了一个要点,当前工作的 kotlin 被剪断了gist.github.com/kibotu/f9bda6831573e8226fc3298df8ac73be
【解决方案3】:

Google 的 CameraUpdateFactory 出现问题 我用时间解决了,时间跨度很小!

public void zoomToBounds() {
    LatLngBounds latLngBounds = getBoundsOfInput(inputPoints);
    final int PADDING = 20;

    final CameraPosition now = map.getCameraPosition();
    final float tilt = map.getCameraPosition().tilt;
    final float bearing = map.getCameraPosition().bearing;
    final LatLng[] target = new LatLng[1];
    final float[] zoom = new float[1];

    map.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, PADDING), 1, null);

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            target[0] = map.getCameraPosition().target;
            zoom[0] = map.getCameraPosition().zoom;
        }
    }, 10);
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            map.animateCamera(CameraUpdateFactory.newCameraPosition(now), 1, null);
        }
    }, 30);

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            map.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition(target[0], zoom[0], tilt, bearing)));
        }
    }, 60);
}

看起来很脏,但可以工作

3 Handler 完成工作,每个后延迟必须大于前一个

【讨论】:

  • 使用时间跨度不是一个好主意,轮换和外部事件会导致不可预测的行为
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 1970-01-01
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多