百度地图获取缩放级别

目前在做一个产品的大改版,主要是交互方式变化很大,尤其是增加了地图相关交互,类似于滴滴、优步首页。
map.png

开发时遇到的很大的一个问题就是缩放控制,由于界面中同时存在地图及输入覆盖层,在地图上添加标注时需要精确控制标注显示区域,使标注显示范围控制在覆盖层区域上方。

遮盖区域.jpeg

查阅android端相关api后发现缩放控制主要由此类 MapStatusUpdateFactory 间接来完成。

api.png

尝试所有方法后发现百度提供的api不能同时控制地理范围及中心点😓,
MapStatusUpdateFactory.newLatLngBounds(builder.build()) 此方法可控制所有标注显示在以地图中心为中心点的整个地图上,但无法控制中心点位置。

尝试人为构造边界点来控制显示

示例.jpeg

如上图,红色为原始点,紫色为根据当前屏幕未被覆盖区域宽高及经纬度差值比例生成的边界点,实际测试后发现 MapStatusUpdateFactory.newLatLngBounds(builder.build()) 此方法不能完美显示。

尝试获取设置中心点及缩放比例

MapStatus 此类也可控制地图。

  MapStatus mapStatus = new MapStatus.Builder()
                    .target(builder.build().getCenter())
                    .zoom(zoom)
                    .targetScreen(point).build();

            mMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(mapStatus));

FADF5D67-2020-44F9-B3B2-EC42049D7E95.png

此方法可控制中心点经纬度及中心点屏幕坐标,适合精确控制单个点。但是MapStatus.Builder 此构造类只提供了缩放级别设置,并不能设置经纬度范围,在查阅了api后发现百度并未提供根据经纬度范围获取缩放比例的api,网上给出的很多方法为通过比例尺、缩放级别计算,很不靠谱...... 遂放弃此方法。

询问了百度地图的产品和技术,告知的方法还是通过MapStatusUpdateFactory 来完成,并不能达到我们的要求,但是ios 提供了相关的方法 😓。

为了不影响开发进度,开发前期采用了人为构造边界点的方法。

在项目主流程接近完成时,又重新开始地图的开发,对百度提供的一些类进行了仔细研究。发现 MapStatusUpdateFactory 类的 MapStatusUpdateFactory 方法,也就是人为构造边界点所使用的方法:

    public static MapStatusUpdate newLatLngBounds(LatLngBounds var0) {
        if(var0 == null) {
            return null;
        } else {
            MapStatusUpdate var1 = new MapStatusUpdate(3);
            var1.d = var0;
            return var1;
        }
    }

在所构造的 MapStatusUpdate 对象在此方法mMap.animateMapStatus(MapStatusUpdateFactory.newLatLngBounds(builder.build())); 调用过程中,会调用以下方法:

 MapStatusUpdate(int var1) {
        this.a = var1;
    }

    MapStatus a(e var1, MapStatus var2) {
        if(null != var1 && null != var2) {
            switch(this.a) {
            case 1:
                return this.b;
            case 2:
                return new MapStatus(var2.rotate, this.c, var2.overlook, var2.zoom, var2.targetScreen, (LatLngBounds)null);
            case 3:
                double var3 = 0.0D;
                double var5 = 0.0D;
                double var7 = 0.0D;
                double var9 = 0.0D;
                GeoPoint var11 = CoordUtil.ll2mc(this.d.southwest);
                GeoPoint var12 = CoordUtil.ll2mc(this.d.northeast);
                var3 = var11.getLongitudeE6();
                var5 = var12.getLatitudeE6();
                var7 = var12.getLongitudeE6();
                var9 = var11.getLatitudeE6();
                float var13 = var1.a((int)var3, (int)var5, (int)var7, (int)var9, var2.a.j.right - var2.a.j.left, var2.a.j.bottom - var2.a.j.top);
                LatLng var14 = this.d.getCenter();
                return new MapStatus(var2.rotate, var14, var2.overlook, var13, var2.targetScreen, (LatLngBounds)null);
}

case 3 返回的 MapStatus 对象的构造方法为:

   MapStatus(float var1, LatLng var2, float var3, float var4, Point var5, LatLngBounds var6) {
        this.rotate = var1;
        this.target = var2;
        this.overlook = var3;
        this.zoom = var4;
        this.targetScreen = var5;
        if(this.target != null) {
            this.b = CoordUtil.ll2mc(this.target).getLongitudeE6();
            this.c = CoordUtil.ll2mc(this.target).getLatitudeE6();
        }

        this.bound = var6;
    }

注意这个构造方法的 var4 参数,此参数为缩放级别。

传入的值便是由此方法计算出来的:
float var13 = var1.a((int)var3, (int)var5, (int)var7, (int)var9, var2.a.j.right - var2.a.j.left, var2.a.j.bottom - var2.a.j.top);

这个类是什么鬼

public class e implements b {
     public e(Context var1, String var2) {
       this.A = var1;
       this.f = new ArrayList();
       this.an = var2;
   }
}

本想自己实例化一个对象,发现找不到这个 an 到底是什么东西...... 直接实例化的方法失败了。

在经过一番查找后,在 BaiduMap 中找到了这个类的实例

    private e i;
    BaiduMap(af var1) {
        this.j = var1;
        this.i = this.j.b();
        this.d = ad.b;
        this.c();
    }

    BaiduMap(j var1) {
        this.h = var1;
        this.i = this.h.a();
        this.d = ad.a;
        this.c();
    }

并且是在 BaiduMap 实例化时就被实例化了!!!

这个属性是 private 的,并不能直接获取,需要通过反射获取:

        Field eField = null;
        eField = BaiduMap.class.getDeclaredField("i");
        eField.setAccessible(true);
        com.baidu.platform.comapi.map.e zoomUtils = (com.baidu.platform.comapi.map.e) eField.get(baiduMap);

获取到这个类的实例后,就可以调用它的方法计算缩放级别了:

public float a(int var1, int var2, int var3, int var4, int var5, int var6) {
        if(!this.i) {
            return 12.0F;
        } else if(this.g == null) {
            return 0.0F;
        } else {
            Bundle var7 = new Bundle();
            var7.putInt("left", var1);
            var7.putInt("right", var3);
            var7.putInt("bottom", var4);
            var7.putInt("top", var2);
            var7.putInt("hasHW", 1);
            var7.putInt("width", var5);
            var7.putInt("height", var6);
            return this.g.c(var7);
        }
    }

传入相关参数

       GeoPoint southwest = CoordUtil.ll2mc(builder.build().southwest);
        GeoPoint northeast = CoordUtil.ll2mc(builder.build().northeast);
        double left = southwest.getLongitudeE6();
        double top = northeast.getLatitudeE6();
        double right = northeast.getLongitudeE6();
        double bottom = southwest.getLatitudeE6();
        float zoom = zoomUtils.a((int) left, (int) top, (int) right, (int) bottom, width, height);

此时就得到缩放级别了,最后的 widthheight 为显示区域 。

上述计算方法经过层层调用,最终会调用native方法

public class JNIBaseMap {
    public long a;

    public JNIBaseMap() {
    }

    public native float GetZoomToBound(long var1, Bundle var3);
}

实际测试中,比人为构造边界点的效果好很多,但是存在宽高区域控制无效的情况,目前暂无更好的办法,只能期望百度开放相关的接口了......

最后附上完整代码


 public static float getFitZoom(BaiduMap baiduMap, LatLngBounds.Builder builder, int width, int height) throws Exception {
        Field eField = null;
        eField = BaiduMap.class.getDeclaredField("i");
        eField.setAccessible(true);
        com.baidu.platform.comapi.map.e zoomUtils = (com.baidu.platform.comapi.map.e) eField.get(baiduMap);
        GeoPoint southwest = CoordUtil.ll2mc(builder.build().southwest);
        GeoPoint northeast = CoordUtil.ll2mc(builder.build().northeast);
        double left = southwest.getLongitudeE6();
        double top = northeast.getLatitudeE6();
        double right = northeast.getLongitudeE6();
        double bottom = southwest.getLatitudeE6();
        float zoom = zoomUtils.a((int) left, (int) top, (int) right, (int) bottom, width, height);
        Log.e("zoom",zoom+"");
        return zoom;
    }

注:百度地图版本4.5.2

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容

  • 因为要做一个地图操作的项目,需要用到这个地图库,但是查询官方API麻烦,而且这个地图框架的API做的用起来确实太麻...
    虚幻的锈色阅读 33,891评论 1 15
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,656评论 18 139
  • 【 申请密钥AndroidSDK:应用程序包名+数字签名 As查看数字签名:cmd-----cd .android...
    征程_Journey阅读 2,277评论 0 5
  • 感恩帮助我的所有人,支持我的所有人 没有反思的人生不值得过 每一个目标都要心甘情愿,都要找到坚持的原因 90天目标...
    yunzhan阅读 141评论 0 1
  • 注定一场无根的漂泊 像落叶,像思念 那些不肯安放的 那些不肯停留的 也许是你,也许是我 有颠沛流离的伤口 找不到一...
    燕返楼兰阅读 185评论 0 4