百度地图SDK2.1.1的自定义图标标注

前段时间研究了一下百度地图,看见一些其他的应用在使用百度地图时,地图上的标注物好像都是自己定义的并且带有立体感,所以就自己研究了一些怎样自定义

布局进行地图的标注,比如在地图上标注你的好友,并且将好友的名字在标注物上显示出来,这样就需要进行自定义的标注物,google了很多博客,但是都不是我

想要的效果,他们的自定义都没有自定义自己的布局。下面将自己的做的记录一下。

首先我们知道百度地图的标注物使用的是item.setMarker(draw),这个item是OverlayItem对象,draw是一个Drawable对象。也就是说在百度地图上进行的标注物

必须是Drawable类型的,所以我们就应该去想怎样将一个布局对象转化为Drawable对象,同时布局对象通常都是一个View对象。所以接下来我们就应该思考怎样

将一个View对象转化为一个Drawable对象。这个google一下很容易就找到方法:

可以将View转化成BitMap对象,然后将BItmap对象转化成BitMapDrawable对象就Ok了(因为BitMapDrawable是Drawable的子类)

	view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, 
        		MeasureSpec.UNSPECIFIED));  
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());        
		view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();  
        Bitmap bitmap = view.getDrawingCache();         
        BitmapDrawable draw = new BitmapDrawable(bitmap);
这样就能够将draw在百度地图上进行标注了。

接下来上一个百度地图的小例子:将地图的标注和定位进行了分开,并且定时进行标注,能够手动的进行定位。记得要在AndroidManiFest中添加相关的权限。

public class MapApplication extends Application{

	BMapManager bMapManager;
	public static final String pwd="XX";
	private static MapApplication instance;
	public boolean m_bKeyRight = true;
	@Override
	public void onCreate() {		
		super.onCreate();
		instance = this;
		initMap();
	}
	
	@Override
	public void onTerminate() {
		super.onTerminate();
	}
	
	public void initMap(){
		if(bMapManager==null){
			bMapManager = new BMapManager(getApplicationContext());
		}
		if(!bMapManager.init(pwd,new MyGeneralListener())){
			Toast.makeText(getApplicationContext(), "初始化错误", Toast.LENGTH_SHORT).show();
		}
	}
	
	/** 常用事件监听,用来处理通常的网络错误,授权验证错误等 */
	public static class MyGeneralListener implements MKGeneralListener {
        
        @Override
        public void onGetNetworkState(int iError) {
            if (iError == MKEvent.ERROR_NETWORK_CONNECT) {
                Toast.makeText(MapApplication.instance, "您的网络出错啦!",
                    Toast.LENGTH_LONG).show();
            }
            else if (iError == MKEvent.ERROR_NETWORK_DATA) {
                Toast.makeText(MapApplication.instance, "输入正确的检索条件!",
                        Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onGetPermissionState(int iError) {
            if (iError ==  MKEvent.ERROR_PERMISSION_DENIED) {
                //授权Key错误:
                Toast.makeText(MapApplication.instance, 
                        "百度地图Key失效!", Toast.LENGTH_LONG).show();
                MapApplication.instance.m_bKeyRight = false;
            }
        }
    }
}

首先在Application中进行百度地图的初始化。

public class LayoutLabel implements Runnable{

	ItemizedOverlay<OverlayItem> overlay;
	Drawable marker;
	Context context;
	MapView mapView;
	private double latitude = 23.165281,longitude = 113.425987;
	View view;
	public static volatile boolean isStop = false;
	
	public LayoutLabel(Context context,MapView mapView){
		this.context = context;
		this.mapView = mapView;
		init();
	}
	
	public void init(){
		marker = context.getResources().getDrawable(R.drawable.main_map_icon_nav_check);
		marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker
				.getIntrinsicHeight());
		overlay = new ItemizedOverlay<OverlayItem>(marker, mapView);
		mapView.getOverlays().add(overlay);	
		
		view= (RelativeLayout)LayoutInflater.from(context).inflate(R.layout.picc_worker_location, null);		
		TextView tv = (TextView)view.findViewById(R.id.picc_worker_name);		
		tv.setText("曹操");
		mapView.addView(view);//将子view添加到父容器中,所有的标注物都是mapView上进行标注的。		
		view.setVisibility(View.GONE);		
	}
	
	public void label(){
		overlay.removeAll();
		mapView.refresh();
		
		GeoPoint point = new GeoPoint((int)(latitude*1e6), (int)(longitude* 1e6));
		OverlayItem item = new OverlayItem(point, "MapApplication", null);					
		
		BitmapDrawable draw = getDrawableFromBitmap(getBitmapFromView(view));		
		draw.setBounds(0, 0, draw.getIntrinsicWidth(), draw
				.getIntrinsicHeight());			
		item.setMarker(draw);
		overlay.addItem(item);
		mapView.refresh();
	}
	
	public Bitmap getBitmapFromView(View view) {
		//如果没有将view指定 parent view 那么下面这句则会出现空指针异常
        view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, 
        		MeasureSpec.UNSPECIFIED));  
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());        
		view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();  
        Bitmap bitmap = view.getDrawingCache();         
        return bitmap;       
    }
	
	public BitmapDrawable getDrawableFromBitmap(Bitmap bitmap){		
		BitmapDrawable draw = new BitmapDrawable(Resources.getSystem(), bitmap);
		draw.setBounds(0, 0, draw.getIntrinsicWidth(), draw
				.getIntrinsicHeight());	
		
		return draw;
	}

	@Override
	public void run() {
		while(!isStop){
			label();
			try {
				Thread.sleep(10000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}	
	}	
}
上面的代码是定时进行自定义的地图标注物定位,先将要标注的View添加到mapView上。然后进行上述的转化使用setMarker方法进行定位标注。

public class LayoutView {

	MapView mapView;
	MapController controller;
	Drawable marker;
	Context context;
	ItemizedOverlay<OverlayItem> overlay;
	
	public LayoutView(MapView mapView,Context context){
		this.mapView = mapView;
		this.context = context;
		init();
	}
	
	public void init(){
		controller = mapView.getController();
		GeoPoint point = new GeoPoint((int)(23.165281*1e6), (int)(113.425987* 1e6)); 
		controller.setZoom(14);
		controller.enableClick(true);                                    
		controller.setCenter(point);
		controller.animateTo(point);
		
		marker = context.getResources().getDrawable(R.drawable.main_map_icon_nav_check);
        overlay =new ItemizedOverlay<OverlayItem>(marker, mapView);
        mapView.getOverlays().add(overlay);
        
		mapView.setBuiltInZoomControls(true); 
		mapView.refresh();
	}
	
	public void mapOnClick(GeoPoint pointBaidu){
		if(pointBaidu!=null){					
	        overlay.removeAll();
	        OverlayItem item = new OverlayItem(pointBaidu, null, null);
	        
	        item.setMarker(marker);
	        overlay.addItem(item);
	        mapView.refresh();
	        controller.animateTo(pointBaidu);
		}
	}
}

这个类是将定位和GPS获取进行了分离,进行手动定位时只要初始化这个类,调用其中的方法就能够进行手动定位。

public class LocationMap{
	
	LocationClient mLocClient;
	MapApplication application;
	Context context;
	public static double latitude=23.165281,longitude=113.425987;
	public static GeoPoint point;
	public static BDLocation location;
	
	public LocationMap(Context context){
		this.context = context;
		application = (MapApplication)context.getApplicationContext();
				
		LocationClientOption option = new LocationClientOption();
		option.setOpenGps(true);//打开gps
	    option.setCoorType("bd09ll");//设置坐标类型
        option.setScanSpan(10000);//设置定时获取的时间间隔
        option.disableCache(true);//设置是否要定位缓存
        option.setPriority(LocationClientOption.GpsFirst);//设置定位优先方式
        option.setProdName("MapActivity");//设置应用名字
        
        mLocClient = new LocationClient(context);
        mLocClient.setLocOption(option);
        mLocClient.registerLocationListener(new MyLocationListenner());
        mLocClient.start();
        mLocClient.requestLocation();       
	}
	
    private class MyLocationListenner implements BDLocationListener{
		@Override
		public void onReceiveLocation(BDLocation location) {
			if(location!=null){
				latitude = location.getLatitude();
				longitude = location.getLongitude();
				LocationMap.location = location;
				point = new GeoPoint((int)(location.getLatitude()*1e6), (int)(location.getLongitude()* 1e6));				
			}
		}
		@Override
		public void onReceivePoi(BDLocation location) {
			
		}	
    }
    
	public static double getLatitude() {
		return latitude;
	}

	public static void setLatitude(double latitude) {
		LocationMap.latitude = latitude;
	}

	public static double getLongitude() {
		return longitude;
	}

	public static void setLongitude(double longitude) {
		LocationMap.longitude = longitude;
	}  
}
这个类是使用定位SDK进行GPS的获取。

public class MapActivity extends Activity implements OnClickListener{

	MapView mapView;
	Button btn;
	LayoutView layoutView;
	Thread thread;
	MapApplication application;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		application = (MapApplication)getApplication();
        if (application.bMapManager == null) {
        	application.bMapManager = new BMapManager(this);
        	application.bMapManager.init(MapApplication.pwd, new MapApplication.MyGeneralListener());
        }
		setContentView(R.layout.activity_map);
		
		mapView = (MapView)findViewById(R.id.mapView);
		btn = (Button)findViewById(R.id.request);
		btn.setOnClickListener(this);
	}
	
	@Override
	protected void onStart() {
		new LocationMap(this);
		layoutView = new LayoutView(mapView, this);
		thread = new Thread(new LayoutLabel(this, mapView));
		thread.start();
		super.onStart();
	}
	@Override
	public void onClick(View v){
		GeoPoint point = new GeoPoint((int)(LocationMap.latitude*1e6), (int)(LocationMap.longitude* 1e6)); 
		layoutView.mapOnClick(point);		
	}
	
	@Override
	protected void onDestroy() {
		stopLayoutLabel();
		super.onDestroy();
	}
	
	public void stopLayoutLabel(){
		LayoutLabel.isStop = true;
		thread.interrupt();
		mapView.destroy();
		if (application.bMapManager != null){
			application.bMapManager.destroy();
			application.bMapManager = null;              
        }
	}
}


主Activity进行地图的控件的初始化。

下面看下例子的效果。

百度地图SDK2.1.1的自定义图标标注_第1张图片                     百度地图SDK2.1.1的自定义图标标注_第2张图片

现在只实现了自定义的标注和手动定位,但是怎样对标注物进行立体化,也就是添加阴影还没有找到方法,谁知道留言告知一下,一起进步学习。

这个小例子的下载链接http://download.csdn.net/detail/zkw12358/6688299 注意百度的验证码我去掉了,要运行的话自己去百度地图官网申请一个吧。



你可能感兴趣的:(百度地图SDK2.1.1的自定义图标标注)