• 浅谈百度地图的简单开发之结合方向传感器实现定位功能(三)


     

    今天我们来谈下百度地图的定位功能。在此之前我已经将百度地图的基本地图大概说了下,事实上百度地图的基本功能还有非常多的内容。

    感兴趣的能够到百度地图的开发人员的官网看看。今天就開始来讲下百度地图中的定位功能。

    今天所讲的百度地图所涉及的内容主要有:基本定位的实现。自己定义定位图标。结合方向传感器定位,选择定位中的几种模式(罗盘模式,普通模式,尾随模式)。

    一、基本定位的实现:

    所谓定位无非就是获取到一个地方所处地球的经纬度坐标。这个反映到地图中就是一个点。可是怎么去实现一个定位呢??

    首先,须要去创建一个定位client对象。然后给这个定位client对象设置监听器。而且每隔1s中就去请求一次定位。这就是所谓实时监听定位信息的变化。也就是位置发生变化,那么所处的经纬度就变化了,通过经纬度值能够得到一个经纬度对象,通过这个经纬度对象(实际上就是相应一个点),反映在地图上点的位置发生了变化。

    这样一来定位也是一个高耗的工作,所以我们也须要管理定位的生命周期。当我们开启应用就去开启定位,关闭应用就得关闭定位的请求。

    记住一点就是使用定位功能还得在AndroidManifest.xml配置一个Service。

    注冊service:

         <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);
    			}
    		}

    二、改动自己定义图标

    	/**
    	 * @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);//表示使用动画的效果传入,通过传入一个地图更新状态对象。然后利用百度地图对象来展现和还原那个地图更新状态。即此时的地图显示就为你如今的位置
    		}
    

    三、结合方向传感器来控制定位图标方向。使得整个图标会随着手机方向的转动而转动。

    可是假设去实时推断手机在转动呢?以及手机转动的方向和角度是多少呢?这时候就须要手机中内置的方向传感器,该方向传感器能够监測到手机在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);//回调的方法
    	}
    }
    

    四、选择定位中的几种模式(罗盘模式。普通模式,尾随模式):

    	/**
    	 * @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下载链接 

  • 相关阅读:
    1029 旧键盘 (20 分)
    1028 人口普查 (20 分)
    1026 程序运行时间 (15 分
    1025 反转链表 (25 分
    1024 科学计数法 (20 分
    1023 组个最小数 (20 分)
    将命令的输出保存到文件
    使用与管理控制台历史
    度量命令执行时间
    检查最后运行命令的状态
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7091583.html
Copyright © 2020-2023  润新知