高德API使用小结-定位和marker

功能描述:实现一个普通的地图展示,地图上有当前定位小蓝点和门店定位Marker信息。当前定位需要从定位服务异步获取,可能失败,门店的位置从接口异步获取,两个异步的数据最终展示在一个地图View上,并且Marker需要展示info window,需要两者不重叠不遮挡完全展示。

效果如下图:


需求.png

接入准备:

1、下载jar包(如Android_Map3D_SDK_V5.2.1_20170630.jar),放入工程libs目录。
2、build.gradle文件添加:
compile 'com.amap.api:3dmap:latest.integration'
3、添加meta-date,appkey信息。
4、添加地图需要的权限,如定位等。

使用步骤:

xml中添加布局:
<com.amap.api.maps.MapView
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:layout_marginTop="30dp" />

SDK底层使用OpenGL ES实现了两个地图组件,分别是GLSurfaceView、TextureView。

特点:
1、GLSurfaceView
包括 MapView、MapFragment、SupportMapFragment 三种容器。下面简单介绍一下 SupportMapFragment:
MapFragment 是 Android Fragment 类的一个子类,用于在 Android Fragment 中放置地图。 MapFragment 也是地图容器,与 MapView 一样提供对 AMap 对象(地图的控制类)的访问权。与 MapView 相比 SupportMapFragment 方便之处在于其可以更好的管理地图的生命周期,布局灵活。
2、TextureView
包括TextureMapView、TextureMapFragment、TextureSupportMapFragment 三种容器。
使用场景:您将MapView与其他的GLSurfaceView(比如相机)叠加展示,或者是在ScrollView中加载地图时,建议使用TextureMapView及SupportTextureMapFragment来展示地图,可以有效解决 GLSurfaceView 叠加时出现的穿透、滚动黑屏等问题。

根据需求合理选择实现的组件和方式

初始化MapView和管理对象AMap,显示地图
MapView mMapView.onCreate(savedInstanceState);
aMap = mMapView.getMap();

// info window的适配器
aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
    @Override
    public View getInfoWindow(Marker marker) {
       return null;
    }
    @Override
    public View getInfoContents(Marker marker) {
        return null;
    }
}

// 搞一些marker,然后给marker设置info window,这个过程由aMap来完成
Marker maker = aMap.addMarker(new MarkerOptions()
                .icon(BitmapDescriptorFactory.fromBitmap(
                        BitmapFactory.decodeResource(getResources(), R.drawable.xxx)))
                .title("title")
                .snippet("xxx")
                .anchor(0.5F, 0.5F)
                .position(storeLatLng)
                .draggable(false)
                .setFlat(true));


// 设置地图的UI属性
UiSettings uiSettings = aMap.getUiSettings();
// 隐藏缩放控件
uiSettings.setZoomControlsEnabled(false);
// 隐藏比例尺控件
uiSettings.setScaleControlsEnabled(false);
...

// 设置事件交互
aMap.setOnMarkerClickListener(new AMap.OnMarkerClickListener() {
    @Override
    public boolean onMarkerClick(Marker marker) {
        // 消耗事件,不继续传递
        return true;
    }
});
aMap.setOnInfoWindowClickListener(new AMap.OnInfoWindowClickListener() {
    @Override
    public void onInfoWindowClick(Marker marker) {
        // 点击打开导航dialog
        ToastUtil.showShortMsg(XXX.this, "打开导航dialog");
    }
});

// 开始定位,并显示定位小蓝点
final MyLocationStyle myLocationStyle = new MyLocationStyle();
// 设置自定义小蓝点的图标
myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.mylocation));
// 设置小蓝点的锚点
myLocationStyle.anchor(0.5F, 0.5F);
// 设置小蓝点的边框颜色
myLocationStyle.strokeColor(getResources().getColor(R.color.blue));
// 设置小蓝点的填充颜色
myLocationStyle.radiusFillColor(Color.argb(100, 29, 161, 242));
// 设置小蓝点的边框粗细
myLocationStyle.strokeWidth(1.0F);
// 表示地图只定位一次
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);
// 是否显示定位小蓝点
myLocationStyle.showMyLocation(true);
aMap.setMyLocationStyle(myLocationStyle);

// 高德api在5.0对定位的实现做了更改,官网(https://lbs.amap.com/api/android-sdk/guide/create-map/mylocation)
aMap.setOnMyLocationChangeListener(new AMap.OnMyLocationChangeListener() {
    @Override
    public void onMyLocationChange(Location location) {
        // 从location对象中获取经纬度信息,地址描述信息,建议拿到位置之后调用逆地理编码接口获取(获取地址描述数据章节有介绍)
        if (location != null) {
            locationLatLng = new LatLng(location.getLatitude(), location.getLongitude());
            if (storeLatLng != null) {
                zoomToSpanWithCenter();
            }
        }
    }
});

// 设置为true表示启动显示定位小蓝点,false表示隐藏定位小蓝点并不进行定位,默认是false。
aMap.setMyLocationEnabled(true);

现在地图就可以正常展示了,定位完成后,会显示定位小蓝点,我们设置为只定位一次,这样可以节省性能和电量,并且也符合需求。

还有一些问题:
1、高德地图缩放级别分为大概20级,我们需要显示一个合适的级别。
2、我们给marker设置的info window会出现被遮挡的情况。

接下来对地图做进一步的约束

1、缩放到合适的级别:
LatLngBounds.Builder这个api可以帮助我们获取最佳的展示缩放比例,我们需要指定一个中心点,另外在传入一些我们需要展示的经纬度的集合,然后它会返给我们一个存储有合适范围约束的LatLngBounds对象。

private LatLngBounds getLatLngBounds(LatLng centerPoint, List<LatLng> pointList) {
    LatLngBounds.Builder builder = LatLngBounds.builder();
    if (centerPoint != null) {
        for (int i = 0; i < pointList.size(); i++) {
            LatLng p = pointList.get(i);
            LatLng p1 = new LatLng((centerPoint.latitude * 2) - p.latitude,
                    (centerPoint.longitude * 2) - p.longitude);
            builder.include(p);
            builder.include(p1);
        }
    }
    return builder.build();
}

有了合适范围约束对象后,我们的marker和当前位置小蓝点都可以展示在地图里,需要我们调整一下地图的显示

LatLngBounds bounds = getLatLngBounds(centerLatLng, pointList);
// 第二个参数为地图设置padding
aMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));

设置好padding,防止显示的marker等离地图范围边挨得太近。

2、info window被遮挡,显示不全的问题
在一番搜索之后,发现并没有合适的api可以使用,┭┮﹏┭┮
突然想到是不是可以添加一些不显示的点来重新让地图定位,用这些不可见的点来把我们要显示的内容给圈起来,圈定一个范围。

相对于定位的小蓝点,门店的点有四个相对的位置,如下图:


图1.png

图2.png

图3.png

图4.png

其中,图2和图3容易被遮挡,我们在这两个位置的上方和右方添加两个点就可以显示我们的需求

public void zoomToSpanWithCenter() {
    List<LatLng> pointList = new ArrayList<>();
    LatLng centerLatLng;
    LatLng helperLatLngVertical = null;
    LatLng helperLatLngHorizontal = null;

    // 判断店铺和当前位置哪个纬度更高,然后添加辅助点以更好地分配位置防止店铺info window显示不全
    if (storeLatLng.latitude > locationLatLng.latitude) {
        helperLatLngVertical = new LatLng(Math.max(storeLatLng.latitude, locationLatLng.latitude)
                + Math.abs(storeLatLng.latitude - locationLatLng.latitude), storeLatLng.longitude);
    }
    // 判断店铺和当前位置哪个经度更靠右侧,然后添加辅助点以更好地分配位置防止店铺info window显示不全
    if (storeLatLng.longitude > locationLatLng.longitude) {
        helperLatLngHorizontal = new LatLng(storeLatLng.latitude,
                Math.max(storeLatLng.longitude, locationLatLng.longitude)
                + Math.abs(storeLatLng.longitude - locationLatLng.longitude) / 10);
    }

    pointList.add(storeLatLng);
    pointList.add(locationLatLng);
    if (helperLatLngVertical != null) {
        pointList.add(helperLatLngVertical);
    }
    if (helperLatLngHorizontal != null) {
        pointList.add(helperLatLngHorizontal);
    }
    centerLatLng = new LatLng((locationLatLng.latitude + storeLatLng.latitude
            + (helperLatLngVertical != null ? helperLatLngVertical.latitude : 0)
            + (helperLatLngHorizontal != null ? helperLatLngHorizontal.latitude:0)) / pointList.size(),
            (locationLatLng.longitude + storeLatLng.longitude
                    + (helperLatLngVertical != null ? helperLatLngVertical.longitude : 0)
                    + (helperLatLngHorizontal != null ? helperLatLngHorizontal.longitude:0)) / pointList.size());

    LatLngBounds bounds = getLatLngBounds(centerLatLng, pointList);
    // 第二个参数为地图设置padding
    aMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
}

最终显示不会被遮挡,并且缩放显示也合乎要求,O(∩_∩)O

扫尾工作:

1、检查有没有泄露情况、该释放的资源有没有及时释放

@Override
protected void onDestroy() {
    super.onDestroy();
    mMapViewStoreDetail.onDestroy();
    if (mLocationClient != null) {
        mLocationClient.onDestroy();
    }
}

在Android Studio里打开Android Profiler查看打开、关闭activity情况下实例有没有及时回收释放。
2、有没有

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

推荐阅读更多精彩内容