淺談百度地圖的簡單開發之結合方向傳感器實現定位功能(三)

 

今天咱們來談下百度地圖的定位功能。在此以前我已經將百度地圖的基本地圖大概說了下,事實上百度地圖的基本功能還有很是多的內容。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();
	}
}


執行效果:

      

Demo下載連接 

相關文章
相關標籤/搜索