还是觉得每章单独建立目录方便,从这章开始吧。
覆盖物是指叠加或覆盖到地图上的内容,覆盖物有自己的地理坐标,将根据地图的移动而移动。
百度地图支持多种类型的覆盖物:
其中PoiOverlay、RouteOverlay等我们在之前已经接触过,下面详细描述。
MapView使用一个List管理覆盖物,通过向MapView.getOverlays() add或remove上述类或其基类的实例即可向地图添加或删除覆盖物。在更新地图覆盖物后,需调用MapView.refresh() 使更新生效。
将MyLocationOverlay添加到覆盖物中,能够实现在地图上显示当前位置的图标以及指南针。具体代码如下:
MyLocationOverlay myLocationOverlay = new MyLocationOverlay( mMapView); LocationData locData = new LocationData(); // 此处模拟位置,可用实际位置替代 locData.latitude = 31.209294; locData.longitude = 121.472471; locData.direction = 300.0f; myLocationOverlay.setData(locData); mMapView.getOverlays().add(myLocationOverlay); mMapView.refresh(); mMapView.getController().animateTo( new GeoPoint((int) (locData.latitude * 1e6), (int) (locData.longitude * 1e6)));
Poi搜索图层的使用可以参照之前的文章:地图检索。
路线图层的使用可以参照之前的文章:路线规划。
请参照路线规划中的公交搜索部分。
2.0.0以前的SDK中是可以直接继承Overlay来实现自定义图层的,但新版的SDK中我们只能通过集成ItemizedOverlay来实现自定义图层功能了。
下面的代码演示了添加自定义图层的功能,百度的这个例子非常好。不过在我的测试手机上很奇怪没能显示title和snippet。
// 准备要添加的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.loc); mark.setBounds(0, 0, mark.getIntrinsicWidth(), mark.getIntrinsicHeight()); // OverlayItem(GeoPoint point, java.lang.String title, java.lang.String snippet) OverlayItem item1 = new OverlayItem(p1,"title1","snippet1"); //使用setMarker()方法设置overlay图片,如果不设置则使用构建ItemizedOverlay时的默认设置 OverlayItem item2 = new OverlayItem(p2,"item2","item2"); item2.setMarker(mark); OverlayItem item3 = new OverlayItem(p3,"item3","item3"); //创建ItemizedOverlay CustomOverlay itemOverlay = new CustomOverlay(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();
CustomOverlay.java代码:
public class CustomOverlay extends ItemizedOverlay<OverlayItem> { public CustomOverlay(Drawable mark,MapView mapView) { super(mark, mapView); } @Override public boolean onTap(GeoPoint p, MapView mapView) { return super.onTap(p, mapView); } /** * 覆盖这个方法去处理一个item上的点击事件。 这可能是对屏幕上item的触摸点击,或者对位于中心且已选定的item的跟踪球点击。默认情况下,什么都不做,返回false * 如果点击事件被处理,返回true;如果想要把这个事件传递给其它overlay,返回false */ @Override protected boolean onTap(int index) { System.out.println("第" + index + "个点被点击"); return super.onTap(index); } }
弹出窗口图层将在地图上显示一个三张图片组成的弹窗,点击三张图片将调用不同的事件处理方法。这里的例子比较简单,准备好图片资源和地理位置后,直接创建一个PopupOverlay对象后调用其showPopup方法即可。
// 创建pop对象,注册点击事件监听接口 PopupOverlay pop = new PopupOverlay(mMapView, new PopupClickListener() { @Override public void onClickedPopup(int index) { // 在此处理pop点击事件,index为点击区域索引,点击区域最多可有三个 Toast.makeText(getApplicationContext(), "这是第" + (index + 1) + "个区域", Toast.LENGTH_SHORT).show(); } }); /** * 准备pop弹窗资源,根据实际情况更改 弹出包含三张图片的窗口,可以传入三张图片、两张图片、一张图片。 * 弹出的窗口,会根据图片的传入顺序,组合成一张图片显示. 点击到不同的图片上时,回调函数会返回当前点击到的图片索引index */ Bitmap[] bmps = new Bitmap[3]; try { bmps[0] = BitmapFactory.decodeStream(getAssets().open( "01.png")); bmps[1] = BitmapFactory.decodeStream(getAssets().open( "02.png")); bmps[2] = BitmapFactory.decodeStream(getAssets().open( "03.jpg")); } 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();
// 创建pop对象,注册点击事件监听接口 PopupOverlay pop = new PopupOverlay(mMapView, new PopupClickListener() { @Override public void onClickedPopup(int index) { Toast.makeText(getApplicationContext(), index, Toast.LENGTH_SHORT).show(); } }); // 弹窗弹出位置 GeoPoint ptTAM = new GeoPoint((int) (39.915 * 1E6), (int) (116.404 * 1E6)); LayoutInflater inflater = LayoutInflater.from(BaiduMapActivity.this); View view = inflater.inflate(R.layout.activity_ui, null); // 弹出pop,隐藏pop pop.showPopup(view, ptTAM, 32); // 隐藏弹窗 // pop.hidePop();
绘制几何图形图层的时候需要使用到下面的几个类:
例子仍然使用SDK自带的例子,我在这里重新梳理了注释,标识了逻辑顺序。
// 移动,缩放地图中心点 mMapView.getController().setZoom(16); // 中心点坐标 GeoPoint palaceCenter = new GeoPoint((int)(39.924 * 1E6),(int)(116.403 * 1E6)); mMapView.getController().setCenter(palaceCenter); /** 第一步,创建轮廓对象Geometry */ //故宫左上角 GeoPoint geoPoint1 = new GeoPoint((int)(39.929 * 1E6),(int)(116.397 * 1E6)); //故宫右下角 GeoPoint geoPoint2 = new GeoPoint((int)(39.920 * 1E6),(int)(116.408 * 1E6)); //创建一个轮廓对象 Geometry palaceGeometry = new Geometry(); // 设置轮廓参数是矩形,还有setCircle/setPoint/setPolygon/setPolyline等方法设置轮廓 palaceGeometry.setEnvelope(geoPoint1, geoPoint2); /** 第二步,创建用于外框及填充的Symbol对象 */ Symbol palaceSymbol = new Symbol();//创建样式 Symbol.Color palaceColor = palaceSymbol.new Color();//创建颜色 palaceColor.red = 0;//设置颜色的红色分量 palaceColor.green = 0;//设置颜色的绿色分量 palaceColor.blue = 255;//设置颜色的蓝色分量 palaceColor.alpha = 126;//设置颜色的alpha值 // 创建一个边框对象 // 参数 - 5: 边框的线宽 // 参数 - polygonSymbol.new Color(0xffff0000):边框的颜色 Stroke stroke = new Stroke(5, palaceSymbol.new Color(0xffff0000)); // public void setSurface(Symbol.Color color, int status, int linewidth, Symbol.Stroke stroke) // 设置面样式 // color - 颜色 // status - 填充状态,0表示不填充,1表示填充 // linewidth - 线宽,当填充状态为填充时线宽无意义 // stroke - 边框 palaceSymbol.setSurface(palaceColor, 1, 3, stroke); /** 第三步,创建Graphic对象 */ Graphic palaceGraphic = new Graphic(palaceGeometry, palaceSymbol); /** 第四步,创建一个GraphicsOverlay来装载故宫的Graphic */ GraphicsOverlay palaceOverlay = new GraphicsOverlay(mMapView); // palaceId可以在后面用来移除该对象。 palaceOverlay.removeGraphic(long graphicID) long palaceId = palaceOverlay.setData(palaceGraphic); // 将overlay添加到mapview中 mMapView.getOverlays().add(palaceOverlay); // 刷新地图使新添加的overlay生效 mMapView.refresh();
文字图层基本上和图形差不多,注意文本对象(TextItem)创建时指定了文字大小,所以不会随地图缩放:
// 注意Symbol是不可重用的,所以对应每一个Symbol.Color对象都需要创建一个Symbol对象。 // 创建文本颜色 Symbol textSymbol = new Symbol(); Symbol.Color textColor = textSymbol.new Color(); textColor.alpha = 255; textColor.red = 0; textColor.blue = 255; textColor.green = 0; // 创建背景颜色 Symbol bgSymbol = new Symbol(); Symbol.Color bgColor = bgSymbol.new Color(); bgColor.alpha = 150; bgColor.red = 80; bgColor.blue = 80; bgColor.green = 80; // 创建文本对象 TextItem textItem = new TextItem(); textItem.fontColor = textColor; textItem.bgColor = bgColor; textItem.fontSize = 30; textItem.text = "欢迎使用百度地图SDK!"; textItem.pt = mMapView.getMapCenter(); // 创建文本图层 TextOverlay textOverlay = new TextOverlay(mMapView); textOverlay.addText(textItem); // 添加图层到地图 mMapView.getOverlays().add(textOverlay); mMapView.refresh();
图片图层可以用来在地图上添加一个图片。图片将会随地图的平移、旋转、缩放做相应的操作。图片图层介于底图和底图标注信息(即图片图层不会遮挡地图标注信息),图片图层添加顺序不影响其他图层的相互关系。
// 新建Ground对象 GeoPoint centerPoint = new GeoPoint((int)(39.924 * 1E6),(int)(116.403 * 1E6)); Drawable d = getResources().getDrawable(R.drawable.liehuo_net_001); Bitmap bitmap = ((BitmapDrawable) d).getBitmap(); Ground mGround = new Ground(bitmap, centerPoint, 5000, 3000); // 新建GroundOverlay对象 GroundOverlay mGroundOverlay = new GroundOverlay(mMapView); mGroundOverlay.addGround(mGround); // 添加图层 mMapView.getOverlays().add(mGroundOverlay); mMapView.refresh();
MapView继承自ViewGroup,所以可以使用addView添加一个View对象,这部分较为简单,使用也较少,暂不介绍。
删除图层可以调用,remove方法中的参数支持任意图层:
mMapView.getOverlays().remove(mGroundOverlay); mMapView.refresh();
mMapView.getOverlays().clear(); mMapView.refresh();