您当前的位置Android SDK>开发指南>覆盖物

覆盖物

1.概述

所有叠加或覆盖到地图的内容,我们统称为地图覆盖物。如标注、矢量图形元素(包括:折线、多边形和圆)、定位图标等。覆盖物拥有自己的地理坐标,当您拖动或缩放地图时,它们会相应的移动。

 目前百度地图SDK支持多种类型的覆盖物,可以满足用户的各种需求。用户可根据自己的实际需求自由添加各种类型的覆
 盖物,且不会产生冲突。此外,用户可以根据添加图层的顺序来控制覆盖物显示的顺序(图片图层除外)。

百度地图SDK为开发者们提供了如下类型的地图覆盖物:

  • 我的位置图层(MyLocationOverlay):用于显示用户当前位置的图层(支持自定义位置图标);

  • Poi搜索结果图层(PoiOverlay):用于显示兴趣点搜索结果的图层;

  • 路线图层(RouteOverlay):公交、步行和驾车线路图层,将公交、步行和驾车出行方案的路线及关键点显示在地图上(起、终点图标用户可自定义);

  • 公交换乘图层(TransitOverlay):公交换乘线路图层,将某一特定地区的公交出行方案的路线及换乘位置显示在地图上(起、终点图标用户可自定义);

  • 自定义图层(ItemizedOverlay):可将一个或多个兴趣点绘制到地图上,且支持自定义图标(支持动态更新Item位置、图标);

  • 弹出窗图层(PopupOverlay):在地图上显示一个弹出窗口;

  • 几何图形绘制图层(GraphicsOverlay):用于绘制点、折线段、弧线、圆、矩形、多边形等几何图形的图层;

  • 文字绘制图层(TextOverlay):用于绘制文字的图层。

  • 图片图层(GroundOverlay):用于展示用户传入图片的图层。

  • 全景图图层(PanoramaOverlay):在全景图内标绘兴趣点,支持自定义图标样式。

注:除弹出窗图层外,其他各个图层均已实现多实例。全景图图层是针对全景图所使用的特殊图层。

MapView使用一个List管理覆盖物,通过向MapView.getOverlays() add或remove上述类或其基类的实例即可向地图添加或删除覆盖物。在更新地图覆盖物后,需调用MapView.refresh() 使更新生效。

2.我的位置图层:MyLocationOverlay

将MyLocationOverlay添加到覆盖物中,能够实现在地图上显示当前位置的图标以及指南针:

自2.0.0版本开始,MyLocationOverlay只负责显示我的位置,位置数据请使用百度定位SDK获取,将获取的位置数据放在一个LocationData结构中并用该结构设置MyLcationOverlay的数据源,即可创建MyLocationOverlay。因此定位图层的使用略有不同,具体参考如下代码:

MyLocationOverlay myLocationOverlay = new MyLocationOverlay(mMapView);
LocationData locData = new LocationData();
//手动将位置源置为天安门,在实际应用中,请使用百度定位SDK获取位置信息,要在SDK中显示一个位置,需要使用百度经纬度坐标(bd09ll)
locData.latitude = 39.945;
locData.longitude = 116.404;
locData.direction = 2.0f;
myLocationOverlay.setData(locData);
mMapView.getOverlays().add(myLocationOverlay);
mMapView.refresh();
mMapView.getController().animateTo(new GeoPoint((int)(locData.latitude*1e6),
(int)(locData.longitude* 1e6)));

此外,自v2.2.0起,地图SDK为您提供了更丰富的定位效果展示,即普通态、跟随态和罗盘态。具体使用方法请参考官方Demo(LocationOverlayDemo.java)。

运行结果如下:

android_dev09.jpg

3.Poi搜索结果图层:PoiOverlay

具体使用方法请参考兴趣点搜索部分的相关介绍。

4.路线图层:RouteOverlay

具体使用方法请参考路径规划中驾车及步行线路搜索相关部分的内容。此外,在绘制路线检索结果的时候,您还可以通过setStMarker(Drawable stMarker)和setEnMarker(Drawable enMarker)方法来自定义起、终点图标的样式。(具体使用方法请参考相关Demo部分的介绍)

5.公交换乘图层:TransitOverlay

具体使用方法请参考路径规划中公交线路搜索部分的内容。此外,在绘制路线检索结果的时候,您还可以通过setStMarker(Drawable stMarker)和setEnMarker(Drawable enMarker)方法来自定义起、终点图标的样式。(具体使用方法请参考相关Demo部分的介绍)

6.自定义图层:ItemizedOverlay

自v2.1.2开始,自定义图层支持动态更新Item位置、图标。

在地图上显示一个或一组覆盖物。

从2.0.0版本开始,SDK不支持直接继承Overlay , 用户可通过继承ItemizedOverlay来添加覆盖物。

添加覆盖物的一般流程如下:

1. 创建OverlayItem,准备overlay数据;

2. 创建ItemizedOverlay实例,调用 addItem(OverlayItem) 接口添加overlay。

3. 调用MapView.getOverlays().add()方法添加overlay到mapview中。

4. 调用MapView.refresh() 使Overlay生效

示例代码如下:

   
				/*
				 * 要处理overlay点击事件时需要继承ItemizedOverlay
				 * 不处理点击事件时可直接生成ItemizedOverlay.
				 */
				class OverlayTest extends ItemizedOverlay<OverlayItem> {
				    //用MapView构造ItemizedOverlay
				    public OverlayTest(Drawable mark,MapView mapView){
				            super(mark,mapView);
				    }
				    protected boolean onTap(int index) {
				        //在此处理item点击事件
				        System.out.println("item onTap: "+index);
				        return true;
				    }
				        public boolean onTap(GeoPoint pt, MapView mapView){
				                //在此处理MapView的点击事件,当返回 true时
				                super.onTap(pt,mapView);
				                return false;
				        }
				        // 自2.1.1 开始,使用 add/remove 管理overlay , 无需重写以下接口
				        /*
				        @Override
				        protected OverlayItem createItem(int i) {
				                return mGeoList.get(i);
				        }
				       
				        @Override
				        public int size() {
				                return mGeoList.size();
				        }
				        */
				}        
				 
				/**
				 *  在想要添加Overlay的地方使用以下代码,
				 *  比如Activity的onCreate()中
				 */
				//准备要添加的Overlay
				double mLat1 = 39.90923;
				double mLon1 = 116.397428;
				double mLat2 = 39.9022;
				double mLon2 = 116.3922;
				double mLat3 = 39.917723;
				double mLon3 = 116.3722;
				// 用给定的经纬度构造GeoPoint,单位是微度 (度 * 1E6)
				GeoPoint p1 = new GeoPoint((int) (mLat1 * 1E6), (int) (mLon1 * 1E6));
				GeoPoint p2 = new GeoPoint((int) (mLat2 * 1E6), (int) (mLon2 * 1E6));
				GeoPoint p3 = new GeoPoint((int) (mLat3 * 1E6), (int) (mLon3 * 1E6));
				//准备overlay图像数据,根据实情情况修复
				Drawable mark= getResources().getDrawable(R.drawable.icon_marka);
				//用OverlayItem准备Overlay数据
				OverlayItem item1 = new OverlayItem(p1,"item1","item1");
				//使用setMarker()方法设置overlay图片,如果不设置则使用构建ItemizedOverlay时的默认设置
				OverlayItem item2 = new OverlayItem(p2,"item2","item2");
				item2.setMarker(mark);
				OverlayItem item3 = new OverlayItem(p3,"item3","item3");
				 
				//创建IteminizedOverlay
				OverlayTest itemOverlay = new OverlayTest(mark, mMapView);
				//将IteminizedOverlay添加到MapView中
			
				mMapView.getOverlays().clear();
				mMapView.getOverlays().add(itemOverlay);
				 
				//现在所有准备工作已准备好,使用以下方法管理overlay.
				//添加overlay, 当批量添加Overlay时使用addItem(List<OverlayItem>)效率更高
				itemOverlay.addItem(item1);
				itemOverlay.addItem(item2);
				itemOverlay.addItem(item3);
				mMapView.refresh();
				//删除overlay .
				//itemOverlay.removeItem(itemOverlay.getItem(0));
				//mMapView.refresh();
				//清除overlay
				// itemOverlay.removeAll();
				// mMapView.refresh();
				

效果图:

app_myitemizedoverlay.png

7.弹出窗口图层:PopupOverlay

PopupOverlay用于快速在特定位置显示一个由1-3张图片组成的弹窗,且三张图片都具有相应的响应方法,代码示例如下:

在天安门显示一个弹窗:

				//pop demo
				//创建pop对象,注册点击事件监听接口
				PopupOverlay pop = new PopupOverlay(mMapView,new PopupClickListener() {                
				        @Override
				        public void onClickedPopup(int index) {
				                //在此处理pop点击事件,index为点击区域索引,点击区域最多可有三个
				        }
				});
				/**  准备pop弹窗资源,根据实际情况更改
				 *  弹出包含三张图片的窗口,可以传入三张图片、两张图片、一张图片。
				 *  弹出的窗口,会根据图片的传入顺序,组合成一张图片显示.
				 *  点击到不同的图片上时,回调函数会返回当前点击到的图片索引index
				 */
				Bitmap[] bmps = new Bitmap[3];
				try {
				bmps[0] = BitmapFactory.decodeStream(getAssets().open("marker1.png"));
				     bmps[1] = BitmapFactory.decodeStream(getAssets().open("marker2.png"));
				bmps[2] = BitmapFactory.decodeStream(getAssets().open("marker3.png"));
				} catch (IOException e) {
				         e.printStackTrace();
				}
				//弹窗弹出位置
				GeoPoint ptTAM = new GeoPoint((int)(39.915 * 1E6), (int) (116.404 * 1E6));
				//弹出pop,隐藏pop
				pop.showPopup(bmps, ptTAM, 32);
				//隐藏弹窗
				//  pop.hidePop();
				

运行结果如下:

自Android SDK v2.3.0起,为了更灵活地使用PopupOverlay,弹出窗图层中,新增了弹出内容为自定义View的方法。核心代码如下:

					showPopup(View view, GeoPoint point, int yOffset);
					//view:自定义 View
					//point:弹窗的位置(锚点在窗口的中下方向。水平方向:Center;垂直方向:Bottom)
					//yOffset:弹窗在y轴上的偏移量,取值范围yOffset>=0。单位:像素
				

8.几何图形绘制图层:GraphicsOverlay

自定义绘制几何图形需要以下几个类的支持:

  • Geometry:这是一个几何图形类,利用此类,可以构建待绘制的各种基本几何元素;
  • Symbol:样式类,如果只构建几何图形类而没有样式的话,该几何图形是无意义的;
  • Graphic:图形类,利用几何图形加上样式,这样就可以构建一个图形类,Graphic就是这样一个类,用于管理所添加的图形;
  • GraphicsOverlay:这是一个用于绘制图形的overlay,和其他的各种overlay用法相同。

下面就来向大家介绍如何通过以上几个类绘制一个属于自己的图形:

第一步:

创建自绘图形:Geometry,Geometry表示一个用于绘图的几何图形,目前SDK支持的几何图形有:点、折线段、弧线、圆、矩形和任意多边形(包括凸、凹两种)。如下为添加矩形的核心代码:

				//故宫左上角
				GeoPoint geoPoint1 = new GeoPoint((int)(39.929 * 1E6),(int)(116.397 * 1E6));
				//故宫右下角
				GeoPoint geoPoint2 = new GeoPoint((int)(39.920 * 1E6),(int)(116.408 * 1E6));
				GeoPoint palaceCenter = new GeoPoint((int)(39.924 * 1E6),(int)(116.403 * 1E6));
				//创建一个覆盖故宫范围的距形
				Geometry palaceGeometry = new Geometry();
				palaceGeometry.setEnvelope(geoPoint1, geoPoint2);
				

注: Geometry对象不可复用,要绘制多个图形,需要创建多个Geometry。

第二步:

为自绘图形选择合适的样式:Symbol,Symbol表示绘图样式,如点颜色,线宽,填充色等。示例代码如下:

				Symbol palaceSymbol = new Symbol();//创建样式
				Symbol.Color palaceColor = palaceSymbol.newColor();//创建颜色
				palaceColor.red = 0;//设置颜色的红色分量
				palaceColor.green = 0;//设置颜色的绿色分量
				palaceColor.blue = 255;//设置颜色的蓝色分量
				palaceColor.alpha = 126;//设置颜色的alpha值
				// 创建一个边框对象
				// 参数 - 5: 边框的线宽
				// 参数 - polygonSymbol.new Color(0xffff0000):边框的颜色
				Stroke stroke = new Stroke(5,polygonSymbol.new Color(0xffff0000))
				palaceSymbol.setSurface(palaceColor,1,3,stroke);//设置样式参数,颜色:palaceColor是否填充距形:是线
				

注:Symbol对象不可复用,要绘制多个图形,需要创建多个Symbol。

第三步:

构建绘图对象:Graphic,通过几何元素(Geometry)和相对应的样式(Symbol)就可以组合成Graphic, Graphic表示SDK可直接用于绘制的一个绘图对象,用户通过操纵Graphic对象向地图添加/移除自绘图形。示例代码如下:

				//创建故宫的Graphic对象
				Graphic palaceGraphic = new Graphic(palaceGeometry, palaceSymbol);
				

注:Graphic对象不可复用,要绘制多个图形,需要创建多个Graphic。

第四步:

GraphicsOverlay:将自绘图形添加到地图中。Graphic对象可通过GraphicsOvelay添加到MapView中。顾名思义,GraphicsOverlay也是一个Overlay , 所以其操作方法与其他覆盖物(如:RouteOverlay , ItemizedOverlay)相同,都可通过MapView.getOverlays() 添加/移除overlay, 通过MapView.refresh() 刷新地图使overlay操作生效。示例代码如下:

				/**
				* 创建一个GraphicsOverlay来装载故宫的Graphic
				* 构造参数mMapView为MapView对象,如果不知道如何生成MapView对象,可参看Hello World章节。
				*/
				GraphicsOverlaypalaceOverlay = new GraphicsOverlay(mMapView);
				/**
				* 向GraphicsOverlay添加Graphic
				*一个GraphicsOVerlay可添加多个Graphic
				*GraphicsOVerlay的remove接口使用setData()返回的ID来移除指定Graphic
				*/
				longpalaceId = palaceOverlay.setData(palaceGraphic);
				//将overlay添加到mapview中
				mMapView.getOverlays().add(palaceOverlay);
				//刷新地图使新添加的overlay生效
				mMapView.refresh();
				//移动,缩放地图到最视野
				mMapView.getController().setZoom(16);
				mMapView.getController().setCenter(palaceCenter);
				

通过几上几个步骤,我们就可以向故宫所围成的矩形添加一层蓝色覆盖物了,自绘图形的更多用法,请参见官网Demo。结果示意图如下:

9.文字绘制图层:TextOverlay

文字绘制的方法与几何图形绘制的方法类似,它也需要几个类的功能支持才能完成最终绘制:

  •    Symbol:样式类,主要负责为所绘制的文字提供颜色属性;
  •  TextItem:文字类,包含文字对齐方式、颜色、字号、绘制位置、字体等基本信息;
  •  TextOverlay:这是一个用于绘制文字的overlay,和其他的各种overlay用法相同。

下面将向大家介绍如何在地图上绘制一段简单的文字:

第一步:定义并初始化两个Symbol.Color对象,用于设置文字的颜色和其背景的颜色;

	Symbol textSymbol = new Symbol();  
	Symbol.Color textColor = textSymbol.new Color();  
	textColor.alpha = 255;  
	textColor.red = 0;  
	textColor.blue = 255;  
	textColor.green = 0;  
	            
	Symbol textSymbol1 = new Symbol();  
	Symbol.Color textColor1 = textSymbol1.new Color();  
	textColor1.alpha = 150;  
	textColor1.red = 80;  
	textColor1.blue = 80;  
	textColor1.green = 80;  

第二步:定义并初始化TextItem对象,用于所绘制文字的基本属性信息;

	TextItem textItem = new TextItem();
	textItem.fontColor = textColor;
	textItem.bgColor = textColor1;
	textItem.fontSize = 30;
	textItem.text = "欢迎使用百度地图SDK!";
	textItem.pt = mapView.getMapCenter();

第三步:定义并初始化TextOverlay,同时把第二步中创建的textItem对象添加到此overlay中;

	TextOverlay textOverlay = new TextOverlay(mapView);  
	textOverlay.addText(textItem);  

第四步:在MapView对象中添加文字图层,并刷新显示;

	mapView.getOverlays().add(textOverlay);  
	mapView.refresh();  

通过以上四步简单的操作,即可完成文字绘制操作。效果如下图所示:

android_dev31.jpg

10.图片图层:GroundOverlay:

利用图片图层,开发者可在地图的指定位置上添加图片。该图片可随地图的平移、缩放、旋转等操作做相应的变换。图片图层是一种特殊的Overlay, 它位于底图和底图标注层之间(即图片图层不会遮挡地图标注信息), 此外,图片图层的添加顺序不会影响其他图层(例如:POI搜索图层、我的位置图层等)的叠加关系。

下面将向大家介绍如何在MapView中添加、删除一个图片图层:

添加图片图层:

1. 初始化图层信息

					
					GroundOverlay mGroundOverlay = new GroundOverlay(mMapView);
					GeoPoint leftBottom = new GeoPoint((int) (mLat5 * 1E6),(int) (mLon5 * 1E6));
					GeoPoint rightTop = new GeoPoint((int) (mLat6 * 1E6),(int) (mLon6 * 1E6));
					Drawable d = getResources().getDrawable(R.drawable.ground_overlay);
					Bitmap bitmap = ((BitmapDrawable) d).getBitmap();
					Ground mGround = new Ground(bitmap, leftBottom, rightTop); 
				

2. 将图片图层添加到地图中

					mMapView.getOverlays().add(mGroundOverlay);
					mGroundOverlay.addGround(mGround);
					mMapView.refresh();
				

删除图片图层:

				mGroundOverlay.removeGround(mGround);
				mMapView.refresh();
				

11.全景图图层:PanoramaOverlay

全景图图层是专门针对全景图功能所建立的覆盖物图层,它支持在全景图内添加自定义的标注。

具体的使用方法请参考全景图章节的介绍。

12.向地图添加自定义View

SDK 的 MapView 继承自系统控件 ViewGroup ,所以可以像往ViewGroup添加子view一样向MapView添加子view. 向MapView添加自定义View 时, 我们需要一个LayoutParam 参数来告诉MapView您想把自定义View添加到MapView的什么地方,构建好LayoutParam后,调用:

				MapView.addView(View myView, MapView.LayoutParam layoutParam);
				

就可以将View添加到MapView 中.

注:

与IteminzedOverlay相比,使用addView()方式添加覆盖物性能较差,不建议使用addView()向MapView 添加大量自定义View.。

MapView.LayoutParam 构造函数说明:

1.使用地理位置坐标布局。

				    public LayoutParams(int width, int height, GeoPoint point, int alignment) 
				

说明:

width: 显示自定义view 的宽度,

height: 显示自定义的view高度,

point: 自定义view将要添加到的位置(使用地理位置坐标表示)

alignment: 对齐方式,表示要view的哪个位置去对齐 point.

alignment可选以下参数:

MapView.LayoutParams.TOP_LEFT: 使用view左上角顶点对齐point.

MapView.LayoutParams.CENTER_HORIZONTAL: 使用view上边中点对齐point.

MapView.LayoutParams.RIGHT : 使用view右上角顶点对齐point.

MapView.LayoutParams.CENTER_VERTICAL : 使用view左边中点对齐point.

MapView.LayoutParams.CENTER : 使用view中心点对齐point.

MapView.LayoutParams.BOTTOM_CENTER : 使用view下边中点对齐point.

2.使用偏移量和地理位置坐标布局.

				public LayoutParams(int width, int height, 
                    GeoPoint point, 
                    int x, 
                    int y,
                    int alignm  )
				

说明:

如果使用构建函数1) 不能满足您的对齐需求,则可以使用此构造函数,用这种方法布局的效果是在1)的效果之上再加一个偏移 (x,y).

3.使用屏幕坐标布局。

				 public LayoutParams(int width, int height, 
                    int x,
                    int y,  
                    int alignment) 
				

说明:

width: 显示自定义view的宽度,

height: 显示自定义view的高度,

x: 对齐点的x坐标,

y: 对齐点的y坐标,

alignment: 对齐方式,表示要view的哪个位置去对齐(x,y), 可选值同1.

示例代码如下:

				//自定义控件        
				 Button button = new Button(this);
				 button.setText("Hello World");
				 GeoPoint pt =new GeoPoint((int)(39.915* 1E6),(int)(116.404* 1E6));
				 //创建布局参数
				 MapView.LayoutParams layoutParam  = new MapView.LayoutParams(
				       //控件宽,继承自ViewGroup.LayoutParams
				       MapView.LayoutParams.WRAP_CONTENT,
				        //控件高,继承自ViewGroup.LayoutParams
				       MapView.LayoutParams.WRAP_CONTENT,
				       //使控件固定在某个地理位置
				        pt,
				       //控件对齐方式
				         MapView.LayoutParams.TOP);
				 //添加View到MapView中
				 mMapView.addView(button,layoutParam);
				

13.如何删除覆盖物?

删除某个Overlay图层,调用以下方法:

					mapView.getOverlays().remove(overlay); 
					// overlay为已经添加到mapView中的Overlay(可以为RouteOverlay,TransitOverlay,ItemizedOverlay,MyLocationOverlay,GraphicsOverlay,TextOverlay)对象
					mapView.refresh(); //2.0.0版本起,清除覆盖物后的刷新仅支持refresh方法
				

清除所有覆盖物:

				mapView.getOverlays().clear();
				mapView.refresh();  //2.0.0版本起,清除覆盖物后的刷新仅支持refresh方法