Android 百度地圖最新SDK v3.2.0和Android定位SDK:v5.0應用(3)

上一篇中,已經實現了對地圖的一些基本的簡單操作,現在要實現以下幾個功能:

a 在百度地圖中間實現一個固定不動的View,類似快的打車軟件地圖中中間固定不動的View;

b 在地圖中間固定不動的View上添加PopupWindow,實現隨着地圖移動,即時顯示當前的位置信息;

c 在百度地圖上添加覆蓋物Marker與InfoWindow的點擊事件,這裏分別用3種不同的方式實現;

功能就這麼點,開始代碼實現:


1.在百度地圖中間實現一個固定不動的View,類似快的打車軟件地圖中中間固定不動的CenterIcon


CenterIcon.java

public class CenterIcon extends View {

    public static int w;
    public static int h;
    public static Bitmap mBitmap;
    public static MapView mMapView;

    public CenterIcon(Context context,MapView mMapView) {

        super(context);
        // 設置屏幕中心的圖標
        mBitmap = BitmapFactory.decodeResource(getResources(),
                R.drawable.current_position);
        
        this.mMapView = mMapView;
    }

    @Override
    protected void onDraw(Canvas canvas) {

   super.onDraw(canvas);
        // 獲取屏幕中心的座標
        w = mMapView.getWidth() / 2 - mBitmap.getWidth() / 2;
        h = mMapView.getHeight() / 2 ;
        canvas.drawBitmap(mBitmap, w, h, null);
    }

}

說明:CenterIcon繼承View,在屏幕中心畫出來,然後在BaseMapActivity中添加以下代碼

// 初始化屏幕中心
		CenterIcon centerIcon = new CenterIcon(this, mMapView);
		getWindow().addContentView(
				centerIcon,
				new LayoutParams(LayoutParams.WRAP_CONTENT,
						LayoutParams.WRAP_CONTENT));


這樣就實現了在地圖中間(屏幕)有了一個固定不動的CenterIcon了。

2.在地圖中間固定不動的 CenterIcon上添加PopupWindow,實現隨着地圖移動,即時顯示當前的位置信息


a 初始化中間彈出窗:
/**
	 * 初始化中間彈出窗
	 */
	public void initCenterAddrPop() {

		centerInflater = (LayoutInflater) getApplicationContext()
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		centerPopView = centerInflater.inflate(R.layout.pop_map_centure, null,
				false);
		centerPopWindow = new PopupWindow(centerPopView,
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, false);
		// popwindow外面可touch
		centerPopWindow.setOutsideTouchable(true);
		// 獲取兩個textview
		locationNameTextView = (TextView) centerPopView
				.findViewById(R.id.locationName);
		locationTipsTextView = (TextView) centerPopView
				.findViewById(R.id.locationTips);

	}

說明:pop_map_centure.xml 是我們自定義的佈局,用來顯示當前位置的地理信息。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pop_home_layout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:background="@drawable/location_tips"
    android:gravity="center_vertical"
    android:maxWidth="1000.0dip"
    android:minWidth="40.0dip"
    android:orientation="horizontal" >

    <LinearLayout
        android:layout_width="0dip"
        android:layout_height="wrap_content"
        android:layout_weight="4"
        android:gravity="left|center_vertical"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/locationName"
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:text="浙江省杭州市餘杭區餘杭區倉前街道"
            android:textColor="#adadad"
            android:textSize="13sp" />

        <TextView
            android:id="@+id/locationTips"
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:text="浙江省杭州市餘杭區餘杭區倉前街道"
            android:textColor="#adadad"
            android:textSize="11sp" />
    </LinearLayout>

    <ImageView
        android:layout_width="18dp"
        android:layout_height="18dp"
        android:layout_margin="8dp"
        android:background="@drawable/location_expand"
        android:contentDescription="定位" />

</LinearLayout>

b 顯示中間彈出窗,當然,我們需要實現百度地圖移動別的時候顯示它。

/**
	 * 顯示中間彈出窗
	 */
	public void showCenterAddrPop(Double latitude, Double longitude,
			String name, String address) {

		if (name == null || name.length() == 0) {
			locationNameTextView.setVisibility(View.GONE);
		} else {
			locationNameTextView.setVisibility(View.VISIBLE);
			locationNameTextView.setText(name);
		}
		locationTipsTextView.setText(address);
		// 設置中心彈出框顯示位置

		// centerPopWindow.showAtLocation(callShopToSwitchButton,
		// Gravity.CENTER,
		// 0, -CenterIcon.mBitmap.getHeight());

		centerPopWindow.showAtLocation(mMapView, Gravity.CENTER, 0,
				-CenterIcon.mBitmap.getHeight());

	}

c 百度地圖狀態改變監聽函數setOnMapStatusChangeListener。

// 百度地圖狀態改變監聽函數
		mBaiduMap.setOnMapStatusChangeListener(new OnMapStatusChangeListener() {
			@Override
			public void onMapStatusChangeStart(MapStatus status) {
				// updateMapState(status);
			}

			@Override
			public void onMapStatusChangeFinish(MapStatus status) {
				updateMapState(status);
			}

			@Override
			public void onMapStatusChange(MapStatus status) {
				// updateMapState(status);
			}
		});


 在地圖狀態改變完成onMapStatusChangeFinish的函數中實現updateMapState(status)。

private void updateMapState(MapStatus status) {
		LatLng mCenterLatLng = status.target;
		/** 獲取經緯度 */
		myCentureLatitude = mCenterLatLng.latitude;
		myCentureLongitude = mCenterLatLng.longitude;

		LatLng ptCenter = new LatLng(myCentureLatitude, myCentureLongitude);
		mSearch.reverseGeoCode(new ReverseGeoCodeOption().location(ptCenter));

	}

這裏實現OnGetGeoCoderResultListener(地理編碼/反地理編碼結果)接口,重寫反地理編碼查詢結果回調函數:void onGetReverseGeoCodeResult(ReverseGeoCodeResult result),調用上面的showCenterAddrPop,就可以實現及時的顯示屏幕中心的位置信息了。

@Override
	public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
		if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
			T.showLong(getApplicationContext(), "抱歉,未能找到結果");
			return;
		}
		showCenterAddrPop(myCentureLatitude, myCentureLongitude,
				result.getBusinessCircle(), result.getAddress());

	}

這是我們實現的效果圖(Android5.0.1親測):



3.在百度地圖上添加添加覆蓋物Marker與InfoWindow的點擊事件,這裏分別用3種不同的方式實現


a 先定義幾個地理位置信息,這裏方便演示,直接寫死了,在實際項目中,換一下即可。
OverlayInfo.java

public class OverlayInfo implements Serializable   {

	 private double latitude;  
	 private double longitude;  
	 private String  name;
	 
	 public static List<OverlayInfo> infos = new ArrayList<OverlayInfo>();  
	 
	 static {
		 infos.add(new OverlayInfo(120.141306, 30.258157, "酒店"));
		 infos.add(new OverlayInfo(120.2000, 30.250057, "商場"));
		 infos.add(new OverlayInfo(120.221306, 30.2598157, "西湖"));
		 infos.add(new OverlayInfo(120.165000, 30.250007, "美食街"));
	 }
	 
	 
	 
	public OverlayInfo(double longitude,double latitude, String name) {
		super();
		this.latitude = latitude;
		this.longitude = longitude;
		this.name = name;
	}
	public double getLatitude() {
		return latitude;
	}
	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}
	public double getLongitude() {
		return longitude;
	}
	public void setLongitude(double longitude) {
		this.longitude = longitude;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}  
	 
	 
}

b 覆蓋物Marker彈出InfoWindow的佈局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:background="@drawable/location_tips"
    android:orientation="horizontal" >

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/icon_location" />

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="杭州"
        android:textColor="#6B6B6B"
        android:textSize="13sp" />

</LinearLayout>

就是簡單的定義了一張圖片和一行文字信息。

c 初始化百度地圖上的覆蓋物Marker。
/**
	 * 初始化覆蓋物Marker
	 */
	public void addInfosOverlay() {
		// mBaiduMap.clear();
		LatLng latLng = null;
		OverlayOptions overlayOptions = null;
		Marker marker = null;
		for (OverlayInfo ovinfo : OverlayInfo.infos) {
			// 位置
			latLng = new LatLng(ovinfo.getLatitude(), ovinfo.getLongitude());
			L.i(TAG, "ovinfo.getLatitude():" + ovinfo.getLatitude()
					+ "ovinfo.getLongitude():" + ovinfo.getLongitude());
			// 圖標
			overlayOptions = new MarkerOptions().position(latLng)
					.icon(mIconMaker).zIndex(5);
			marker = (Marker) (mBaiduMap.addOverlay(overlayOptions));
			Bundle bundle = new Bundle();
			bundle.putSerializable("Overlayinfo", ovinfo);
			marker.setExtraInfo(bundle);
		}

	}

d 對百度地圖上的Marker添加點擊時間,彈出InfoWindow。
// 對Marker的點擊
		mBaiduMap.setOnMarkerClickListener(new OnMarkerClickListener() {
			@Override
			public boolean onMarkerClick(Marker marker) {

			//	return setInfoWindowClickOne(marker);
			//	return setInfoWindowClickTwo(marker);
				return setInfoWindowClickThree(marker);

			}

		});

說明:這裏分別用了3種方式實現,前兩種是對InfoWindow自定義了佈局文件,第三種只是簡單設置了button.setBackgroundResource(R.drawable.popup);

第一種: 通過傳入的 bitmap descriptor 構造一個InfoWindow。使用BitmapDescriptorFactory.fromView(View view),根據一個 View 創建 Bitmap 描述信息, 當 view 爲 null 時返回 null。
public InfoWindow(BitmapDescriptor bd,
          LatLng position,
          int yOffset,
          InfoWindow.OnInfoWindowClickListener listener)
通過傳入的 bitmap descriptor 構造一個 InfoWindow。
參數:
bd - InfoWindow 展示的bitmap
position - InfoWindow 顯示的地理位置
yOffset - InfoWindow Y 軸偏移量
listener - InfoWindow 點擊監聽者

public boolean setInfoWindowClickOne(Marker marker) {
		// 第一種: 通過傳入的 bitmap descriptor 構造一個
		// InfoWindow。使用BitmapDescriptorFactory.fromView(View view),根據一個 View 創建
		// Bitmap 描述信息, 當 view 爲 null 時返回 null

		/*
		 * public InfoWindow(BitmapDescriptor bd, LatLng position, int yOffset,
		 * InfoWindow.OnInfoWindowClickListener listener) 參數: bd - InfoWindow
		 * 展示的bitmap position - InfoWindow 顯示的地理位置 yOffset - InfoWindow Y 軸偏移量
		 * listener - InfoWindow 點擊監聽者
		 */

		final OverlayInfo ovinfo = (OverlayInfo) marker.getExtraInfo().get(
				"Overlayinfo");
		LayoutInflater pointInflater = (LayoutInflater) getApplicationContext()
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View pointPopView = pointInflater.inflate(R.layout.pop_map_maker, null,
				false);

		TextView tv_name = (TextView) pointPopView.findViewById(R.id.tv_name);
		tv_name.setText(ovinfo.getName());

		BitmapDescriptor bd = BitmapDescriptorFactory.fromView(pointPopView);
		// 將marker所在的經緯度的信息轉化成屏幕上的座標
		final LatLng ll = marker.getPosition();
		Projection mProjection = mBaiduMap.getProjection();
		if (mProjection == null) {
			return false;
		}

		Point p = mBaiduMap.getProjection().toScreenLocation(ll);
		L.i(TAG, "p.x=" + p.x);
		L.i(TAG, "p.y=" + p.y);
		p.y -= 47;
		LatLng llInfo = mBaiduMap.getProjection().fromScreenLocation(p);
		// 爲彈出的InfoWindow添加點擊事件
		InfoWindow pointWindow = new InfoWindow(bd, llInfo, -47,
				new InfoWindow.OnInfoWindowClickListener() {
					@Override
					public void onInfoWindowClick() {
						// 隱藏InfoWindow
						// mBaiduMap.hideInfoWindow();
						T.showLong(getApplicationContext(), ovinfo.getName());

					}

				});
		mBaiduMap.showInfoWindow(pointWindow);

		return true;
	}

第二種:直接給View設置點擊事件
使用
public InfoWindow(View view,
          LatLng position,
          int yOffset)
通過傳入的 view 構造一個 InfoWindow, 此時只是利用該view生成一個Bitmap繪製在地圖中。
參數:
view - InfoWindow 展示的 view
position - InfoWindow 顯示的地理位置
yOffset - InfoWindow Y 軸偏移量

public boolean setInfoWindowClickTwo(Marker marker) {
		// 第二種:
		/*
		 * public InfoWindow(View view, LatLng position, int yOffset)通過傳入的 view
		 * 構造一個 InfoWindow, 此時只是利用該view生成一個Bitmap繪製在地圖中。 直接給View設置點擊事件
		 */
		final OverlayInfo ovinfo = (OverlayInfo) marker.getExtraInfo().get(
				"Overlayinfo");
		LayoutInflater pointInflater = (LayoutInflater) getApplicationContext()
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View pointPopView = pointInflater.inflate(R.layout.pop_map_maker, null,
				false);
		pointPopView.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				T.showLong(getApplicationContext(), ovinfo.getName());

			}
		});
		TextView tv_name = (TextView) pointPopView.findViewById(R.id.tv_name);
		tv_name.setText(ovinfo.getName());

		BitmapDescriptor bd = BitmapDescriptorFactory.fromView(pointPopView);
		// 將marker所在的經緯度的信息轉化成屏幕上的座標
		final LatLng ll = marker.getPosition();
		Projection mProjection = mBaiduMap.getProjection();
		if (mProjection == null) {
			return false;
		}

		Point p = mBaiduMap.getProjection().toScreenLocation(ll);
		L.i(TAG, "p.x=" + p.x);
		L.i(TAG, "p.y=" + p.y);
		p.y -= 47;
		LatLng llInfo = mBaiduMap.getProjection().fromScreenLocation(p);
		// 構造InfoWindow
		InfoWindow pointWindow = new InfoWindow(pointPopView, llInfo, -47);
		// 顯示InfoWindow
		mBaiduMap.showInfoWindow(pointWindow);

		return true;
	}

第三種 這種不能自定義彈出的InfoWindow佈局

public boolean setInfoWindowClickThree(Marker marker) {
		// 第三種:這種不能自定義彈出的InfoWindow佈局
		final OverlayInfo ovinfo = (OverlayInfo) marker.getExtraInfo().get(
				"Overlayinfo");
		Button button = new Button(getApplicationContext());
		button.setBackgroundResource(R.drawable.popup);
		button.setText(ovinfo.getName());
		final LatLng ll = marker.getPosition();
		Projection mProjection = mBaiduMap.getProjection();
		if (mProjection == null) {
			return false;
		}
		BitmapDescriptor bd = BitmapDescriptorFactory.fromView(button);
		Point p = mBaiduMap.getProjection().toScreenLocation(ll);
		L.i(TAG, "p.x=" + p.x);
		L.i(TAG, "p.y=" + p.y);
		p.y -= 47;
		LatLng llInfo = mBaiduMap.getProjection().fromScreenLocation(p);
		InfoWindow pointWindow = new InfoWindow(bd, llInfo, -47,
				new InfoWindow.OnInfoWindowClickListener() {
					@Override
					public void onInfoWindowClick() {
						// 隱藏InfoWindow
						// mBaiduMap.hideInfoWindow();
						T.showLong(getApplicationContext(), ovinfo.getName());

					}

				});
		mBaiduMap.showInfoWindow(pointWindow);

		return true;

	}

e 地圖單擊事件,隱藏彈出InfoWindow

	mBaiduMap.setOnMapClickListener(new OnMapClickListener() {

			@Override
			public boolean onMapPoiClick(MapPoi arg0) {
				// TODO Auto-generated method stub
				return false;
			}

			@Override
			public void onMapClick(LatLng arg0) {
				mBaiduMap.hideInfoWindow();

			}
		});

最後看一下彈出的InfoWindow點擊效果



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章