編輯:關於Android編程
之前講了百度地圖定位和地圖基本操作,這篇博客講一下,怎麼去給地圖添加覆蓋物,並當點擊覆蓋物的時候顯示詳細信息。
要給地圖添加覆蓋物,首先需要覆蓋物的經緯度,如果還要實現點擊事件,顯示詳細的信息,還需要覆蓋物的描述信息(如圖片,位置名稱等),所以先新建一個實體類,來存放這些信息。
實體類必須實現序列化接口
package com.zwinsoft.mybaidumap.entity; import java.io.Serializable; /** * 地圖標注信息實體類 * @author jing__jie * */ public class MarkerInfoUtil implements Serializable{ private static final long serialVersionUID = 8633299996744734593L; private double latitude;//緯度 private double longitude;//經度 private String name;//名字 private int imgId;//圖片 private String description;//描述 //構造方法 public MarkerInfoUtil() {} public MarkerInfoUtil(double latitude, double longitude, String name, int imgId, String description) { super(); this.latitude = latitude; this.longitude = longitude; this.name = name; this.imgId = imgId; this.description = description; } //toString方法 @Override public String toString() { return "MarkerInfoUtil [latitude=" + latitude + ", longitude=" + longitude + ", name=" + name + ", imgId=" + imgId + ", description=" + description + "]"; } //getter setter 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; } public int getImgId() { return imgId; } public void setImgId(int imgId) { this.imgId = imgId; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
在activity中添加幾條markerinfo數據,用來顯示marker
private void setMarkerInfo() {
infos = new ArrayList();
infos.add(new MarkerInfoUtil(117.216624,39.142693,"天津站",R.drawable.tianjinzhan,"天津站,俗稱天津東站,隸屬北京鐵路局管轄"));
infos.add(new MarkerInfoUtil(117.176955,39.111345,"南開大學",R.drawable.nankai,"正式成立於1919年,是由嚴修、張伯苓秉承教育救國理念創辦的綜合性大學。"));
infos.add(new MarkerInfoUtil(117.174081,39.094994,"天津水上公園",R.drawable.shuishang,"天津水上公園原稱青龍潭,1951年7月1日正式對游客開放,有北方的小西子之稱。"));
}
在activity_main.xml中,添加一個按鈕,當點擊的時候顯示marker,再次點擊的時候marker消失。
case R.id.btn_marker:
if(!showMarker){
//顯示marker
addOverlay(infos);
showMarker = true;
}else{
//關閉顯示marker
mBaiduMap.clear();
showMarker = false;
}
break;
//顯示marker
private void addOverlay(List infos2) {
//清空地圖
mBaiduMap.clear();
//創建marker的顯示圖標
BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.ditu1);
LatLng latLng = null;
Marker marker;
OverlayOptions options;
for(MarkerInfoUtil info:infos){
//獲取經緯度
latLng = new LatLng(info.getLatitude(),info.getLongitude());
//設置marker
options = new MarkerOptions()
.position(latLng)//設置位置
.icon(bitmap)//設置圖標樣式
.zIndex(9) // 設置marker所在層級
.draggable(true); // 設置手勢拖拽;
//添加marker
marker = (Marker) mBaiduMap.addOverlay(options);
//使用marker攜帶info信息,當點擊事件的時候可以通過marker獲得info信息
Bundle bundle = new Bundle();
//info必須實現序列化接口
bundle.putSerializable("info", info);
marker.setExtraInfo(bundle);
}
//將地圖顯示在最後一個marker的位置
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
mBaiduMap.setMapStatus(msu);
}
這樣marker就顯示出來了。效果圖:
下面需要添加marker的點擊事件,使marker在點擊的時候,顯示info中的信息。首先需要一個布局用來展示圖片,名稱等信息。
添加marker的點擊事件
//添加marker點擊事件的監聽
mBaiduMap.setOnMarkerClickListener(new OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
//從marker中獲取info信息
Bundle bundle = marker.getExtraInfo();
MarkerInfoUtil infoUtil = (MarkerInfoUtil) bundle.getSerializable("info");
//將信息顯示在界面上
ImageView iv_img = (ImageView)rl_marker.findViewById(R.id.iv_img);
iv_img.setBackgroundResource(infoUtil.getImgId());
TextView tv_name = (TextView)rl_marker.findViewById(R.id.tv_name);
tv_name.setText(infoUtil.getName());
TextView tv_description = (TextView)rl_marker.findViewById(R.id.tv_description);
tv_description.setText(infoUtil.getDescription());
//將布局顯示出來
rl_marker.setVisibility(View.VISIBLE);
return true;
}
});
效果圖:
再添加一個地圖點擊事件,當點擊地圖的時候,將詳細信息布局影藏
//地圖點擊事件
mBaiduMap.setOnMapClickListener(new OnMapClickListener() {
@Override
public boolean onMapPoiClick(MapPoi arg0) {
return false;
}
@Override
public void onMapClick(LatLng arg0) {
rl_marker.setVisibility(View.GONE);
}
});
其中點擊顯示info信息的布局是固定的,有時候我們需要顯示一個infowindow,跟隨在marker上,這就需要百度地圖提供的InfoWindow來實現。
在marker的點擊監聽中添加
//infowindow中的布局
TextView tv = new TextView(MainActivity.this);
tv.setBackgroundResource(R.drawable.infowindow);
tv.setPadding(20, 10, 20, 20);
tv.setGravity(Gravity.CENTER);
tv.setTextColor(android.graphics.Color.WHITE);
tv.setText(infoUtil.getName());
bitmapDescriptor = BitmapDescriptorFactory.fromView(tv);
//infowindow位置
LatLng latLng = new LatLng(infoUtil.getLatitude(), infoUtil.getLongitude());
//infowindow點擊事件
OnInfoWindowClickListener listener = new OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick() {
//隱藏infowindow
mBaiduMap.hideInfoWindow();
}
};
//顯示infowindow,-47是偏移量,使infowindow向上偏移,不會擋住marker
InfoWindow infoWindow = new InfoWindow(bitmapDescriptor, latLng, -47, listener);
mBaiduMap.showInfoWindow(infoWindow);
效果圖:
下面總結一下MainActivity代碼,包含地圖控制(地圖模式控制,地圖縮放控制),地圖定位,帶方向的定位,顯示覆蓋物,顯示覆蓋物點擊事件等,希望大家多多指正。
package com.zwinsoft.mybaidumap;
import java.util.ArrayList;
import java.util.List;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BaiduMap.OnMapClickListener;
import com.baidu.mapapi.map.BaiduMap.OnMapStatusChangeListener;
import com.baidu.mapapi.map.BaiduMap.OnMarkerClickListener;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.InfoWindow;
import com.baidu.mapapi.map.InfoWindow.OnInfoWindowClickListener;
import com.baidu.mapapi.map.MapPoi;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationConfiguration.LocationMode;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.model.LatLng;
import com.zwinsoft.mybaidumap.entity.MarkerInfoUtil;
import com.zwinsoft.mybaidumap.tools.MyOrientationListener;
import com.zwinsoft.mybaidumap.tools.MyOrientationListener.OnOrientationListener;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
/**
* 我的百度地圖首頁
* @author jing__jie
*
*/
public class MainActivity extends Activity implements OnClickListener {
private MapView mMapView = null;
private BaiduMap mBaiduMap;
private ImageButton ib_large,ib_small,ib_mode,ib_loc,ib_traffic,ib_marker;
//模式切換,正常模式
private boolean modeFlag = true;
//當前地圖縮放級別
private float zoomLevel;
//定位相關
private LocationClient mLocationClient;
private MyLocationListener mLocationListener;
//是否第一次定位,如果是第一次定位的話要將自己的位置顯示在地圖 中間
private boolean isFirstLocation = true;
//創建自己的箭頭定位
private BitmapDescriptor bitmapDescriptor;
//經緯度
double mLatitude;
double mLongitude;
//方向傳感器監聽
private MyOrientationListener myOrientationListener;
private float mLastX;
private List infos;
//顯示marker
private boolean showMarker = false;
private RelativeLayout rl_marker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//在使用SDK各組件之前初始化context信息,傳入ApplicationContext
//注意該方法要再setContentView方法之前實現
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
//初始化控件
initView();
//初始化地圖
initMap();
//定位
initLocation();
//創建自己的定位圖標,結合方向傳感器,定位的時候顯示自己的方向
initMyLoc();
//創建marker信息
setMarkerInfo();
}
private void setMarkerInfo() {
infos = new ArrayList();
infos.add(new MarkerInfoUtil(117.216624,39.142693,"天津站",R.drawable.tianjinzhan,"天津站,俗稱天津東站,隸屬北京鐵路局管轄"));
infos.add(new MarkerInfoUtil(117.176955,39.111345,"南開大學",R.drawable.nankai,"正式成立於1919年,是由嚴修、張伯苓秉承教育救國理念創辦的綜合性大學。"));
infos.add(new MarkerInfoUtil(117.174081,39.094994,"天津水上公園",R.drawable.shuishang,"天津水上公園原稱青龍潭,1951年7月1日正式對游客開放,有北方的小西子之稱。"));
}
private void initMyLoc() {
//初始化圖標
bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.arrow);
//方向傳感器監聽
myOrientationListener = new MyOrientationListener(this);
myOrientationListener.setOnOrientationListener(new OnOrientationListener() {
@Override
public void onOrientationChanged(float x) {
mLastX = x;
}
});
}
private void initMap() {
//獲取地圖控件引用
mMapView = (MapView) findViewById(R.id.bmapView);
// 不顯示縮放比例尺
mMapView.showZoomControls(false);
// 不顯示百度地圖Logo
mMapView.removeViewAt(1);
//百度地圖
mBaiduMap = mMapView.getMap();
// 改變地圖狀態
MapStatus mMapStatus = new MapStatus.Builder().zoom(15).build();
MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
mBaiduMap.setMapStatus(mMapStatusUpdate);
//設置地圖狀態改變監聽器
mBaiduMap.setOnMapStatusChangeListener(new OnMapStatusChangeListener() {
@Override
public void onMapStatusChangeStart(MapStatus arg0) {
}
@Override
public void onMapStatusChangeFinish(MapStatus arg0) {
}
@Override
public void onMapStatusChange(MapStatus arg0) {
//當地圖狀態改變的時候,獲取放大級別
zoomLevel = arg0.zoom;
}
});
//地圖點擊事件
mBaiduMap.setOnMapClickListener(new OnMapClickListener() {
@Override
public boolean onMapPoiClick(MapPoi arg0) {
return false;
}
@Override
public void onMapClick(LatLng arg0) {
rl_marker.setVisibility(View.GONE);
}
});
}
private void initLocation() {
//定位客戶端的設置
mLocationClient = new LocationClient(this);
mLocationListener = new MyLocationListener();
//注冊監聽
mLocationClient.registerLocationListener(mLocationListener);
//配置定位
LocationClientOption option = new LocationClientOption();
option.setCoorType("bd09ll");//坐標類型
option.setIsNeedAddress(true);//可選,設置是否需要地址信息,默認不需要
option.setOpenGps(true);//打開Gps
option.setScanSpan(1000);//1000毫秒定位一次
option.setIsNeedLocationPoiList(true);//可選,默認false,設置是否需要POI結果,可以在BDLocation.getPoiList裡得到
mLocationClient.setLocOption(option);
}
private void initView() {
//地圖控制按鈕
ib_large = (ImageButton)findViewById(R.id.ib_large);
ib_large.setOnClickListener(this);
ib_small = (ImageButton)findViewById(R.id.ib_small);
ib_small.setOnClickListener(this);
ib_mode = (ImageButton)findViewById(R.id.ib_mode);
ib_mode.setOnClickListener(this);
ib_loc = (ImageButton)findViewById(R.id.ib_loc);
ib_loc.setOnClickListener(this);
ib_traffic = (ImageButton)findViewById(R.id.ib_traffic);
ib_traffic.setOnClickListener(this);
ib_marker = (ImageButton)findViewById(R.id.ib_marker);
ib_marker.setOnClickListener(this);
rl_marker = (RelativeLayout)findViewById(R.id.rl_marker);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ib_large:
if (zoomLevel < 18) {
mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomIn());
ib_small.setEnabled(true);
} else {
showInfo("已經放至最大,可繼續滑動操作");
ib_large.setEnabled(false);
}
break;
case R.id.ib_small:
if (zoomLevel > 6) {
mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomOut());
ib_large.setEnabled(true);
} else {
ib_small.setEnabled(false);
showInfo("已經縮至最小,可繼續滑動操作");
}
break;
case R.id.ib_mode://衛星模式和普通模式
if(modeFlag){
modeFlag = false;
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
showInfo("開啟衛星模式");
}else{
modeFlag = true;
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
showInfo("開啟普通模式");
}
break;
case R.id.ib_loc:
isFirstLocation = true;
showInfo("返回自己位置");
break;
case R.id.ib_traffic://是否開啟交通圖
if(mBaiduMap.isTrafficEnabled()){
mBaiduMap.setTrafficEnabled(false);
ib_traffic.setBackgroundResource(R.drawable.offtraffic);
showInfo("關閉實時交通圖");
}else{
mBaiduMap.setTrafficEnabled(true);
ib_traffic.setBackgroundResource(R.drawable.ontraffic);
showInfo("開啟實時交通圖");
}
break;
case R.id.ib_marker:
if(!showMarker){
//顯示marker
showInfo("顯示覆蓋物");
addOverlay(infos);
showMarker = true;
ib_marker.setBackgroundResource(R.drawable.ditu4);
}else{
//關閉顯示marker
showInfo("關閉覆蓋物");
mBaiduMap.clear();
showMarker = false;
ib_marker.setBackgroundResource(R.drawable.ditu3);
}
break;
default:
break;
}
}
//顯示marker
private void addOverlay(List infos) {
//清空地圖
mBaiduMap.clear();
//創建marker的顯示圖標
BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.ditu1);
LatLng latLng = null;
Marker marker;
OverlayOptions options;
for(MarkerInfoUtil info:infos){
//獲取經緯度
latLng = new LatLng(info.getLatitude(),info.getLongitude());
//設置marker
options = new MarkerOptions()
.position(latLng)//設置位置
.icon(bitmap)//設置圖標樣式
.zIndex(9) // 設置marker所在層級
.draggable(true); // 設置手勢拖拽;
//添加marker
marker = (Marker) mBaiduMap.addOverlay(options);
//使用marker攜帶info信息,當點擊事件的時候可以通過marker獲得info信息
Bundle bundle = new Bundle();
//info必須實現序列化接口
bundle.putSerializable("info", info);
marker.setExtraInfo(bundle);
}
//將地圖顯示在最後一個marker的位置
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
mBaiduMap.setMapStatus(msu);
//添加marker點擊事件的監聽
mBaiduMap.setOnMarkerClickListener(new OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
//從marker中獲取info信息
Bundle bundle = marker.getExtraInfo();
MarkerInfoUtil infoUtil = (MarkerInfoUtil) bundle.getSerializable("info");
//將信息顯示在界面上
ImageView iv_img = (ImageView)rl_marker.findViewById(R.id.iv_img);
iv_img.setBackgroundResource(infoUtil.getImgId());
TextView tv_name = (TextView)rl_marker.findViewById(R.id.tv_name);
tv_name.setText(infoUtil.getName());
TextView tv_description = (TextView)rl_marker.findViewById(R.id.tv_description);
tv_description.setText(infoUtil.getDescription());
//將布局顯示出來
rl_marker.setVisibility(View.VISIBLE);
//infowindow中的布局
TextView tv = new TextView(MainActivity.this);
tv.setBackgroundResource(R.drawable.infowindow);
tv.setPadding(20, 10, 20, 20);
tv.setTextColor(android.graphics.Color.WHITE);
tv.setText(infoUtil.getName());
tv.setGravity(Gravity.CENTER);
bitmapDescriptor = BitmapDescriptorFactory.fromView(tv);
//infowindow位置
LatLng latLng = new LatLng(infoUtil.getLatitude(), infoUtil.getLongitude());
//infowindow點擊事件
OnInfoWindowClickListener listener = new OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick() {
//隱藏infowindow
mBaiduMap.hideInfoWindow();
}
};
//顯示infowindow
InfoWindow infoWindow = new InfoWindow(bitmapDescriptor, latLng, -47, listener);
mBaiduMap.showInfoWindow(infoWindow);
return true;
}
});
}
//自定義的定位監聽
private class MyLocationListener implements BDLocationListener{
@Override
public void onReceiveLocation(BDLocation location) {
//將獲取的location信息給百度map
MyLocationData data = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此處設置開發者獲取到的方向信息,順時針0-360
.direction(mLastX)
.latitude(location.getLatitude())
.longitude(location.getLongitude())
.build();
mBaiduMap.setMyLocationData(data);
//更新經緯度
mLatitude = location.getLatitude();
mLongitude = location.getLongitude();
//配置定位圖層顯示方式,使用自己的定位圖標
MyLocationConfiguration configuration = new MyLocationConfiguration(LocationMode.NORMAL, true, bitmapDescriptor);
mBaiduMap.setMyLocationConfigeration(configuration);
if(isFirstLocation){
//獲取經緯度
LatLng ll = new LatLng(location.getLatitude(),location.getLongitude());
MapStatusUpdate status = MapStatusUpdateFactory.newLatLng(ll);
//mBaiduMap.setMapStatus(status);//直接到中間
mBaiduMap.animateMapStatus(status);//動畫的方式到中間
isFirstLocation = false;
showInfo("位置:" + location.getAddrStr());
}
}
}
@Override
protected void onStart() {
super.onStart();
//開啟定位
mBaiduMap.setMyLocationEnabled(true);
if(!mLocationClient.isStarted()){
mLocationClient.start();
}
//開啟方向傳感器
myOrientationListener.start();
}
@Override
protected void onStop() {
super.onStop();
//關閉定位
mBaiduMap.setMyLocationEnabled(false);
if(mLocationClient.isStarted()){
mLocationClient.stop();
}
//關閉方向傳感器
myOrientationListener.stop();
}
@Override
protected void onDestroy() {
super.onDestroy();
//在activity執行onDestroy時執行mMapView.onDestroy(),實現地圖生命周期管理
mMapView.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
//在activity執行onResume時執行mMapView. onResume (),實現地圖生命周期管理
mMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
//在activity執行onPause時執行mMapView. onPause (),實現地圖生命周期管理
mMapView.onPause();
}
//顯示消息
private void showInfo(String str){
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
}
吸引用戶的眼球,是我們至死不渝的追求;第一時間呈現最有價值的信息,簡明大方,告訴客戶,你的選擇是多麼的明智,這正是你尋覓已久的東西。分組的應用場合還是很多的,有數據集合的
android最後一個組件便是service了,終於學習到最後一個組件了,從年前的開發環境的搭建,到現在學到最後一個組件花了三周的時間,期間記錄的點點滴滴,照著書本學習編
寫在前面的話 在上一篇實現了通過布局泵拿到不同布局為listitem布局,然後實現聯系人的ListView,這一章要做的是拖拽ListView的Item項,本章原理是在上
最近總感覺寫博客的激情不高,不知道為啥。放上效果圖,demo在最下面圖上那個切換按鈕的作用呢,就是模擬改變標簽的個數動態變化整個控件的高度。其實這個控件也算很簡單的控件了