百度地图在安卓上的基本使用

本文档中使用的是3.30版本的SDK。百度地图的SDK在老版本的基础上做了大量的封装,新版API使用起来更加的便捷和直观。只不过百度地图的SDK在升级过程中,部分类的内容有所改变,使用时需要查看一下手册。

本文章涵盖一下几方面内容:

地图状态更新的使用,定位,方向传感器的使用,地图覆盖物的添加,覆盖物的点击,信息窗口的使用

1. 开发前的准备工作及在Activity中显示百度地图

1)   申请APP_KEY:sha1安全码+包名

2)   在AndroidManifest文件中添加AK

<span style="font-family:FangSong_GB2312;font-size:18px;"><application>  
	…
    <meta-data  
        android:name="com.baidu.lbsapi.API_KEY"  
        android:value="开发者 key" /> 
… 
</application>
</span>

3)   添加需要的UserPermission

<span style="font-family:FangSong_GB2312;font-size:18px;"><uses-permission android:name="android.permission.GET_ACCOUNTS" />  
<uses-permission android:name="android.permission.USE_CREDENTIALS" />  
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />  
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />  
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
<uses-permission android:name="android.permission.INTERNET" />  
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />  
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />  
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />  
<uses-permission android:name="android.permission.READ_PHONE_STATE" />  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
<uses-permission android:name="android.permission.BROADCAST_STICKY" />  
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
</span>

这部分内容可以参考百度地图的手册,直接复制粘贴

4)在布局文件中(layout)添加地图容器

<span style="font-family:FangSong_GB2312;font-size:18px;"><com.baidu.mapapi.map.MapView  
    android:id="@+id/bmapView"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:clickable="true" />
</span>

5)在Activity的生命周期方法中写地图容器对应的生命周期方法

<span style="font-family:FangSong_GB2312;font-size:18px;">public class MainActivity extends Activity {  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);   
        //在使用SDK各组件之前初始化context信息,传入ApplicationContext  
        //注意该方法要再setContentView方法之前实现  
        SDKInitializer.initialize(getApplicationContext());  
        setContentView(R.layout.activity_main);  
    }  
}
</span>

注意:在SDK各功能组件使用之前都需要调用SDKInitializer.initialize(getApplicationContext());,因此我们建议该方法放在Application的初始化方法中

6)创建地图Activity,管理地图生命周期


public class MainActivity extends Activity {  
    MapView mMapView = null;  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);   
        //在使用SDK各组件之前初始化context信息,传入ApplicationContext  
        //注意该方法要再setContentView方法之前实现  
        SDKInitializer.initialize(getApplicationContext());  
        setContentView(R.layout.activity_main);  
        //获取地图控件引用  
        mMapView = (MapView) findViewById(R.id.bmapView);  
    }  
    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理  
        mMapView.onDestroy();  
    }  
    @Override  
    protected void onResume() {  
        super.onResume();  
        //在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理  
        mMapView.onResume();  
        }  
    @Override  
    protected void onPause() {  
        super.onPause();  
        //在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理  
        mMapView.onPause();  
        }  
    }

2. Baidu地图的进一步使用

1)  通过之前的百度MapView可以获得BaiduMap对象。当需要对BaiduMap上的各种内容进行更新的时候,需要利用MapStatusUpdate对象。

mMapView = (MapView) findViewById(R.id.map_mapView);
mBaiduMap = mMapView.getMap();
MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(15.0f);
mBaiduMap.setMapStatus(msu);

在获得了地图后,利用地图状态更新对象对地图做了设置。上面代码中对地图的设置是调整了地图的放大级别为15级。(比例尺为500米)

2)通过BaiduMap的setMapType来设置地图的类别,地图的类型包括Normal和Satellite,同时还可以通过setTrafficEnable方法来设置是否在地图上显示交通流量。

3. 百度地图的定位功能


百度地图定位的实现依靠的是LocationClient对象。使用LocationClient时需要两个额外的对象,首先是通过LocationClientOption对LocationClient进行设置。另一个是BDLocationListener接口,接口中有一个onReceiveLocation方法在获得位置后会进行回调。

LocationClientOption会进行一系列的对LocationClient的设置,包括是否使用解析地址名称,是否开启GPS,多长时间更新一次位置等设置:

mLocationClient = new LocationClient(this);创建LocationClient对象
LocationClientOption option = new LocationClientOption();创建LocationClient的属性
option.setCoorType("bd09ll");这里必须写bd09ll
option.setIsNeedAddress(true);
option.setOpenGps(true);
option.setScanSpan(1000); 1秒钟更新位置一次
mLocationClient.setLocOption(option);将属性设置到LocationClient上

BDLocationListener接口中仅有一个抽象方法onReceiveLocation(BDLocationlocation),当定位成功后会回调这个方法,并且传入一个封装了位置信息的BDLocation对象。但是这个BDLocation不能直接使用,需要将里面封装的大量信息提取出来并重新封装为一个可以在地图上显示的内容MyLocationData对象:

MyLocationData data = new MyLocationData.Builder()//
					.accuracy(location.getRadius())//
					.latitude(location.getLatitude())//
					.longitude(location.getLongitude())//
					.build();
mBaiduMap.setMyLocationData(data);

这里MyLocationData对象使用了一个内部类Builder来进行构建。构建完毕后,会将data交给BaiduMap对象来使用,从而将位置显示在地图上。进一步的设置还包括,通过设置MyLocationConfiguration对象,来使用自定义的代表位置的图标格式(默认的是一个圆点)。如果使用了一个三角形或者箭头来作为位置图片的话,就可以为MyLocationData设置一个direction属性,顾名思义,它可以进行方向的变化。当借助手机的方向传感器拿数据时,可以根据手机的位置来改变地图上表示位置的图标的方向。同时BDLocation对象里面通过调用getAddrStr方法,可以获得当前坐标位置对应的街道名称是什么,例如:

Toast.makeText(context,location.getAddrStr(),Toast.LENGTH_SHORT).show();

写完监听器,要将监听器绑定到LocationClient对象上:

mLocationClient.registerLocationListener(mLocationListener);

当为LocationClient对象指定了属性和监听器后,就可以开启/关闭Locationclient对象了。开启时,写在Activity的onStart方法里面比较合适,这样当用户看见界面的时候,定位可能已经完成了:

onStart(){
super.onStart();
		// 开启定位
		mBaiduMap.setMyLocationEnabled(true);
		if (!mLocationClient.isStarted())
			mLocationClient.start();
}

可以看到在LocationClient开始工作之前,要让定位图层处于可用状态。所有的定位信息都将出现在定位图层上面。

注:来自百度地图的官方文档的说明:

百度地图SDK为广大开发者提供的基础地图和上面的各种覆盖物元素,具有一定的层级压盖关系,具体如下(从下至上的顺序):

1、基础底图(包括底图、底图道路、卫星图等);

2、地形图图层(GroundOverlay);

3、热力图图层(HeatMap);

4、实时路况图图层(BaiduMap.setTrafficEnabled(true););

5、百度城市热力图(BaiduMap.setBaiduHeatMapEnabled(true););

6、底图标注(指的是底图上面自带的那些POI元素);

7、几何图形图层(点、折线、弧线、圆、多边形);

8、标注图层(Marker),文字绘制图层(Text);

9、指南针图层(当地图发生旋转和视角变化时,默认出现在左上角的指南针);

10、定位图层(BaiduMap.setMyLocationEnabled(true););

11、弹出窗图层(InfoWindow);

12、自定义View(MapView.addView(View););

所有与定位相关的内容都要“绘制”在定位图层上,所以要先让定位图层可以用,在绘制与定位相关的内容。

同样的在onStop方法中要停止LocationClient继续去获得位置:

protected void onStop(){
		super.onStop();
		// 停止定位
		mBaiduMap.setMyLocationEnabled(false);
		mLocationClient.stop();
	}

必须要注意的是,LocationClient并不是直接进行定位的,从它的类型名字就可以推测出它仅仅是个“客户端”,真正在后台按指定的间隔进行位置获取的是百度地图提供的一个后台常驻Service,这个Service必须在AndroidManifest文件中进行声明,声明的格式如下:

<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>

这是一个供LocationClient进行跨进程访问的,真正进行不间断位置信息获取的服务。而BDLocation接口实际是后台Service和LocationClient进行通信的一个桥梁。

在介绍使用方向传感器获得方向以改变位置图标的指向前,再介绍一个BDLocation中经纬度信息的小应用。

当在地图上滑动,有时可能会滑动到离当前使用者所在位置较远的地方,利用如下代码可以通过点击一个按钮或者菜单项回到以使用者当前所在位置为中心的地图。

mLatitude = location.getLatitude();
mLongtitude = locaton.getLongtitude();
MapStatusUpdate msu =
MapStatusUpdateFactory.newLatLng(new LagLng(mLatitude,mLongtitude));
mBaiduMap.animateMapStatus(msu);

在MyLocationListener接口的onReceiveLocation回调方法中,利用传进来的BDLocation对象为两个属性mLatitude和mLongtitude属性赋值。这样每隔一定的时间间隔,都能保证获得最新的经纬度信息。利用经度和纬度构建一个封装了它们的对象LatLng,并利用它创建MapStatusUpdate对象,并让BaiduMap对象以动画的方式将LatLng表示的位置设为地图的中心点。

接下来,为地图上的位置点指定一个自定义图像作为图示,并且通过使用方向传感器拿数据以根据手机所指向方向的不同来改变自定义图像的指向方位。

4. 使用方向传感器

手机上有众多的传感器,传感器的使用是通过SensorManager来进行的。通过SensorManager能够对使用机中的某一个或某几个传感器。本例中只要获得方向传感器这一个传感器。


使用SensorManager管理传感器时,当传感器感应到数据发生变化时,SensorManager会回调SensorEventListener接口中的方法,因此还需要实现SensorEventListener接口,并将接口注册到SensorManager上。
接口中有两个回调方法:


public void onAccuracyChanged(Sensor arg0, int arg1)
public void onSensorChanged(SensorEvent event)
一般只要重写onSensorChanged方法即可。通过该回调方法的参数获得SensorEvent中封装的传感器事件类型。如果是我们需要的传感器传来的数据,就进行相应的处理。

当把监听器注册到SensorManager中的时候,就可以开始监听传感器数据变化了,如果将监听器从SensorManager中注销掉,就停止了对传感器的监听。

看一个完整的实现:


public class MyOrientationListener implements SensorEventListener{
	private SensorManager mSensorManager; SensorManager对象
	private Context mContext; 我们需要上下文对象来获得SensorManager
	private Sensor mSensor; 未来这个mSensor要引用方向传感器
	private float lastX; 我们只对方向传感器传递过来X轴的变化感兴趣

	public MyOrientationListener(Context context){
		this.mContext = context; 获得外部传入的上下文对象
	}

	public void start()	{
		mSensorManager = (SensorManager)
			mContext.getSystemService(Context.SENSOR_SERVICE);
		if (mSensorManager != null){
			// 获得方向传感器
			mSensor = mSensorManager.getDefaultSensor(
					Sensor.TYPE_ORIENTATION);
		}

		if (mSensor != null){说明手机上确实有方向传感器
		注册SensorEventListener监听来自mSensor监听器的事件,监听的频率是SensorManager.SENSOR_DELAY_UI。SensorManager中还定义了不同的常量表示不同的监听精度和监听频率。本例中的拿到的数据主要是为了更新地图界面上的定位箭头方向,所以使用专门为UI设置的频率就可以SENSOR_DELAY_UI
			mSensorManager.registerListener(this, mSensor,
					SensorManager.SENSOR_DELAY_UI);
		}
	}

	public void stop(){
		mSensorManager.unregisterListener(this);
	}
	@Override
	public void onAccuracyChanged(Sensor arg0, int arg1){
		监听器中的这个方法不用实现
	}

	@SuppressWarnings(
	{ "deprecation" })
	@Override
	public void onSensorChanged(SensorEvent event){
		判断事件的类型是否是来自方向传感器
		if (event.sensor.getType() == Sensor.TYPE_ORIENTATION){
		方向传感器中的事件是XYZ轴三轴数据的当前值
                  我们只关心X轴方向的数据变化
			float x = event.values[SensorManager.DATA_X];
			if (Math.abs(x - lastX) > 1.0) {
这里是一个设计框架类的典型应用技巧。留下一个接口,和一个接口的注册方法,让真正的使用者通过提供接口的实现来进行具体的对X轴方向这个数据的消费和使用
				if (mOnOrientationListener != null){
					mOnOrientationListener.
						onOrientationChanged(x);
				}
			}
	原则上,如果没有OnOrientationListener接口的实现应该抛出一个异常
		lastX = x;
		}
	}
	private OnOrientationListener mOnOrientationListener;
	提供一个注册接口的方法,当onSensorChanged回调发生时获得需要的数据,再去回调用户提供的方法来消费onSensorChanged中提取出来的数据
	public void setOnOrientationListener(
			OnOrientationListener mOnOrientationListener){
		this.mOnOrientationListener = mOnOrientationListener;
	}
	public interface OnOrientationListener	{
		void onOrientationChanged(float x);
	}
}

这个类提供了start方法和stop方法。在start方法中注册SensorEventListener开始进行传感器数据的监听,在Stop方法中注销SensorEventListener停止传感器数据的监听。
接下来,在MainActivity中使用MyOrientationListener的时候,要提供一个OnOrientationListener接口的实现类去消费通过传感器获得的X轴数据。

myOrientationListener = new MyOrientationListener(context);
myOrientationListener				.setOnOrientationListener(
		new OnOrientationListener(){
			@Override
			public void onOrientationChanged(float x){
						mCurrentX = x;
					}
				});

这个实现比较简单,就是当传感器获得X轴数据后,回调用户提供的OnOrientationListener中的onOrientationChanged方法,将这个X轴数据传进去,传进去后,将这个值作为一个属性的值mCurrentX。
未来,X轴发生变化时,mCurrentX值会发生变化,这个变化会影响到位置图标的变化。

所以,首先要将位置图标从一个默认的圆形替换为一个三角形:

首先获得图标本身(从drawable—>BitmapDescriptor)

<span style="font-family:FangSong_GB2312;font-size:18px;">BitmapDescriptor mIcon = BitmapDescriptorFactory.fromResource(
				R.drawable.navi_map_gps_locked);
</span>

然后将这个自定义的图标封装到MyLocationConfiguration中:

<span style="font-family:FangSong_GB2312;font-size:18px;">MyLocationConfiguration config = new MyLocationConfiguration(
					mLocationMode, 
					true, 
					mIconLocation);
</span>

创建MyLocationConfiguration对象时需要三个参数:
LocationMode:地图模式。百度地图的地图模式有三种,NORMAL标准模式,COMPASS罗盘模式和FOLLOWING跟随模式
boolean enableDirection:是否允许显示方向信息。我们这里就是要显示方向的变化情况,所以要设置为true。
BitmapDescriptor:使用自定义的表示位置的图标
当MyLocationConfiguration创建完毕后,要让BaiduMap对象来使用这个对象:
mBaiduMap.setMyLocationConfigeration(config);
还有额外的一点需要注意的是,因为现在要使用方向,所以在之前Build MyLocationData对象时现在需要多添加一个属性direction,让BaiduMap对象可以去呈现方向的变化:

<span style="font-family:FangSong_GB2312;font-size:18px;">MyLocationData data = new MyLocationData.Builder()//
			.direction(mCurrentX)//
			.accuracy(location.getRadius())//
			.latitude(location.getLatitude())//
			.longitude(location.getLongitude())//
			.build();
mBaiduMap.setMyLocationData(data);
</span>

现在整体的工作流程是:传感器监听和位置监听一同启动。传感器监听到X轴的数据变化后,会将数据传递到MainActivity的一个属性mCurrentX中。LocationClient每间隔ScanSpan毫秒(本例是1000毫秒)会去刷新一次位置(每隔一秒从LocationClient向com.baidu.location.f服务发起一次请求,通过com.baidu.location.f服务获得位置),得到新的位置后,通过回调BDLocationListener中的onReceiveLocation方法将位置信息封装为BDLocation进行传递。利用最新的BDLocation对象中封装的数据来更新BaiduMap上呈现的内容,包括范围,经度,纬度和方向。

5. 在地图上添加覆盖物Overlay

Baidu地图中覆盖物相关类的名称叫做Marker。与覆盖物相关的内容包括覆盖物的相关属性设置,如覆盖物的图标,覆盖物的位置(经纬度)。同时可以通过地图为覆盖物添加单击事件监听器OnMarkerClickListener(为覆盖物添加监听器不是在Marker对象上添加,而是在BaiduMap上添加的)。

设置Marker属性的时候使用的MarkerOptions来封装这些属性。


MarkerOptions opts = 
	new MarkerOptions().position(经纬度).icon(图标).zIndex(5);

其中position方法是设置Marker在地图上的位置,参数为LatLng,它里面封装了Latitude和Longtitude。
icon方法设置Marker的图标,参数为BitmapDescriptor。
zIndex方法指定了Marker所在的图层位置,数字越大离使用者越近。
当设置好了属性之后,就可以调用BaiduMap的addOverlay(opts)方法将Marker对象添加到地图上。这里需要注意的是,百度官方的API文档写的是addOverlay需要的参数类型是OverlayOptions,方法的返回值类型是com.baidu.mapapi.map.Overlay。我们的MarkerOptions继承自OverlayOptions,Marker继承自com.baidu.mapapi.map.Overlay。所以,如果需要在BaiduMap调用了addOverly方法返回后,还需要对添加物进行其他的设置,比如添加单击事件监听器,就需要用一个对象引用该方法的返回值,如果使用Marker直接引用的话就需要进行一次类型的强转,从Overlay转为Marker:


Marker marker = (Marker) mBaiduMap.addOverlay(opts);

Marker还有一个不错的功能,类似View的setTag方法,通过调用Marker的setExtraInfo()方法,可以为Marker对象绑定一个Bundle对象,通过向Bundle对象中添加内容(例如putSerializable放对象进去),将Bundle绑定到Marker上,这样当该Marker对象上发生了点击时,如果有需要,就可以通过获取该Marker对象上绑定的Bundle中的内容来较复杂的数据。


Bundle bundle = new Bundle();
	bundle.putSerializable("bean", bean);
	marker.setExtraInfo(bundle);

当Marker出现在地图上之后,可以为他们添加监听器。即在地图上点击了Marker之后会触发一系列内容,比如当点击了一个Marker后,在被点击的Marker上方出现一个信息窗,这个信息窗显示出与Marker相关的内容。注意:信息窗与覆盖物本身没有任何联系。
首先构建信息窗对象:
InfoWindow的构造器有两种:

InfoWindow(BitmapDescriptor bd, LatLng position, int yOffset, InfoWindow.OnInfoWindowClickListener listener)
通过传入的 bitmap descriptor 构造一个 InfoWindow。
InfoWindow(View view, LatLng position, int yOffset)
通过传入的 view 构造一个 InfoWindow, 此时只是利用该view生成一个Bitmap绘制在地图中。
看一下四个参数的构造器:
bd参数:这里使用一个图像来作为InfoWindow出现。
position参数:InfoWindow的经纬度信息
yOffset参数:这是因为,如果当你点击Marker的时候想生成一个InfoWindow,而如果InfoWindow和Marker的LatLng是相同的时候,他们会出现在同一个地图点上,这样InfoWindow就会把Marker给盖住了。所以,要让InfoWindow对象在真实LatLng坐标点的基础上沿Y轴方向进行适当的便宜,出现在同一个LatLng位置点的Marker的上方或者下方,这个yOffset就是以当前屏幕像素为单位进行偏移的偏移量。当然,如果不想使用偏移量,也可以采用更改LatLng的方式,方法是:
真实的LatLngà将真实的LatLng转为当前屏幕坐标点(即用屏幕像素数来表示这个点)—>对屏幕坐标点进行偏移(此时偏移可以发生在任意方向上,X轴Y轴均可以)à将偏移后的屏幕点坐标转为对应的LatLngà将该偏移过的LatLng提交给InfoWindow的构造器。
listener:当InfoWindow被点击时时会回调该监听器的onInfoWindowClick()方法。
三参数构造器中,可以传入一个View来作为InfoWindow。这就意味着可以使用复杂布局来构造这个InfoWindow。
这里特别需要注意一点的是,在早期的Baidu API中InfoWindow有这样一个构造器InfoWindow(View view, LatLng ll, OnInfoWindowClickListener listener)
这个构造器从3.3 API开始已经不存在了。
在新版本中,如果即需要为InfoWindow指定一个自定义的View作为视图,又希望为它指定一个点击动作的监听器InfoWindowClickListener,可以利用四个参数的构造器,利用BitmapDescriptorFactory将View转为BitmapDescriptor:
mInfoWindow = new InfoWindow(
          BitmapDescriptorFactory.fromView(button), 
          ll, -47, listener);
接下来可以看一个完整的,关于在地图上添加Marker的的例子。当在地图上点击Marker的时候,会在Marker上方出现一个InfoWindow。这是因为InfoWindow会在以真实的经纬度映射到屏幕上时,在“正确的”位置上向上偏移一段距离,这样就不会覆盖同样位置的Marker了。点击了InfoWindow后,InfoWindow会消失,如果点击了地图上的其它位置,InfoWindow也会消失。InfoWindow中显示的信息是来自被点击的Marker中的ExtraInfo信息中的Bundle中的内容。
首先创建Marker对象,并为Marker指定属性:
mBaiduMap.clear(); 添加Marker之前把原先地图上已经存在的Marker都清除掉
LatLng latLng = null; 封装经纬度
Marker marker = null; 覆盖物
OverlayOptions options; OverlayOptions是MarkerOptions的父类
for (Info info : infos){//Info是一个Bean,封装了一个地点的经度纬度等信息
// 经纬度
latLng = new LatLng(info.getLatitude(), info.getLongitude());
// 开始设置Marker的属性
// 其中mMarker是覆盖物使用的图标:
// BitmapDescriptor mMarker = 
// BitmapDescriptorFactory.fromResource(R.drawable.maker);
options = new MarkerOptions().position(latLng).icon(mMarker).zIndex(5);
//将创建好的覆盖物添加到地图上
marker = (Marker) mBaiduMap.addOverlay(options);
//这里要让Marker上面“携带”一个封装了大量信息的bean对象
//类似于View的setTag方法
//稍微有点不同的是,setTag方法可以直接放入bean对象,setExtraInfo方法
//需要放入一个Bundle,把bean对象放入到Bundle中。
//要放入Bundle,就要求bean对象必须是可序列化的
Bundle arg0 = new Bundle();
arg0.putSerializable("info", info);
marker.setExtraInfo(arg0);
}
//上面创建了infos长度个Marker,每一个Marker里面都“携带”了
//infos中的一个info
//此时将地图的中心移动到最后一个info的经纬度位置
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
mBaiduMap.setMapStatus(msu);
当添加了覆盖物或者说Marker之后,如果想点击时产生响应,就要在地图上绑定Marker的监听器。
mBaiduMap.setOnMarkerClickListener(new OnMarkerClickListener(){
          @Override
          public boolean onMarkerClick(Marker marker){
          //获得Marker上绑定的封装了信息的对象
          Bundle extraInfo = marker.getExtraInfo();
          //info是一个实现了序列号接口的bean
          Info info = (Info) extraInfo.getSerializable("info");
          ImageView iv = (ImageView) mMarkerLy.findViewById(R.id.id_info_img);
          TextView distance = (TextView) mMarkerLy.findViewById(R.id.id_info_distance);
          TextView name = (TextView) mMarkerLy.findViewById(R.id.id_info_name);
          TextView zan = (TextView) mMarkerLy.findViewById(R.id.id_info_zan);
          iv.setImageResource(info.getImgId());
          distance.setText(info.getDistance());
          name.setText(info.getName());
          zan.setText(info.getZan() + "");
          //本例会使用一个TextView作为InfoWindow的布局
          InfoWindow infoWindow;
          TextView tv = new TextView(context);
          tv.setBackgroundResource(R.drawable.location_tips);
          tv.setPadding(30, 20, 30, 50);
          tv.setText(info.getName());
          tv.setTextColor(Color.parseColor("#ffffff"));
          final LatLng latLng = marker.getPosition();
          //将一个经纬度映射为屏幕上的点坐标(即从经纬度坐标转为当前屏幕以像素点表示的xy坐标)
          Point p = mBaiduMap.getProjection().toScreenLocation(latLng);
          //将真实位置屏幕点的纵坐标上移47个像素点
          p.y -= 47;
          //移动完毕后,将这个屏幕点映射回经纬度坐标(此时的经纬度坐标已经不是原来精确的经纬度坐标了)
          LatLng ll = mBaiduMap.getProjection().fromScreenLocation(p);
          //在移动后的经纬度位置绘制infowindow
          //此时infowindow出现在屏幕上的位置是移动后的经纬度在屏幕点上的位置
          //利用获得的各种内容构建infowindow对象
          //需要注意的是,例子中使用的这个构造器是infowindow的老版本构造器。在新版本的Baidu地图中
          //要使用新的4参数构造器(说明见上)
//infoWindow = new InfoWindow(BitmapDescriptorFactory.fromView(tv)
//利用工厂加载View组件,而不能直接使用视图组件
//ll,经纬度信息
//-47, 直接提供屏幕点偏移量即可,省去了经纬度坐标嗯哼屏幕坐标的转换
//new OnInfoWindowListener(){点击InfoWindow后回调监听器中的方法
         //to…do
});
          infoWindow = new InfoWindow(tv, ll, new OnInfoWindowClickListener(){
                    @Override
                    public void onInfoWindowClick(){
          //一旦点击了某一个infowindow,地图会将这个infowindow隐藏
                              mBaiduMap.hideInfoWindow();
                    }});
          mBaiduMap.showInfoWindow(infoWindow);
          return true;
          }});
以上这段代码为Marker添加了监听器,需要注意的是,因为是在地图上对Marker进行点击,所以Marker的监听器是添加在地图上的。当某一个Marker被点击后,infowindow出现,infowindow中放了一个TextView用来显示内容,显示的内容是“存放”在Marker上的一个可序列化的Bean对象中封装的信息。当点击infowindow的时候,被点击的infowindow调用infowindow上绑定的监听器,让infowindow消失。
地图上除了可以绑定Marker监听器之外,还可以绑定其他的监听器,比如点击地图时会回调地图上绑定的点击事件监听器:
mBaiduMap.setOnMapClickListener(new OnMapClickListener(){
                               @Override
                               public boolean onMapPoiClick(MapPoi arg0){
                                         return false;
                               }
                               @Override
                               public void onMapClick(LatLng arg0){
                                         mBaiduMap.hideInfoWindow();
                               }
                    });
当在地图上点击时,就会触发地图上的OnMapClickListener监听器。本例中,点击发生后,将地图上正在显示的infowindow都隐藏掉。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Android中使用百度地图,可以按照以下步骤进行操作: 1. 在百度地图开放平台上注册账号,并创建应用,获取AK密钥。 2. 在Android Studio中创建一个新的项目,然后在项目的build.gradle文件中加入以下代码: ``` dependencies { implementation 'com.baidu.android:map-sdk:6.3.0' } ``` 3. 在AndroidManifest.xml文件中添加以下权限: ``` <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> ``` 4. 在布局文件中添加MapView控件,例如: ``` <com.baidu.mapapi.map.MapView android:id="@+id/bmapView" android:layout_width="match_parent" android:layout_height="match_parent" app:mapType="normal" app:logoPosition="left_top"/> ``` 5. 在Activity中获取MapView对象,并设置地图类型和缩放级别等属性,例如: ``` public class MainActivity extends AppCompatActivity { private MapView mMapView; private BaiduMap mBaiduMap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mMapView = (MapView) findViewById(R.id.bmapView); mBaiduMap = mMapView.getMap(); //设置地图类型为卫星地图 mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE); //设置缩放级别为18 MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.zoomTo(18); mBaiduMap.setMapStatus(mapStatusUpdate); } @Override protected void onDestroy() { super.onDestroy(); mMapView.onDestroy(); } @Override protected void onResume() { super.onResume(); mMapView.onResume(); } @Override protected void onPause() { super.onPause(); mMapView.onPause(); } } ``` 以上就是在Android中使用百度地图基本步骤。需要注意的是,使用百度地图需要联网,因此需要在AndroidManifest.xml文件中添加相应的权限。同时,在Activity的生命周期方法中需要调用MapView的对应方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值