上一篇文章我们初次认识了百度地图,并且使用它写了获取地理位置的Demo,
这一篇文章,我们来实现地图的显示。
地图,是一个view,它只是一个界面,而真正的位置,是通过叠加图层来显示的,而这个图层的位置是通过我们位置监听器的经纬度来确定的
显示地图
修改上一篇文章的布局文件
[activity_main.xml]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.surine.onemap.MainActivity"
tools:showIn="@layout/app_bar_main">
<TextView
android:id="@+id/first"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Hello World!"
/>
<com.baidu.mapapi.map.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
/>
</LinearLayout>
增加了百度地图的一个view,
然后我们在java里添加代码
//首先我们的initmap肯定是在onCreate里调用,findview
private void initMap() {
//sdk的初始化
SDKInitializer.initialize(getApplicationContext());
mmap = (MapView) findViewById(R.id.map);
}
//然后这个管理地图的生命周期
//onResume状态
@Override
protected void onResume() {
super.onResume();
mmap.onResume();
}
//pause状态
@Override
protected void onPause() {
super.onPause();
mmap.onPause();
}
大概这个样子,我们可以运行了。
一番编译之后,终于start activity……
然后,结果是一个fc。
好吧,保持冷静。fc我见多了,冷静解决好了。
我们先看一下日志
这里是一个反射错误,出现这种错误大概就几种情况,布局嵌套,没有找到view等,由于我也是第一次使用baidumap,我肯定不知道它里面的view使用规则,所以我就上网查了一下,大多数人说是初始化不对,也就是说初始化未完成,我们找不到view。
那么我猜测这个初始化应该是建立在setContentView()之前的,我直接新建了自定义Application,在APP打开的时候就进行初始化。
[MyApplication.java]
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 在使用 SDK 各组间之前初始化 context 信息,传入 ApplicationContext
SDKInitializer.initialize(this);
}
}
那么相应的我们的清单文件内容需要修改,也就是给<Application>标签添加name
android:name=".MyApplication"
有网友说需要带上包名,经过测试不带也可以,如果你需要的话,可以在前面加上包名。
android:name="com.xxx.xxx.MyApplication"
这个样子之后我们可以删掉,我们刚才在MainActivity里的初始化代码。(不删也可以其实)
最后我们来运行一下。
可以看到我们已经得到了地图界面,并且可以滑动操作(注意联网……不联网说啥呢,哈哈)
显示自己的位置
可以看到当前我们的地图显示的北京市区,我们下面要实现将位置自动移到我当前的位置,我们先来看一下代码
//首先我们创建一个BaiduMap对象,然后用他来获取map
//注意这一行代码写的位置,应该是findview mapview之后,防止出现空指针
baidumap = mmap.getMap();
然后我们新建一个方法叫moveTo();
private void moveTo(BDLocation bdLocation) {
if(isFirstLocate){
//传入经纬度
LatLng ll = new LatLng(bdLocation.getLatitude(),bdLocation.getLongitude());
//建立更新工厂
MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
//执行更新
baidumap.animateMapStatus(update);
//建立缩放更新
update = MapStatusUpdateFactory.zoomTo(16f);
//执行更新
baidumap.animateMapStatus(update);
isFirstLocate = false;
}
}
然后在什么时候调用这个方法?答案很显然,就是在我们上一篇文章写的监听器里,因为地理位置是从那里获取来的,我们传入bdlocation这个参数,可以用它来获取相关信息。
那么我们现在梳理一下代码。
首先我们获取了baidumap这么个对象,作用是什么呢?
BaiduMap类是百度地图SDK里提供的一个类,通过getMap这个方法获取map实例,然后我们就可以对地图进行各种各样的操作了。
可以看到我们的MoveTo代码,首先是一个if判断,根据我变量名的命名大家也可以知道,他就是判断有没有移动过,是不是第一次定位(当然默认值给true),如果是true就执行操作,否则结束。
条件语句里面是一些对地图的操作,
Latlng这个对象主要存放经纬度,接受两个参数,经纬度,接下来我们就创建一个update工厂管理,传入Latlng,最后让地图执行update,逻辑还是很清晰的,baidu地图 sdk封装的已经很简单了,同样zoomto是一个控制缩放级别的方法(范围为浮点3f-19f)
更新结束之后我们就可以给 isfirstloca复制false,当然可能执行速度太快,我们根本看不到动画,这个时候,我们给第二次更新加个2s延时就可以,你看看你能不能实现呢?
我们看一下结果
一不小心暴露了自己的位置,这是第一次定位结果,具体操作中可以看到更新动画。
地图标注
我们经常看到地图定位标注,比如说小黄车ofo的小黄车都是通过标注显示到地图上的。
标注这个功能叫做marker
具体代码如下:
private void moveTo(BDLocation bdLocation) {
.... (省略的代码)
//检查是否有过标注,如果有,清除
if(marker!=null) {
marker.remove();
}
//创建latlng对象管理位置
LatLng latLng = baidumap.getMapStatus().target;
//准备 marker 的图片
BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_marka);
//准备 marker option 添加 marker 使用
markerOptions = new MarkerOptions().icon(bitmap).position(latLng);
//获取添加的 marker 这样便于后续的操作
marker = (Marker) baidumap.addOverlay(markerOptions);
//对 marker 添加点击相应事件
baidumap.setOnMarkerClickListener(new OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker arg0) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "Marker被点击了!", Toast.LENGTH_SHORT).show();
return false;
}
});
}
很简单的代码,但是这里面有几个问题,第一个是这个标注不是定位,所以位置不会一成不变,可以随着移动而显示在不同位置,第二个是因为我们的位置是实时更新的,所以代码会调用很多次,标注也会打好多次,所以我们加了判断,在标注之前先去掉以前标注的。那么下面是演示结果。
可以看到我们的标注已经显示在地图上了。
这里还是给出zhh_happig文章里写的一些常用方法
markerOptions.position(latLng);//marker坐标位置
markerOptions.icon(icon);//marker图标,可以自定义
markerOptions.draggable(false);//是否可拖拽,默认不可拖拽
markerOptions.anchor(0.5f, 1.0f);//设置 marker覆盖物与位置点的位置关系,默认(0.5f, 1.0f)水平居中,垂直下对齐
markerOptions.alpha(0.8f);//marker图标透明度,0~1.0,默认为1.0
markerOptions.animateType(MarkerAnimateType.drop);//marker出现的方式,从天上掉下
markerOptions.flat(false);//marker突变是否平贴地面
markerOptions.zIndex(1);//index
//Marker动画效果
markerOptions.icons(bitmapList);//如果需要显示动画,可以设置多张图片轮番显示
markerOptions.period(10);//每个10ms显示bitmapList里面的图片
[作者:zhh_happig
链接:http://www.jianshu.com/p/fdd1ba783495
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。]
这个仅仅是简单的探索一下,更多的玩法在以后的文章可能会有
定位图层
定位图层指的是,我们在地图上点击定位按钮给我们显示的小圆点,具体的代码如下
//在初始化方法里写开启
private void initMap() {
···省略的代码
// 开启定位图层
baidumap.setMyLocationEnabled(true);
}
private void moveTo(BDLocation bdLocation) {
if(····){
···省略的代码
//创建LocationData对象
MyLocationData locData = new MyLocationData.Builder()
//设置精度半径,可以设置0,此时就不会显示外圈的圆
.accuracy(bdLocation.getRadius())
//设置方向,不过一定要 设置option.setNeedDeviceDirect(true);
//通过这个方法获取的方式不是实时更新的,所以一般选择用手机
//方向传感器来判断
.direction(bdLocation.getDirection()).latitude(bdLocation.getLatitude())
.longitude(bdLocation.getLongitude()).build();
//设置显示
baidumap.setMyLocationData(locData);
}
}
把代码写在if判断里面更符合实际
如果离开该活动记得取消定位图层释放资源(设置false)
可以看到我们的定位图层还是在moveTo的代码里添加了一些东西,根据我们的经纬度,我们可以设置这个小圆点
演示如图
可以看到我们的定位图层是一个小蓝点。
总结
本篇文章主要实现了地图的显示,而不再是简单的数据,下一篇文章我们将继续探索百度地图的其他功能。
参考
《第一行代码 第二版》
简书:zhh_happig
百度地图开发文档