本章将讲述如何利用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下载地址
http://download.csdn.net/detail/u012552275/9680875
参考文章:
http://blog.csdn.net/lmj623565791/article/details/37737213