美文网首页经验之谈
使用百度地图仿滴滴定位

使用百度地图仿滴滴定位

作者: MarkShaun | 来源:发表于2016-08-13 15:08 被阅读3192次

SDK版本:Android SDK v4.0.0
先上图看下效果:


最终效果图.png

嘿嘿,还不错吧,中间也算踩了不少坑,想了很多,在这里记录吧,也希望能够给大家带来点参考。如有不足,欢迎指正。

先说下需求:
1、显示自己的位置;
2、可以手动选择位置;

按照百度给的介绍,通过添加markerOptions的方法简单的实现了下(参照OverlayDemo),
效果如下:

demo1.png
感觉有以下的几点不足:
a、marker跟随地图拖拽移动,通过拖拽或者长按的方法选择位置不准确,体验不好;
b、添加的marker图层在定位图层(蓝点)的下面;
改进:
a、marker固定在中间,通过移动地图选择位置;
b、改变marker的层级;

尝试方法:
方法一:(不可取)
通过监听地图的状态,每次更改就把marker的位置重新设置下。起初只是在onMapStatusChangeFinish的时候设置下,但是marker还是会随地图移动,结束的时候会突然跳到中间。后来改为onMapStatusChange中设置,但是还是感觉不流畅。

mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {
    @Override
    public void onMapStatusChangeStart(MapStatus mapStatus) {}
    @Override
    public void onMapStatusChange(MapStatus mapStatus) {
        marker.setPosition(mapStatus.target);
    }
    @Override
    public void onMapStatusChangeFinish(MapStatus mapStatus) {}
});

另外,本以为可以通过中的zIndex设置marker的图层,然并卵,所以这种方法就不可用了。

final MarkerOptions markerOptions = new MarkerOptions()
        .position(mBaiduMap.getMapStatus().target)
        //.draggable(true)//可拖拽
        .icon(bitmap)
        .zIndex(12);

final Marker marker = (Marker) mBaiduMap.addOverlay(markerOptions);
//长按定位(改变marker的位置)
mBaiduMap.setOnMapLongClickListener(new BaiduMap.OnMapLongClickListener() {
    @Override
    public void onMapLongClick(LatLng latLng) {
        marker.setPosition(latLng);
        Toast.makeText(BaseMapDemo.this, "定位成功", Toast.LENGTH_SHORT).show();
    }
});

方法二:
既然要使marker的位置在MapView中间(初始和我的位置重叠),那么我们是否可以和获取我的位置 按钮一样,直接在布局文件中写死呢?这样岂不是不会卡顿,并且层级肯定是在定位层级的上面。事实证明这种方法是可以行的通的,但需要注意的一点是,我们需要处理markerOnClick事件,避免在该区域无法移动底部的地图,另外对于其位置也要进行下处理(我们要使其底部位于MapView的中间),在这里,我起初想法是增大MarginBottom。 后来我想到了另外一种方法,然后就没有对这个做具体的demo。下面我放一个朋友的处理方法(使用Vector处理图片,话说我还是第一次见(⊙﹏⊙)b),大家可以参考下:

demo2.png 布局文件.png img样式.png

方法三:
通过不断观察滴滴的样式,我觉得肯定有什么是我没有发现的,果然,当我在看文档的时候这么一段话引起了我的注意:

百度地图SDK为广大开发者提供的基础地图和上面的各种覆盖物元素,具有一定的层级压盖关系,具体如下(从下至上的顺序):
1、基础底图(包括底图、底图道路、卫星图、室内图等);
2、瓦片图层(TileOverlay);
3、地形图图层(GroundOverlay);
4、热力图图层(HeatMap);
5、实时路况图图层(BaiduMap.setTrafficEnabled(true););
6、百度城市热力图(BaiduMap.setBaiduHeatMapEnabled(true););
7、底图标注(指的是底图上面自带的那些POI元素);
8、几何图形图层(点、折线、弧线、圆、多边形);
9、标注图层(Marker),文字绘制图层(Text);
10、指南针图层(当地图发生旋转和视角变化时,默认出现在左上角的指南针);
11、定位图层(BaiduMap.setMyLocationEnabled(true););
12、弹出窗图层(InfoWindow);
13、自定义View(MapView.addView(View););

没错,就是自定义View,MapView.addView(View);,看到这个更加坚定了我的想法。通过AddView的方法。
关键是怎么使自定义的View添加到指定的位置呢,让我们一起来看下这个方法:

MapView.addView.png
说的很明白了,必须是一个MapViewParams,那这就好办了,我们接着看文档: class MapViewLayoutParams.png public static final class MapViewLayoutParams.Builder.png

接下来上代码:

Point point = new Point(mMapView.getWidth() / 2, mMapView.getHeight() /2);//这里指定的是屏幕的坐标
//align 默认垂直下对齐,这样我们就不用自己处理了
MapViewLayoutParams params = new MapViewLayoutParams.Builder()
        .layoutMode(MapViewLayoutParams.ELayoutMode.absoluteMode)
        .height(DensityUtils.dp2px(this, 36))
        .width(DensityUtils.dp2px(this, 16))
        .point(point)
        .build();

mMapView.addView(markLocation, params);
mMapView.refreshDrawableState();

OK,到这里基本上就完事儿了,剩下的就是一些细节的处理,例如为Marker添加AnimationInfoWindow

Animator animUp = ObjectAnimator.ofFloat(markLocation, "translationY", 0f, -30f);
animUp.setDuration(ANIMATION_DURATION);
Animator animDown = ObjectAnimator.ofFloat(markLocation, "translationY", - 30f, 0f);
animDown.setDuration(ANIMATION_DURATION);
final AnimatorSet animatorSet = new AnimatorSet();animatorSet.playSequentially(animUp, animDown);
animatorSet.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {    }
    @Override
    public void onAnimationEnd(Animator animation) {
        mInfoWindow = new InfoWindow(BitmapDescriptorFactory.fromView(infoWindow), mBaiduMap.getMapStatus().target, - (markLocation.getHeight() + 14), listener);//第三个参数调整infoWindow距离中心点的高度
        mBaiduMap.showInfoWindow(mInfoWindow);
    }
    @Override
    public void onAnimationCancel(Animator animation) {    }
    @Override
    public void onAnimationRepeat(Animator animation) {    }
});

//添加InfoWindow
final ImageView infoWindow= new ImageView(getApplicationContext());
infoWindow.setImageResource(R.drawable.icon_position_tips);
infoWindow.setMinimumHeight(DensityUtils.dp2px(this, 42));
infoWindow.setMinimumWidth(DensityUtils.dp2px(this, 91));
final InfoWindow.OnInfoWindowClickListener listener = new InfoWindow.OnInfoWindowClickListener() {
    public void onInfoWindowClick() {
        mBaiduMap.hideInfoWindow();
        Toast.makeText(BaseMapDemo.this,
                "定位成功" + mBaiduMap.getMapStatus().target.longitude +", " + mBaiduMap.getMapStatus().target.latitude,
                Toast.LENGTH_LONG).show();
    }
};

大功告成!在这里还要感谢群里的那位朋友Jin丶破的交流。
源码稍后会放到我的github上。
<strong>------------------------- 补充 -------------------------
使用小米手机发现无法定位,即onReceiveLocation没有执行,纠结了大半天,在此提醒大家,一定要添加

<service
    android:name="com.baidu.location.f"
    android:enabled="true"
    android:process=":remote" >
</service>

感谢:http://m.blog.csdn.net/article/details?id=50499795

补充----------------------------
Native method not found:
com.baidu.platform.comjni.engine.JNIEngine.initClass.

该问题是由于.so的没引入导致的。
为了调试方便,减少等待时间,编译时去掉了全部的so文件

buildTypes {
    debug {
        signingConfig signingConfigs.release
        // 需要测趣拍注释掉这里然后rebuild !!
        // 去掉全部的so文件!! 解决debug启动等太久(含lib so的apk有27MB)问题
        //ndk { abiFilters "armeabi" }
    }
    release {
        signingConfig signingConfigs.release
        //开启混淆
        minifyEnabled true
        zipAlignEnabled true
        // 移除无用的resource文件
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
    }
}

跳转:百度论坛

相关文章

网友评论

  • 8e4e7ad1f872:老铁。。。能发现GitHub的地址吗:heart: 比心心
  • 7b1f39f413fd:addView的时候,使用.layoutMode(MapViewLayoutParams.ELayoutMode.mapMode)设置了坐标点.position(latLng)。
    ```
    LatLng latLng = new LatLng(114.427607,30.478021);
    TextView textView = new TextView(getContext());
    textView.setText("dadash askj ");
    MapViewLayoutParams mlp = new MapViewLayoutParams.Builder()
    .layoutMode(MapViewLayoutParams.ELayoutMode.mapMode)
    .position(latLng)
    .width(ScreenUtils.getWidth(getContext())/2)
    .height(ScreenUtils.getWidth(getContext())/2)
    .build();
    mMapView.addView(textView, mlp);
    mMapView.refreshDrawableState();
    ```
    无效
    8d1bd23129ad:addView后,规划路线时删除了,但是再次定位时removeView有时就会无效。。。
    MarkShaun:@淡容非梦 这个坐标是不是不在你的屏幕范围内?
    7b1f39f413fd:麻烦看看为什么??
  • 175d8206dd26:想看源码
  • 175d8206dd26:请问 github源码地址可以告诉我吗?
  • 萧寒:mMapView.addView(markLocation, params);
    markLocation这个是不是自定义的透明圆圈
    MarkShaun:那个圆圈是百度自己带的,标示自己的位置的。自己就搞一个大头针就行了。

本文标题:使用百度地图仿滴滴定位

本文链接:https://www.haomeiwen.com/subject/ndezjttx.html