上一篇文章我們初次認識了百度地圖,并且使用它寫了獲取地理位置的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.lxweimin.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
百度地圖開發文檔