今天咱們來談下百度地圖的定位功能。在此以前我已經將百度地圖的基本地圖大概說了下,事實上百度地圖的基本功能還有很是多的內容。html
感興趣的可以到百度地圖的開發人員的官網看看。今天就開始來說下百度地圖中的定位功能。java
今天所講的百度地圖所涉及的內容主要有:基本定位的實現。本身定義定位圖標。結合方向傳感器定位,選擇定位中的幾種模式(羅盤模式,普通模式,尾隨模式)。android
1、基本定位的實現:git
所謂定位無非就是獲取到一個地方所處地球的經緯度座標。這個反映到地圖中就是一個點。但是怎麼去實現一個定位呢??api
首先,需要去建立一個定位client對象。而後給這個定位client對象設置監聽器。並且每隔1s中就去請求一次定位。這就是所謂實時監聽定位信息的變化。也就是位置發生變化,那麼所處的經緯度就變化了,經過經緯度值可以獲得一個經緯度對象,經過這個經緯度對象(實際上就是相應一個點),反映在地圖上點的位置發生了變化。app
這樣一來定位也是一個高耗的工做,因此咱們也需要管理定位的生命週期。當咱們開啓應用就去開啓定位,關閉應用就得關閉定位的請求。ide
記住一點就是使用定位功能還得在AndroidManifest.xml配置一個Service。佈局
註冊service:post
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote" > <intent-filter> <action android:name="com.baidu.location.service_v2.2" > </action> </intent-filter> </service>
將定位的生命週期和Activity的生命週期進行綁定:動畫
@Override protected void onStart() { myLocationClient.start();//將定位與Activity生命週期進行綁定,開啓定位 super.onStart(); } @Override protected void onStop() { myLocationClient.stop();//將定位與Activity生命週期進行綁定,關閉定位 super.onStop(); }
初始化定位功能:
<pre class="java" name="code">/** * @author Mikyou * 初始化定位功能 * */ private void initMapLocation() { myLocationClient=new LocationClient(this);//建立一個定位client對象 myListener=new MyLocationListener();//建立一個定位事件監聽對象 myLocationClient.registerLocationListener(myListener);//並給該定位client對象註冊監聽事件 //對LocaitonClient進行一些必要的設置 LocationClientOption option=new LocationClientOption(); option.setCoorType("bd09ll");//設置座標的類型 option.setIsNeedAddress(true);//返回當前的位置信息。假設不設置爲true,默認就爲false,就沒法得到位置的信息 option.setOpenGps(true);//打開GPS option.setScanSpan(1000);//表示1s中進行一次定位請求 myLocationClient.setLocOption(option); useLocationOrientationListener();//調用方向傳感器 } /** * @author Mikyou * 定位結合方向傳感器,從而可以實時監測到X軸座標的變化。從而就可以檢測到 * 定位圖標方向變化,僅僅需要將這個動態變化的X軸的座標更新myCurrentX值。 * 最後在MyLocationData data.driection(myCurrentX); * */ private void useLocationOrientationListener() { myOrientationListener=new MyOrientationListener(MainActivity.this); myOrientationListener.setMyOrientationListener(new onOrientationListener() { @Override public void onOrientationChanged(float x) {//監聽方向的改變。方向改變時。需要獲得地圖上方向圖標的位置 myCurrentX=x; System.out.println("方向:x---->"+x); } }); }
/** * @author zhongqihong * 獲取位置信息的client對象的監聽器類MyLocationListener * */ class MyLocationListener implements BDLocationListener{ @Override public void onReceiveLocation(BDLocation location) { //獲得一個MyLocationData對象,需要將BDLocation對象轉換成MyLocationData對象 MyLocationData data=new MyLocationData.Builder() .accuracy(location.getRadius())//精度半徑 .direction(myCurrentX)//myCurrentX就是經過方向傳感器監聽獲得的值來設置定位的方向
.latitude(location.getLatitude())//經度 .longitude(location.getLongitude())//緯度 .build(); myBaiduMap.setMyLocationData(data); //配置本身定義的定位圖標,需要在緊接着setMyLocationData後面設置 //調用本身定義定位圖標 changeLocationIcon(); latitude=location.getLatitude();//獲得當前的經度 longtitude=location.getLongitude();//獲得當前的緯度 //toast("經度:"+latitude+" 緯度:"+longtitude); if (isFirstIn) {//表示用戶第一次打開,就定位到用戶當前位置。即此時僅僅要將地圖的中心點設置爲用戶此時的位置就能夠 getMyLatestLocation(latitude,longtitude);//得到最新定位的位置,並且地圖的中心點設置爲個人位置 isFirstIn=false;//表示第一次纔會去定位到中心點 locationTextString=""+location.getAddrStr();//這裏獲得地址必須需要在設置LocationOption的時候需要設置isNeedAddress爲true; toast(locationTextString); locationText.setText(locationTextString); } }
2、改動本身定義圖標
/** * @author zhongqihong * 本身定義定位圖標 * */ private void changeLocationIcon() { myBitmapLocation=BitmapDescriptorFactory .fromResource(R.drawable.ic_launcher);//引入本身的圖標 if (isFirstIn) {//表示第一次定位顯示普通模式 MyLocationConfiguration config=new MyLocationConfiguration(LocationMode.NORMAL, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config); } }
獲取最新的位置
/** * @author zhongqihong * 得到最新定位的位置,並且地圖的中心點設置爲個人位置 * */ private void getMyLatestLocation(double lat,double lng) { LatLng latLng=new LatLng(lat, lng);//建立一個經緯度對象。需要傳入當前的經度和緯度兩個整型值參數 MapStatusUpdate msu=MapStatusUpdateFactory.newLatLng(latLng);//建立一個地圖最新更新的狀態對象。需要傳入一個最新經緯度對象 myBaiduMap.animateMapStatus(msu);//表示使用動畫的效果傳入,經過傳入一個地圖更新狀態對象。而後利用百度地圖對象來展示和還原那個地圖更新狀態。即此時的地圖顯示就爲你現在的位置 }
3、結合方向傳感器來控制定位圖標方向。使得整個圖標會隨着手機方向的轉動而轉動。
但是假設去實時推斷手機在轉動呢?以及手機轉動的方向和角度是多少呢?這時候就需要手機中內置的方向傳感器,該方向傳感器可以監測到手機在X,Y,Z軸方向上偏移量。但是咱們通常都是在一個平面內轉動,也就是一個用於在東南西北方向轉動,因此僅僅需要用方向傳感器去實時監測X軸方向的偏移量就能夠,並用一個變量記錄一下當前偏移值,噹噹前偏移值和上一次偏移值的絕對值超過一個臨界值,就可以斷定方向發生改變,並把該方向的偏移量myCurrent設置給MyLocationData對象就能夠。但是方向傳感器的開啓和關閉,還需要和定位服務生命保持一致。假設定位都關閉了,那就沒有必要去開啓方向傳感器了,既然定位生命週期和Activity綁定在一塊兒,因此也僅僅需要把方向傳感器的生命週期和Activity生命週期綁定在一塊兒就能夠。
protected void onDestroy() { super.onDestroy(); //在Activity運行onDestory時運行mapView(地圖)生命週期管理 myMapView.onDestroy(); } @Override protected void onStart() {//當Activity調用onStart方法。開啓定位以及開啓方向傳感器,即將定位的服務、方向傳感器和Activity生命週期綁定在一塊兒 myBaiduMap.setMyLocationEnabled(true);//開啓贊成定位 if (!myLocationClient.isStarted()) { myLocationClient.start();//開啓定位 } //開啓方向傳感器 myOrientationListener.start(); super.onStart(); } @Override protected void onStop() {//當Activity調用onStop方法,關閉定位以及關閉方向傳感器 myBaiduMap.setMyLocationEnabled(false); myLocationClient.stop();//關閉定位 myOrientationListener.stop();//關閉方向傳感器 super.onStop(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); //在Activity運行onResume是運行MapView(地圖)生命週期管理 myMapView.onResume(); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); myMapView.onPause(); }
方向傳感器監聽器
package com.mikyou.sensor; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; public class MyOrientationListener implements SensorEventListener{ private SensorManager mySensorManager; private Sensor mySensor; private Context myContext; private float lastX; private onOrientationListener myOrientationListener; public void start(){//開啓方向傳感器 //先經過系統服務來獲得傳感器管理對象mySensorManager mySensorManager=(SensorManager) myContext.getSystemService(Context.SENSOR_SERVICE); if (mySensorManager!=null) {//假設傳感器管理對象不爲空,則可以經過傳感器管理對象來得到方向傳感器對象 //得到方向傳感器對象 mySensor=mySensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); } if (mySensor!=null) {//假設方向傳感器不爲空,則給該方向傳感器註冊監聽事件 mySensorManager.registerListener(this, mySensor, SensorManager.SENSOR_DELAY_UI); } } public void stop(){//解除註冊方向傳感器監聽事件 mySensorManager.unregisterListener(this); } public MyOrientationListener(Context myContext) {//方向傳感器的一個構造器 super(); this.myContext = myContext; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // TODO Auto-generated method stub } //監聽方向發生變化 @Override public void onSensorChanged(SensorEvent event) {//精度發生改變的時候 if (event.sensor.getType()==Sensor.TYPE_ORIENTATION) {//假設是方向傳感器 float x=event.values[SensorManager.DATA_X];//得到傳感器的X軸的座標,可以返回3個值,即X軸的座標,Y軸座標,Z軸座標,咱們僅僅需要X軸座標 if (Math.abs(x-lastX)>1.0) {//對照本次的X座標的變化比上一次的變化差大於1.0就說明方向發生改變 if (myOrientationListener!=null) {//說明主界面已經註冊了事件,即不爲空,而後產生一個回調將實時變化X軸的座標傳入 //經過一個回調方法。通知主界面去更新UI myOrientationListener.onOrientationChanged(lastX);//就需要把上一次的X軸座標傳入,在MainActivity中的回調方法中去獲取就能夠 } } lastX=x; } } public void setMyOrientationListener(onOrientationListener myOrientationListener) { this.myOrientationListener = myOrientationListener; } //寫一個接口實現方向改變的監聽產生的回調 public interface onOrientationListener{ void onOrientationChanged(float x);//回調的方法 } }
4、選擇定位中的幾種模式(羅盤模式。普通模式,尾隨模式):
/** * @author mikyou * 選擇定位的模式 * */ private void selectLocation() { AlertDialog.Builder builder2=new AlertDialog.Builder(this); builder2.setIcon(R.drawable.track_collect_running) .setTitle("請選擇定位的模式") .setItems(LocationModeString, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String mode=LocationModeString[which]; if (mode.equals("羅盤模式")) { MyLocationConfiguration config=new MyLocationConfiguration(LocationMode.COMPASS, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config); }else if (mode.equals("尾隨模式")) { MyLocationConfiguration config=new MyLocationConfiguration(LocationMode.FOLLOWING, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config); }else if (mode.equals("普通模式")) { MyLocationConfiguration config=new MyLocationConfiguration(LocationMode.NORMAL, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config); }else if (mode.equals("3D鳥瞰模式(已關閉)")||mode.equals("3D鳥瞰模式(已打開)")) { if (mode.equals("3D鳥瞰模式(已打開)")) { UiSettings mUiSettings = myBaiduMap.getUiSettings(); mUiSettings.setCompassEnabled(true); LocationModeString[which]="3D鳥瞰模式(已關閉)"; toast("3D模式已關閉"); }else{ MyLocationConfiguration config=new MyLocationConfiguration(LocationMode.COMPASS, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config); MyLocationConfiguration config2=new MyLocationConfiguration(LocationMode.NORMAL, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config2); LocationModeString[which]="3D鳥瞰模式(已打開)"; toast("3D模式已打開"); } } } }).show(); }
最後附上整個Activity源代碼:
package com.mikyou.maptest; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.graphics.Color; import android.graphics.Point; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import android.widget.ZoomControls; import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.baidu.mapapi.SDKInitializer; import com.baidu.mapapi.map.BaiduMap; import com.baidu.mapapi.map.BaiduMap.OnMapClickListener; import com.baidu.mapapi.map.BaiduMap.OnMarkerClickListener; import com.baidu.mapapi.map.BitmapDescriptor; import com.baidu.mapapi.map.BitmapDescriptorFactory; import com.baidu.mapapi.map.InfoWindow; import com.baidu.mapapi.map.MapPoi; import com.baidu.mapapi.map.MapStatusUpdate; import com.baidu.mapapi.map.MapStatusUpdateFactory; import com.baidu.mapapi.map.MapView; import com.baidu.mapapi.map.Marker; import com.baidu.mapapi.map.MarkerOptions; import com.baidu.mapapi.map.MyLocationConfiguration; import com.baidu.mapapi.map.UiSettings; import com.baidu.mapapi.map.MyLocationConfiguration.LocationMode; import com.baidu.mapapi.map.MyLocationData; import com.baidu.mapapi.map.OverlayOptions; import com.baidu.mapapi.model.LatLng; import com.mikyou.beans.MarkInfo; import com.mikyou.sensor.MyOrientationListener; import com.mikyou.sensor.MyOrientationListener.onOrientationListener; public class MainActivity extends Activity implements OnClickListener,OnMapClickListener,OnMarkerClickListener{ private MapView mapView=null; private BaiduMap myBaiduMap=null; //改動默認View相關 private View defaultBaiduMapScaleButton,defaultBaiduMapLogo,defaultBaiduMapScaleUnit; //基本地圖類型,實時交通,及覆蓋物相關 private ImageView mapRoad; private ImageView mapType; private String[] types={"普通地圖","衛星地圖","熱力地圖(已關閉)"}; private float current;//放大或縮小的比例係數 private ImageView expandMap;//放大地圖控件 private ImageView narrowMap;//縮小地圖 private ImageView addMarks;//加入覆蓋物控件 private BitmapDescriptor myMarks; private List<MarkInfo> markInfoList; private LinearLayout markLayout; //定位相關 private LocationClient myLocationClient;//專門用於監聽位置的client對象 private MyLocationListener myListener;//定位監聽器對象 private double latitude,longtitude;//經緯度 private BitmapDescriptor myBitmapLocation;//定位的本身定義圖標 private boolean isFirstIn=true;//設置一個標記,查看是不是第一次 private String locationTextString;//定義的位置的信息 private TextView locationText;//顯示定位信息的TextView控件 private MyOrientationListener myOrientationListener; private float myCurrentX; private ImageView selectLocationMode; private String[] LocationModeString={"羅盤模式","普通模式","尾隨模式","3D鳥瞰模式(已關閉)"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); SDKInitializer.initialize(getApplicationContext()); setContentView(R.layout.activity_main); mapView=(MapView) findViewById(R.id.map_view_test); initMapView(); changeDefaultBaiduMapView(); initMapLocation(); } /** * @author Mikyou * 初始化定位功能 * */ private void initMapLocation() { myLocationClient=new LocationClient(this);//建立一個定位client對象 myListener=new MyLocationListener();//建立一個定位事件監聽對象 myLocationClient.registerLocationListener(myListener);//並給該定位client對象註冊監聽事件 //對LocaitonClient進行一些必要的設置 LocationClientOption option=new LocationClientOption(); option.setCoorType("bd09ll");//設置座標的類型 option.setIsNeedAddress(true);//返回當前的位置信息。假設不設置爲true。默認就爲false,就沒法得到位置的信息 option.setOpenGps(true);//打開GPS option.setScanSpan(1000);//表示1s中進行一次定位請求 myLocationClient.setLocOption(option); useLocationOrientationListener();//調用方向傳感器 } /** * @author Mikyou * 定位結合方向傳感器,從而可以實時監測到X軸座標的變化,從而就可以檢測到 * 定位圖標方向變化,僅僅需要將這個動態變化的X軸的座標更新myCurrentX值。 * 最後在MyLocationData data.driection(myCurrentX); * */ private void useLocationOrientationListener() { myOrientationListener=new MyOrientationListener(MainActivity.this); myOrientationListener.setMyOrientationListener(new onOrientationListener() { @Override public void onOrientationChanged(float x) {//監聽方向的改變,方向改變時,需要獲得地圖上方向圖標的位置 myCurrentX=x; System.out.println("方向:x---->"+x); } }); } /** * @author zhongqihong * 獲取位置信息的client對象的監聽器類MyLocationListener * */ class MyLocationListener implements BDLocationListener{ @Override public void onReceiveLocation(BDLocation location) { //獲得一個MyLocationData對象,需要將BDLocation對象轉換成MyLocationData對象 MyLocationData data=new MyLocationData.Builder() .accuracy(location.getRadius())//精度半徑 .direction(myCurrentX)//方向 .latitude(location.getLatitude())//經度 .longitude(location.getLongitude())//緯度 .build(); myBaiduMap.setMyLocationData(data); //配置本身定義的定位圖標,需要在緊接着setMyLocationData後面設置 //調用本身定義定位圖標 changeLocationIcon(); latitude=location.getLatitude();//獲得當前的經度 longtitude=location.getLongitude();//獲得當前的緯度 //toast("經度:"+latitude+" 緯度:"+longtitude); if (isFirstIn) {//表示用戶第一次打開。就定位到用戶當前位置。即此時僅僅要將地圖的中心點設置爲用戶此時的位置就能夠 getMyLatestLocation(latitude,longtitude);//得到最新定位的位置,並且地圖的中心點設置爲個人位置 isFirstIn=false;//表示第一次纔會去定位到中心點 locationTextString=""+location.getAddrStr();//這裏獲得地址必須需要在設置LocationOption的時候需要設置isNeedAddress爲true; toast(locationTextString); locationText.setText(locationTextString); } } } /** * @author zhongqihong * 得到最新定位的位置,並且地圖的中心點設置爲個人位置 * */ private void getMyLatestLocation(double lat,double lng) { LatLng latLng=new LatLng(lat, lng);//建立一個經緯度對象,需要傳入當前的經度和緯度兩個整型值參數 MapStatusUpdate msu=MapStatusUpdateFactory.newLatLng(latLng);//建立一個地圖最新更新的狀態對象。需要傳入一個最新經緯度對象 myBaiduMap.animateMapStatus(msu);//表示使用動畫的效果傳入。經過傳入一個地圖更新狀態對象,而後利用百度地圖對象來展示和還原那個地圖更新狀態,即此時的地圖顯示就爲你現在的位置 } /** * @author zhongqihong * 本身定義定位圖標 * */ private void changeLocationIcon() { myBitmapLocation=BitmapDescriptorFactory .fromResource(R.drawable.ic_launcher);//引入本身的圖標 if (isFirstIn) {//表示第一次定位顯示普通模式 MyLocationConfiguration config=new MyLocationConfiguration(LocationMode.NORMAL, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config); } } /** * @author zhongqihong * 初始化地圖的View * */ private void initMapView() { registerAllIds(); registerAllEvents(); } private void registerAllIds() { mapRoad=(ImageView) findViewById(R.id.road_condition); mapType=(ImageView) findViewById(R.id.map_type); expandMap=(ImageView) findViewById(R.id.add_scale); narrowMap=(ImageView) findViewById(R.id.low_scale); addMarks=(ImageView) findViewById(R.id.map_marker); markLayout=(LinearLayout) findViewById(R.id.mark_layout); locationText=(TextView) findViewById(R.id.mylocation_text); selectLocationMode=(ImageView) findViewById(R.id.map_location); } private void registerAllEvents() { mapRoad.setOnClickListener(this); mapType.setOnClickListener(this); expandMap.setOnClickListener(this); narrowMap.setOnClickListener(this); addMarks.setOnClickListener(this); selectLocationMode.setOnClickListener(this); } /** * @author zhongqihong * 除去百度地圖上的默認控件 * */ private void changeDefaultBaiduMapView() { changeInitialzeScaleView();//改變默認百度地圖初始載入的地圖比例 //設置隱藏縮放和擴大的百度地圖的默認的比例button for (int i = 0; i < mapView.getChildCount(); i++) {//遍歷百度地圖中的所有子View,找到這個擴大和縮放的button控件View。而後設置隱藏View就能夠 View child=mapView.getChildAt(i); if (child instanceof ZoomControls) { defaultBaiduMapScaleButton=child;//該defaultBaiduMapScaleButton子View是指百度地圖默認產生的放大和縮小的button。獲得這個View break; } } defaultBaiduMapScaleButton.setVisibility(View.GONE);//而後將該View的Visiblity設爲不存在和不可見,即隱藏 defaultBaiduMapLogo =mapView.getChildAt(1);//該View是指百度地圖中默認的百度地圖的Logo,獲得這個View defaultBaiduMapLogo.setPadding(300, -10, 100, 100);//設置該默認Logo View的位置,因爲這個該View的位置會影響如下的刻度尺單位View顯示的位置 mapView.removeViewAt(1);//最後移除默認百度地圖的logo View defaultBaiduMapScaleUnit=mapView.getChildAt(2);//獲得百度地圖的默認單位刻度的View defaultBaiduMapScaleUnit.setPadding(100, 0, 115,200);//最後設置調整百度地圖的默認單位刻度View的位置 } /** * @author zhongqihong * 改變默認初始化的地圖的比例 * */ private void changeInitialzeScaleView() { myBaiduMap=mapView.getMap();//改變百度地圖的放大比例,讓首次載入地圖就開始擴大到500米的距離,得到百度地圖對象 MapStatusUpdate factory=MapStatusUpdateFactory.zoomTo(15.0f); myBaiduMap.animateMapStatus(factory); } /** * @author zhongqihong * 管理地圖的生命週期 * */ protected void onDestroy() { super.onDestroy(); //在Activity運行onDestory時運行mapView(地圖)生命週期管理 mapView.onDestroy(); } @Override protected void onStart() {//當Activity調用onStart方法,開啓定位以及開啓方向傳感器。即將定位的服務、方向傳感器和Activity生命週期綁定在一塊兒 myBaiduMap.setMyLocationEnabled(true);//開啓贊成定位 if (!myLocationClient.isStarted()) { myLocationClient.start();//開啓定位 } //開啓方向傳感器 myOrientationListener.start(); super.onStart(); } @Override protected void onStop() {//當Activity調用onStop方法。關閉定位以及關閉方向傳感器 myBaiduMap.setMyLocationEnabled(false); myLocationClient.stop();//關閉定位 myOrientationListener.stop();//關閉方向傳感器 super.onStop(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); //在Activity運行onResume是運行MapView(地圖)生命週期管理 mapView.onResume(); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); mapView.onPause(); } //點擊事件相關 @Override public void onClick(View v) { switch (v.getId()) { case R.id.road_condition://是否打開實時交通 switchRoadCondition(); break; case R.id.map_type://選擇地圖的類型 selectMapType(); break; case R.id.add_scale://放大地圖比例 expandMapScale(); break; case R.id.low_scale://縮小地圖比例 narrowMapScale(); break; case R.id.map_marker://加入覆蓋物 addMapMarks(); break; case R.id.my_location://定位功能,需要用到LocationClient進行定位 //BDLocationListener getMyLatestLocation(latitude,longtitude); break; case R.id.map_location://選擇定位模式 selectLocation(); break; default: break; } } /** * @author mikyou * 選擇定位的模式 * */ private void selectLocation() { AlertDialog.Builder builder2=new AlertDialog.Builder(this); builder2.setIcon(R.drawable.track_collect_running) .setTitle("請選擇定位的模式") .setItems(LocationModeString, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String mode=LocationModeString[which]; if (mode.equals("羅盤模式")) { MyLocationConfiguration config=new MyLocationConfiguration(LocationMode.COMPASS, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config); }else if (mode.equals("尾隨模式")) { MyLocationConfiguration config=new MyLocationConfiguration(LocationMode.FOLLOWING, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config); }else if (mode.equals("普通模式")) { MyLocationConfiguration config=new MyLocationConfiguration(LocationMode.NORMAL, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config); }else if (mode.equals("3D鳥瞰模式(已關閉)")||mode.equals("3D鳥瞰模式(已打開)")) { if (mode.equals("3D鳥瞰模式(已打開)")) { UiSettings mUiSettings = myBaiduMap.getUiSettings(); mUiSettings.setCompassEnabled(true); LocationModeString[which]="3D鳥瞰模式(已關閉)"; toast("3D模式已關閉"); }else{ MyLocationConfiguration config=new MyLocationConfiguration(LocationMode.COMPASS, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config); MyLocationConfiguration config2=new MyLocationConfiguration(LocationMode.NORMAL, true, myBitmapLocation); myBaiduMap.setMyLocationConfigeration(config2); LocationModeString[which]="3D鳥瞰模式(已打開)"; toast("3D模式已打開"); } } } }).show(); } /** * @author Mikyou * 加入覆蓋物 * */ private void addMapMarks() { initMarksData(); myBaiduMap.clear();//先清除一下圖層 LatLng latLng=null; Marker marker=null; OverlayOptions options; myMarks=BitmapDescriptorFactory.fromResource(R.drawable.mark);//引入本身定義的覆蓋物圖標。將其轉化成一個BitmapDescriptor對象 //遍歷MarkInfo的List一個MarkInfo就是一個Mark for (int i = 0; i < markInfoList.size(); i++) { //經緯度對象 latLng=new LatLng(markInfoList.get(i).getLatitude(), markInfoList.get(i).getLongitude());//需要建立一個經緯對象。經過該對象就可以定位處處於地圖上的某個詳細點 //圖標 options=new MarkerOptions().position(latLng).icon(myMarks).zIndex(6); marker=(Marker) myBaiduMap.addOverlay(options);//將覆蓋物加入到地圖上 Bundle bundle=new Bundle();//建立一個Bundle對象將每個mark詳細信息傳過去,當點擊該覆蓋物圖標的時候就會顯示該覆蓋物的詳細信息 bundle.putSerializable("mark", markInfoList.get(i)); marker.setExtraInfo(bundle); } MapStatusUpdate msu=MapStatusUpdateFactory.newLatLng(latLng);//經過這個經緯度對象,地圖就可以定位到該點 myBaiduMap.animateMapStatus(msu); } /** * @author mikyou * 初始化覆蓋物信息數據 * */ private void initMarksData() { markInfoList=new ArrayList<MarkInfo>(); markInfoList.add(new MarkInfo(32.079254, 118.787623, R.drawable.pic1, "英倫貴族小旅館", "距離209米", 1888)); markInfoList.add(new MarkInfo(32.064355, 118.787624, R.drawable.pic2, "沙井國際高級會所", "距離459米", 388)); markInfoList.add(new MarkInfo(28.7487420000, 115.8748860000, R.drawable.pic4, "華東交通大學南區", "距離5米", 888)); markInfoList.add(new MarkInfo(28.7534890000, 115.8767960000, R.drawable.pic3, "華東交通大學北區", "距離10米", 188)); myBaiduMap.setOnMarkerClickListener(this); myBaiduMap.setOnMapClickListener(this); } /** * @author zhongqihong * 放大地圖的比例 * */ private void narrowMapScale() { current-=0.5f; MapStatusUpdate msu=MapStatusUpdateFactory.zoomTo(15.0f+current); myBaiduMap.animateMapStatus(msu); } /** *@author zhongqihong *縮小地圖的比例 * */ private void expandMapScale() { current+=0.5f; MapStatusUpdate msu2=MapStatusUpdateFactory.zoomTo(15.0f+current); myBaiduMap.animateMapStatus(msu2); } /** * @author mikyou * 選擇地圖的類型 * */ private void selectMapType() { AlertDialog.Builder builder=new AlertDialog.Builder(MainActivity.this); builder.setIcon(R.drawable.icon) .setTitle("請選擇地圖的類型") .setItems(types, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String select=types[which]; if (select.equals("普通地圖")) { myBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL); }else if (select.equals("衛星地圖")) { myBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE); }else if (select.equals("熱力地圖(已關閉)")||select.equals("熱力地圖(已打開)")) { if(myBaiduMap.isBaiduHeatMapEnabled()) { myBaiduMap.setBaiduHeatMapEnabled(false); Toast.makeText(MainActivity.this, "熱力地圖已關閉", 0).show(); types[which]="熱力地圖(已關閉)"; }else { myBaiduMap.setBaiduHeatMapEnabled(true); Toast.makeText(MainActivity.this, "熱力地圖已打開", 0).show(); types[which]="熱力地圖(已打開)"; } } } }).show(); } /** * @author mikyou * 是否打開實時交通 * */ private void switchRoadCondition() { if (myBaiduMap.isTrafficEnabled()) {//假設是開着的狀態,當點擊後,就會出關閉狀態 myBaiduMap.setTrafficEnabled(false); mapRoad.setImageResource(R.drawable.main_icon_roadcondition_off); }else{//假設是的關閉的狀態。當點擊後,就會處於開啓的狀態 myBaiduMap.setTrafficEnabled(true); mapRoad.setImageResource(R.drawable.main_icon_roadcondition_on); } } /** * @author mikyou * 覆蓋物的點擊事件 * */ @Override public boolean onMarkerClick(Marker marker) { Bundle bundle= marker.getExtraInfo(); MarkInfo MyMarker=(MarkInfo) bundle.getSerializable("mark"); ImageView iv=(ImageView) markLayout.findViewById(R.id.mark_image); TextView distanceTv=(TextView) markLayout.findViewById(R.id.distance); TextView nameTv=(TextView) markLayout.findViewById(R.id.name); TextView zanNumsTv=(TextView) markLayout.findViewById(R.id.zan_nums); iv.setImageResource(MyMarker.getImageId()); distanceTv.setText(MyMarker.getDistance()+""); nameTv.setText(MyMarker.getName()); zanNumsTv.setText(MyMarker.getZanNum()+""); //初始化一個InfoWindow initInfoWindow(MyMarker,marker); markLayout.setVisibility(View.VISIBLE); return true; } /** *@author mikyou *初始化出一個InfoWindow * * */ private void initInfoWindow(MarkInfo MyMarker,Marker marker) { // TODO Auto-generated method stub InfoWindow infoWindow; //InfoWindow中顯示的View內容樣式,顯示一個TextView TextView infoWindowTv=new TextView(MainActivity.this); infoWindowTv.setBackgroundResource(R.drawable.location_tips); infoWindowTv.setPadding(30, 20, 30, 50); infoWindowTv.setText(MyMarker.getName()); infoWindowTv.setTextColor(Color.parseColor("#FFFFFF")); final LatLng latLng=marker.getPosition(); Point p=myBaiduMap.getProjection().toScreenLocation(latLng);//將地圖上的經緯度轉換成屏幕中實際的點 p.y-=47;//設置屏幕中點的Y軸座標的偏移量 LatLng ll=myBaiduMap.getProjection().fromScreenLocation(p);//把改動後的屏幕的點有轉換成地圖上的經緯度對象 /** * @author mikyou * 實例化一個InfoWindow的對象 * public InfoWindow(View view,LatLng position, int yOffset)經過傳入的 view 構造一個 InfoWindow, 此時僅僅是利用該view生成一個Bitmap繪製在地圖中,監聽事件由開發人員實現。 * 參數: * view - InfoWindow 展現的 view * position - InfoWindow 顯示的地理位置 * yOffset - InfoWindow Y 軸偏移量 * */ infoWindow=new InfoWindow(infoWindowTv, ll, 10); myBaiduMap.showInfoWindow(infoWindow);//顯示InfoWindow } /** * @author zhongqihong * 給整個地圖加入的點擊事件 * */ @Override public void onMapClick(LatLng arg0) {//表示點擊地圖其它的地方使得覆蓋物的詳情介紹的佈局隱藏,但是點擊已顯示的覆蓋物詳情佈局上。則不會消失,因爲在詳情佈局上加入了Clickable=true //因爲事件的傳播機制,因爲點擊事件首先會在覆蓋物佈局的父佈局(map)中,因爲map是可以點擊的。map則會把點擊事件給消費掉。假設加上Clickable=true表示點擊事件由詳情佈局本身處理。不禁map來消費 markLayout.setVisibility(View.GONE); myBaiduMap.hideInfoWindow();//隱藏InfoWindow } @Override public boolean onMapPoiClick(MapPoi arg0) { return false; } public void toast(String str){ Toast.makeText(MainActivity.this, str, 0).show(); } }
執行效果: