现在的位置: 首页 > 综合 > 正文

android 百度地图描绘POI

2013年09月16日 ⁄ 综合 ⁄ 共 7430字 ⁄ 字号 评论关闭

 首先还是一贯作风,请大家先看一些图例:


      在上一篇介绍了地图显示自己的位置,在这一篇呢,我简单介绍下在地图如何show出来一系列POI(兴趣点)

      首先我们从服务器拉取要标记POI的信息如(lat,lon,Tag等信息)然后就是根据经纬度创建ItemizedOverlay.这个是用于显示一系列的POI.

     代码片段:

  在onLocationChanged调用:

/***
	 * Location 监听
	 * 
	 * @param arg0
	 */
	@Override
	public void onLocationChanged(Location location) {
		if (location != null) {
			// 获取自己的经纬度点
			GeoPoint geoPoint = new GeoPoint(
					(int) (location.getLatitude() * 1e6),
					(int) (location.getLongitude() * 1e6));
			mMapController.setCenter(geoPoint);

			addItemizedOverlay(geoPoint.getLatitudeE6() / 1e6,
					geoPoint.getLongitudeE6() / 1e6);// 定位一系列点

			// addOverLay(geoPoint);
		}

	}

	/***
	 * 添加一系列的overlay 范围在5000米内
	 * 
	 * @param lat
	 *            纬度
	 * @param lon
	 *            经度
	 */
	void addItemizedOverlay(double lat, double lon) {
		arrayList = new ArrayList<MarkInfo>();
		// 获取服务器返回的一系列点
		ArrayList<MarkInfo> markInfos = Constent.getArrayListPoint();
		for (int i = 0; i < markInfos.size(); i++) {
			MarkInfo markInfo = markInfos.get(i);
			Double dis = MyUtil.getGeoPointDistance(lat, lon, markInfo.lat,
					markInfo.lon);
			if (dis <= distance)
				arrayList.add(markInfo);
		}

		Drawable marker = getResources().getDrawable(R.drawable.item);
		marker.setBounds(0, 0, marker.getIntrinsicWidth(),
				marker.getIntrinsicHeight()); // 为maker定义位置和边界

		overlays = mMapView.getOverlays();
		myItemizedOverlay = new MyItemizedOverlay(marker, this, arrayList);

		myItemizedOverlay.setMapView(mMapView);

		overlays.add(myItemizedOverlay);
		mPopView = createMarkView();// 获取冒泡view
		myItemizedOverlay.setmPopView(mPopView);
		// 将泡泡添加到mMapView上
		mMapView.addView(mPopView, new MapView.LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, null,
				MapView.LayoutParams.WRAP_CONTENT));
		mPopView.setVisibility(View.GONE);
	}

/***
	 * 创建点击mark时的弹出泡泡
	 */

	public View createMarkView() {
		layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mPopView = layoutInflater.inflate(R.layout.popview, null);
		TextView textView = (TextView) mPopView.findViewById(R.id.snippet);
		mPopView.setTag(textView);
		return mPopView;
	}

这里我简单模拟获取服务器的一系列的poi. 并计算自身与这些poi的位置距离,如果小于5000.则显示出来.

在这里说明一下:首先服务器边的处理,不能把所有的poi数据都返回给我们,如果是这样,那么手机就会很耗时会吃不消,不符合移动项目的需求,服务器端:应该对这一系列的poi进行处理,比如根据地区划分开来,如:我传给服务器参数上海浦东,那么只返回给我浦东一系列的poi,这样就解决了这个问题,另外,最好的办法是这段逻辑最好在服务器端,我们请求服务器的参数把距离5000也带过去,返回给我们直接就是要show的poi,这样设计最好了.扯了有点偏了,不过我是初学者,就简单记录下来,如有不妥或着更简单的方法,还请您指示一二,谢谢在先了.

MyItemizedOverlay.java

package com.jj.baidu;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.mapapi.GeoPoint;
import com.baidu.mapapi.ItemizedOverlay;
import com.baidu.mapapi.MapView;
import com.baidu.mapapi.OverlayItem;
import com.baidu.mapapi.Projection;
import com.jj.modle.MarkInfo;

/***
 * 系列覆盖物
 * 
 * @author zhangjia
 * 
 */
public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem> {

	private List<OverlayItem> overlayItems;
	private OverlayItem overlayItem, overlayItem2, overlayItem3, overlayItem4,
			overlayItem5, overlayItem6;

	private Context mContext;
	private Drawable marker;// 覆盖物图标

	private View mPopView = null; // 点击mark时弹出的气泡View

	private MapView mapView;

	private ArrayList<MarkInfo> markInfos;// 一系列经纬度点

	// 注入地图map
	public void setMapView(MapView mapView) {
		this.mapView = mapView;
	}

	// 注入泡泡view
	public void setmPopView(View mPopView) {
		this.mPopView = mPopView;
	}

	public MyItemizedOverlay(Drawable marker, Context context,
			ArrayList<MarkInfo> markInfos) {
		super(boundCenterBottom(marker));
		this.mContext = context;
		this.marker = marker;
		this.markInfos = markInfos;
		overlayItems = new ArrayList<OverlayItem>();
		for (int i = 0; i < markInfos.size(); i++) {
			/***
			 * 第一个参数是GeoPoint,第二个参数是title.通过overlayItem.getTitle()可以获取到,
			 * 第三个参数是Snippet,通过overlayItem.getSnippet()获取到.
			 */
			GeoPoint geoPoint = new GeoPoint(
					(int) (markInfos.get(i).lat * 1e6),
					(int) (markInfos.get(i).lon * 1e6));
			overlayItem = new OverlayItem(geoPoint, i + "",
					markInfos.get(i).Tag);
			overlayItems.add(overlayItem);
		}
		populate(); // createItem(int)方法构造item。一旦有了数据,在调用其它方法前,首先调用这个方法

	}

	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow) {
		// super.draw(canvas, mapView, shadow);

		// Projection接口用于屏幕像素坐标和经纬度坐标之间的变换
		// 这里可以在point旁边draw 一些文字.
		// Projection projection = mapView.getProjection();
		// for (int i = 0; i < overlayItems.size(); i++) {
		// OverlayItem overlayItem = overlayItems.get(i);
		// String title = overlayItem.getTitle();
		// // 把经纬度变换到相对于MapView左上角的屏幕像素坐标
		// Point point = projection.toPixels(overlayItem.getPoint(), null);
		//
		// // 可在此处添加您的绘制代码
		// Paint paintText = new Paint();
		// paintText.setColor(Color.BLUE);
		// paintText.setTextSize(15);
		// canvas.drawText(title, point.x - 30, point.y, paintText); // 绘制文本
		// }

		super.draw(canvas, mapView, shadow);
		// 调整一个drawable边界,使得(0,0)是这个drawable底部最后一行中心的一个像素
		boundCenterBottom(marker);

	}

	@Override
	protected OverlayItem createItem(int position) {
		return overlayItems.get(position);
	}

	@Override
	public int size() {
		return overlayItems.size();
	}

	// 处理当点击事件
	@Override
	protected boolean onTap(final int i) {
		// 获取点击的GeoPoint
		GeoPoint geoPoint = overlayItems.get(i).getPoint();
		// 获取大头针的宽高,
		int x = marker.getIntrinsicHeight();
		int y = marker.getIntrinsicWidth();
		/***
		 * 显示泡泡 参数是要显示的view 水平多少有些偏差,
		 * 
		 * 可以自己进行调整,垂直则让显示在大头针的中间部位即可.即-y/2.
		 */
		mapView.updateViewLayout(mPopView, new MapView.LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, geoPoint,
				-3, -y / 2, MapView.LayoutParams.BOTTOM_CENTER));
		mPopView.setVisibility(View.VISIBLE);
		mapView.getController().animateTo(geoPoint);// 移动到中间
		TextView textView = (TextView) mPopView.getTag();
		textView.setText(overlayItems.get(i).getSnippet());
		mPopView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Toast.makeText(mContext, overlayItems.get(i).getSnippet(), 1)
						.show();

			}
		});

		return super.onTap(i);
	}

}

注释已经很详细,这里不过多介绍.

在这里我简单说明一下:点击地图上的poi标记弹出来的气泡mPopView如何显示.

	mapView.updateViewLayout(mPopView, new MapView.LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, geoPoint,
				-3, -y / 2, MapView.LayoutParams.BOTTOM_CENTER));

第4,5个参数是相对于(geopoint对应屏幕上point的点)来说的.如果不写则表示0,0,则那么mPopView的和poi点将重合,很不友好,你可以测试一下就明白了.因此我们要让mPopView显示在poi的中间,则让mPopView上移(poi的宽度/2)。相信大家都明白的.(你可以看下面运行结果)

在这里我给出如何根据两经纬度点计算之间的距离和方位方法:

public class MyUtil {
	// 地球半径
	private static final double EARTH_RADIUS = 6378137.0;

	/***
	 * 返回 两个GeoPoint之间的距离
	 */
	public static double getGeoPointDistance(double lat_a, double lng_a,
			double lat_b, double lng_b) {
		double radLat1 = (lat_a * Math.PI / 180.0);
		double radLat2 = (lat_b * Math.PI / 180.0);
		double a = radLat1 - radLat2;
		double b = (lng_a - lng_b) * Math.PI / 180.0;
		double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
				+ Math.cos(radLat1) * Math.cos(radLat2)
				* Math.pow(Math.sin(b / 2), 2)));
		s = s * EARTH_RADIUS;
		s = Math.round(s * 10000) / 10000;
		return s;
	}

	/***
	 * 返回 两个GeoPoint之间的方位角
	 */
	public static String getGeoPointCorner(double lat_a, double lng_a,
			double lat_b, double lng_b) {
		double d = 0;
		lat_a = lat_a * Math.PI / 180;
		lng_a = lng_a * Math.PI / 180;
		lat_b = lat_b * Math.PI / 180;
		lng_b = lng_b * Math.PI / 180;

		d = Math.sin(lat_a) * Math.sin(lat_b) + Math.cos(lat_a)
				* Math.cos(lat_b) * Math.cos(lng_b - lng_a);
		d = Math.sqrt(1 - d * d);
		d = Math.cos(lat_b) * Math.sin(lng_b - lng_a) / d;
		d = Math.asin(d) * 180 / Math.PI;

		// d = Math.round(d*10000);
		return d + "";

	}

}

             
   

    自身定位(嘿嘿,有兄弟一起的么)

         

这些数据没有任何联系,我是随便找的,大家可以根据项目需求进行适度调整,

另外点击左下角定位按钮会定位到自身方位.具体实现也很简单,我们直接引用为我们封装了一切的LocationOverLay类,

mMapView.getController().animateTo(locationOverlay.getMyLocation()); 即可.

如果想让箭头跟着自己位置进行移动:

/***
		 * 当位置变化时就会跟进
		 */
		locationOverlay.runOnFirstFix(new Runnable() {
			@Override
			public void run() {
				mMapView.getController().animateTo(
						locationOverlay.getMyLocation());
			}
		});

测试没有问题,不过和百度地图相比逊色不是一点点,移动很不连贯.原因正在研究中,如有知道的朋友请指示一二.

先说道这里,以后慢慢补充添加.


APP应用一般就是这些功能.主要是show一系列的POI.简单说到这里.如有发现会及时更新.

如有问题请留言,Thanks for you 。







     

      

         

【上篇】
【下篇】

抱歉!评论已关闭.