在目前我所开发的几个使用百度地图Android SDK的应用中,需要最多的功能也就是根据一些已知的坐标点信息,显示在百度地图上。从2.0.0版本开始,百度地图Android SDK不支持直接继承Overlay , 用户可通过继承ItemizedOverlay来添加覆盖物。

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

  1. 创建OverlayItem,准备overlay数据;
  2. 继承ItemizedOverlay,至少重写createItem()和 size() 方法。若要处理overlay 点击事件,请重写onTap()方法;
  3. 调用MapView.getOverlays().add()方法添加overlay到mapview中。
  4. 调用MapView.refresh() 使Overlay生效

下面我们来演示如何获取一些坐标点,然后显示在地图上。

新建一个类,命名为ItemizedOverlayActivity并继承Activity,然后在AndroidManifest.xml注册该Activity。

首先还是要先实例化百度地图:

public class ItemizedOverlayActivity extends BaseActivity {

	private MapView mMapView;
	private MapController mMapController;
	private Context context;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		context = this;
		setContentView(R.layout.activity_map);

		initMapView();

		new ShowOverlaysTask().execute();
	}

	//初始化百度地图
	private void initMapView() {
		mMapView = (MapView) findViewById(R.id.bmapsView);
		mMapController = mMapView.getController();
		mMapController.setZoom(14);
	}
}

然后准备需要显示在地图上的覆盖物的坐标信息,实际项目中我们一般都是请求一个api,然后从json或xml中解析出小区信息。这里我们只演示从文件中读取json数据后,然后解析出需要显示在地图上的小区信息。

	//从本地读取json数据
	private String readFile(String filename){
		String str = null;
		try {
		InputStream inStream=getResources().getAssets().open(filename);
		 byte [] buffer=new byte[1024];
		   int len=0;
		   ByteArrayOutputStream outStream=new ByteArrayOutputStream();
		   while((len=inStream.read(buffer))!=-1){
		    outStream.write(buffer, 0, len);
		   }
		   inStream.close();
		   outStream.close();

		   str = outStream.toString();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return str;
	}

然后从json字符串中读取信息DistrictInfo

	/**
	 * 将json字符串转换为DistrictInfo
	 * @param json
	 * @return
	 * @throws Exception
	 */
	private List <DistrictInfo>  parserJson(String json) throws Exception{
		List <DistrictInfo>  districs = new ArrayList <DistrictInfo> ();
		JSONObject x1 = new JSONObject(json);
		String s1 = x1.get("liuzhichao.com").toString();
		JSONObject x2 = new JSONObject(s1);
		String s2 = x2.get("tableSet").toString();
		JSONObject x3 = new JSONObject(s2);
		JSONArray list = x3.getJSONArray("list");

		for(int i=0;i <list.length();i++){
			DistrictInfo info = new DistrictInfo();
			JSONObject obj = list.getJSONObject(i);

			info.setId(obj.getString("projectId"));
			info.setName(obj.getString("name"));
			info.setAddress(obj.getString("address"));
			info.setLat(Double.parseDouble(obj.getString("lat")));
			info.setLng(Double.parseDouble(obj.getString("lng")));

			districs.add(info);
		}

		return districs;
	}

继承ItemizedOverlay,重写createItem()和 size() 方法

//从2.0.0版本开始,SDK不支持直接继承Overlay , 用户可通过继承ItemizedOverlay来添加覆盖物。
	class OverItemT extends ItemizedOverlay <OverlayItem> {

		private List <OverlayItem>  geoList = new ArrayList <OverlayItem> ();

		public OverItemT(Drawable marker,List <DistrictInfo>  districts) {
			super(marker);

			for (DistrictInfo district : districts) {
				double mLat = Double.valueOf(district.getLat());
				double mLng = Double.valueOf(district.getLng());
				GeoPoint point = new GeoPoint((int) (mLat * 1E6),(int) (mLng * 1E6));
				geoList.add(new OverlayItem(point, district.getName(), district.getAddress()));

			}
			populate(); //createItem(int)方法构造item。一旦有了数据,在调用其它方法前,首先调用这个方法
		}

		@Override
		protected OverlayItem createItem(int location) {
			// TODO Auto-generated method stub
			return geoList.get(location);
		}

		@Override
		public int size() {
			// TODO Auto-generated method stub
			return geoList.size();
		}

	}

调用MapView.getOverlays().add()方法添加overlay到mapview中,这里我们用到一个异步类。

/**
	 * 将小区信息显示在地图上的异步类
	 * @author liuzc
	 * @email  liuzc89@gmail.com
	 * @url    http://liuzhichao.com
	 */
	class ShowOverlaysTask extends AsyncTask <Void, Void, List <DistrictInfo> >  {

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
		}

		@Override
		protected List <DistrictInfo>  doInBackground(Void... params) {
			if(mMapView==null) return null;

			try {
				//实际项目中我们一般都是请求一个api,然后从json或xml中解析出小区信息
				//这里演示从文件中读取
				return parserJson(readFile("project.json"));

			} catch (Exception e) {
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(List <DistrictInfo>  districts) {
			if(mMapView==null) return ;

			mMapView.getOverlays().clear();

			if (districts!=null &amp;&amp; districts.size()!=0) {
				Drawable marker = getResources().getDrawable(R.drawable.location_mark);////得到需要标在地图上的资源

				mMapView.getOverlays().add(new OverItemT(marker, districts));

				mMapView.refresh();//刷新地图 sdk2.0之后
				//mMapView.invalidate(); //在sdk2.0之前是调用invalidate方法刷新界面
			}else{
				Toast.makeText(context, "暂无楼盘信息", Toast.LENGTH_LONG).show();
			}
		}
	}

在百度地图SDK2.0之后,需要调用MapView.refresh()使Overlay生效,而不再使用mMapView.invalidate()

这时如果我们运行项目的话,在地图上无法看到添加的覆盖物,这是因为我们地图的中心点仍是默认的,我们需要将地图的中心点设置为添加的覆盖物的附近。在初始化百度地图时,添加如下代码。

//显示当前地图中心点
		GeoPoint point = new GeoPoint((int) ( 22.54423* 1E6),(int) ( 114.05779 * 1E6));
		mMapController.setCenter(point);

		mMapView.refresh();

再次运行项目,可以看到已经正常显示了覆盖物。

baiduMap_ItemizedOverlay
baiduMap_ItemizedOverlay

到目前为止,三个Demo的完整项目文件下载地址:BaiduMapDemo.zip