百度地圖4.1_1開發教程(3)Marker
阿新 • • 發佈:2019-02-08
本章將講述如何利用Marker在地圖生成點,並實現點選Marker彈出該點對應的資訊。
1.點選點獲取座標
2.在我的專案裡,會將地圖上的一些飛機作為Marker,點選並彈出該飛機對應的詳情
3.點選地圖其他區域,將清除所有飛機類的marker
4.地圖的觸控,單擊等監聽
最終效果圖如下:(實際專案中,請注意美觀)
獲取座標
首先,在佈局加上顯示座標的控制元件,這裡用一個textView來顯示
<TextView
android:id="@+id/activity_main_tv_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:hint="點選顯示當前地理詳情"/>
接下來在類裡呼叫API:
//地圖觸控事件
mBaiduMap.setOnMapTouchListener(new BaiduMap.OnMapTouchListener()
{
@Override
public void onTouch (MotionEvent motionEvent)
{
}
});
// 地圖單擊事件
mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener()
{
@Override
public void onMapClick(LatLng latLng)
{
currentPt = latLng;
updateMapState();
}
@Override
public boolean onMapPoiClick(MapPoi mapPoi)
{
if (tv_detail.getText() == null || "".equals(tv_detail.getText()))
{
}
currentPt = mapPoi.getPosition();
updateMapState();
return false;
}
});
/**
* 更新地圖狀態顯示面板
*/
private void updateMapState()
{
if (tv_detail == null)
{
return;
}
String state = "";
if (currentPt == null)
{
state = "點選、長按、雙擊地圖以獲取經緯度和地圖狀態";
} else
{
state = String.format("當前經度: %f 當前緯度:%f",
currentPt.longitude, currentPt.latitude);
}
state += "\n";
MapStatus ms = mBaiduMap.getMapStatus();
state += String.format(
"zoom=%.1f rotate=%d overlook=%d",
ms.zoom, (int) ms.rotate, (int) ms.overlook);
tv_detail.setText(state);
}
至此,獲取地圖的座標就完成了。
## 顯示Marker、地圖觸控事件、移除Marker等 ##
接下來,我們實現一個稍微複雜的功能,如圖上底部所示,點選SwitchCompat,動態在地圖上顯示一堆點(marker),點選marker,展現該點的詳細資訊
在佈局加入:
<LinearLayout
android:id="@+id/activity_main_ll_bottomlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:showDividers="middle">
<android.support.v7.widget.SwitchCompat
android:id="@+id/activity_main_sc_marker"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/colorPrimary"
android:padding="10dp"
android:text="一堆點"
android:textColor="@android:color/white"
android:textOff="-.-"
android:textOn="^.^"
toggle:showText="true"/>
</LinearLayout>
<!-- 飛機資訊 -->
<LinearLayout
android:id="@+id/activity_main_flightinfo_ll_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:animateLayoutChanges="true"
android:background="@android:color/white"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical"
android:padding="10dp"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="@+id/activity_main_flightinfo_tv_num"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="飛機編號:"
android:textSize="18sp"/>
<TextView
android:id="@+id/activity_main_flightinfo_tv_model"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="飛機型號"
android:textSize="18sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="@+id/activity_main_flightinfo_tv_startPlace"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="出發地:"
android:textSize="18sp"/>
<TextView
android:id="@+id/activity_main_flightinfo_tv_endPlace"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="抵達地:"
android:textSize="18sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="@+id/pop_window_flight_info_tv_startTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="出發時間:"
android:textSize="18sp"/>
<TextView
android:id="@+id/pop_window_flight_info_tv_endTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="抵達時間:"
android:textSize="18sp"/>
</LinearLayout>
</LinearLayout>
飛機詳情資訊此時是隱藏的,只有在單機到marker的時候才顯示出來。
接下來,顯示飛機資訊一定要有實體類。新建MarkerInfo:
注:省略Getter and Setter方法,請自行生成,或拷貝文章末尾的Demo
// 飛機編號
private String num;
// 飛機型號
private String model;
// 出發地
private String startPlace;
// 抵達地
private String endPlace;
// 出發時間
private String startTime;
// 抵達時間
private String endTime;
// 緯度
private double latitude;
// 經度
private double longitude;
public static List<MarkerInfo> mMarkerInfos= new ArrayList<>();; // 飛機資訊列表
public MarkerInfo()
{
}
public MarkerInfo( String num, String model, String startPlace, String endPlace,
String startTime, String endTime , double latitude, double longitude)
{
super();
this.num = num;
this.model = model;
this.startPlace = startPlace;
this.endPlace = endPlace;
this.startTime = startTime;
this.endTime = endTime;
this.latitude = latitude;
this.longitude = longitude;
}
static // 模擬資料,在地圖上新增3個marker,所對應的資料
{
mMarkerInfos.add(new MarkerInfo( "bh101", "model1", "北京", "天津", "10:00", "11:00",
39.963175, 116.400244 ));
mMarkerInfos.add(new MarkerInfo( "bh102", "model2", "北京", "石家莊", "10:00", "11:30",
39.963175, 116.400244 ));
mMarkerInfos.add(new MarkerInfo( "bh103", "model3", "北京", "呼和浩特", "10:00", "12:00",
39.963175, 116.400244 ));
}
public String getNum()
{
return num;
}
下面準備工作結束
在類裡申明控制元件和findViewById,此處省略若干行程式碼
接下來申明
// 報告點
private List<Marker> markerList; // 飛機點列表
private Marker mMarker; // 飛機點
private BitmapDescriptor marker_flight;
private InfoWindow mInfoWindow;
list存放我們的marker,如果不用list,將來移除的marker只能是一個點,而不是所有,因此,新增和移除都需要遍歷
sc_marker.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if(isChecked)
{
if (markerList == null) // 如果markerList為空,說明此時沒有生成報告點
{
addFlightInfo(MarkerInfo.mMarkerInfos); // 新增報告點的方法
}
} else
{
if (markerList != null)
{
for (int i = 0; i < markerList.size(); i++)
{
markerList.get(i).remove();
}
markerList = null;
}
}
}
});
為開關控制元件新增監聽,當選中狀態的時候,如果列表沒有marker,則走新增marker的方法,在取消狀態的時候,僅當list不為空的時候,才去移除marker,在移除結束後,將list置為空是我自己的寫法以防意外發生。如果你邏輯比較強認為這裡不需要加,也可以。
接下來看一下新增 marker的方法:
/**
* 新增飛機資訊
*
* @param flightInfos
*/
private void addFlightInfo(List<MarkerInfo> flightInfos)
{
LatLng latlng = null;
OverlayOptions overlayOptions = null;
markerList = new ArrayList<>();
marker_flight = BitmapDescriptorFactory
.fromResource(R.mipmap.ic_flight); // 飛機圖示
for (MarkerInfo infos : flightInfos)
{
latlng = new LatLng(infos.getLatitude(), infos.getLongitude()); // 經緯度
overlayOptions = new MarkerOptions().position(latlng).icon(marker_flight).zIndex(9).animateType(MarkerOptions.MarkerAnimateType.grow);
mMarker = (Marker) (mBaiduMap.addOverlay(overlayOptions));
Bundle bundle = new Bundle();
bundle.putSerializable("info", infos);
mMarker.setExtraInfo(bundle);
markerList.add(mMarker);
}
// 將地圖移動到最後一個經緯度位置
MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(latlng);
mBaiduMap.setMapStatus(u);
}
我們在呼叫方法的時候,把MarkerInfo裡的模擬資料載入進來,在迴圈中將對應的經緯度取出來,放在latlng物件中,在new MarkerOptions的時候,將座標傳了進去,並設定了飛機圖示、marker所在層級、生長動畫,最後使用mBaiduMap的addOverlay方法,新增marker,最後,使用bundle物件將infos的內容儲存到了marker中。這樣,就生成了一堆飛機點。
接下來,我們看一下點選時間:
// mark事件監聽
mBaiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener()
{
@Override
public boolean onMarkerClick(Marker marker)
{
MarkerInfo info = (MarkerInfo) marker.getExtraInfo().get("info");
InfoWindow.OnInfoWindowClickListener listener = null;
TextView text = new TextView(getApplicationContext());
text.setBackgroundResource(R.mipmap.location_tips);
text.setPadding(30, 30, 30, 30);
text.setTextColor(getResources().getColor(android.R.color.white));
text.setText(info.getNum());
// 將marker所在的經緯度的資訊轉化成螢幕上的座標
LatLng ll = marker.getPosition();
listener = new InfoWindow.OnInfoWindowClickListener()
{
@Override
public void onInfoWindowClick()
{
mBaiduMap.hideInfoWindow();
}
};
mInfoWindow = new InfoWindow(BitmapDescriptorFactory.fromView(text), ll, -47, listener);
// 設定詳細資訊到佈局
setInfoToLayout(ll_info, info);
ll_info.setVisibility(View.VISIBLE); // 顯示飛機詳情佈局
mBaiduMap.showInfoWindow(mInfoWindow); // 顯示彈窗
return true;
}
});
首先,marker.getExtraInfo().get("info")取得了marker對應的資料,這裡我們動態添加了一個TextView,顯示飛機的型號。,在listener中,如果點選到了彈出的textView,就讓它消失,最後,setInfoToLayout()來將bundle裡的資料顯示到詳情佈局中,並設為可見狀態,最後showInfoWindow顯示出來,就基本完成了。下面看一下setInfoToLayout(ll_info, info);方法:
/**
* 為佈局新增飛機詳情資訊
*
* @param ll_info
* @param info
*/
private void setInfoToLayout(LinearLayout ll_info, MarkerInfo info)
{
ViewHolder viewHolder = null;
if (ll_info.getTag() == null)
{
viewHolder = new ViewHolder();
viewHolder.tv_num = (TextView) ll_info.findViewById(R.id.activity_main_flightinfo_tv_num);
viewHolder.tv_model = (TextView) ll_info.findViewById(R.id.activity_main_flightinfo_tv_model);
viewHolder.tv_startPlace = (TextView) ll_info.findViewById(R.id.activity_main_flightinfo_tv_startPlace);
viewHolder.tv_endPlace = (TextView) ll_info.findViewById(R.id.activity_main_flightinfo_tv_endPlace);
viewHolder.tv_startTime = (TextView) ll_info.findViewById(R.id.pop_window_flight_info_tv_startTime);
viewHolder.tv_endTime = (TextView) ll_info.findViewById(R.id.pop_window_flight_info_tv_endTime);
ll_info.setTag(viewHolder);
}
viewHolder = (ViewHolder) ll_info.getTag();
viewHolder.tv_num.setText("飛機編號:" + info.getNum());
viewHolder.tv_model.setText("飛機型號:" + info.getModel());
viewHolder.tv_startPlace.setText("出發地:" + info.getStartPlace());
viewHolder.tv_endPlace.setText("抵達地:" + info.getEndPlace());
viewHolder.tv_startTime.setText("出發時間:" + info.getStartTime());
viewHolder.tv_endTime.setText("抵達時間:" + info.getEndTime());
}
private class ViewHolder
{
TextView tv_num, tv_model, tv_startPlace, tv_endPlace, tv_startTime, tv_endTime;
}
至此,功能就實現了,但是每次彈出詳情只能點選TextView才能消失,感覺這樣做體驗不太舒服,因此,可以在地圖的觸控時間加入對應的事件:
//地圖觸控事件
mBaiduMap.setOnMapTouchListener(new BaiduMap.OnMapTouchListener()
{
@Override
public void onTouch(MotionEvent motionEvent)
{
ll_info.setVisibility(View.GONE);
mBaiduMap.hideInfoWindow();
}
});
ok,到此已經完成了本章的內容。如果有幫到你,請點贊。有疑問的可以留言,我會抽時間幫忙解決。
Demo下載地址
參考文章: