在使用地图模块中很多时候我们都需要在地图中使用自定义的Marker,并且自定义点击弹出框事件,下面我将带大家一起来看如何在地图中进行Marker的添加和使用。
1、首先我们先初始化需要的参数对象。
MapView planDetailMap;
//自定义窗体
private View infoWindow = null;
private HashMap<Integer, Marker> markers = new HashMap<>();
private AMap aMap;
2、进行地图模块的初始化执行在onCreate()方法里面,
planDetailMap.onCreate(savedInstanceState);
if (aMap == null) {
aMap = planDetailMap.getMap();
}
//设置地图缩放
aMap.moveCamera(CameraUpdateFactory.zoomTo(12));
//设置缩放按钮不显示
aMap.getUiSettings().setZoomControlsEnabled(false);
//设置自定义信息窗口
aMap.setInfoWindowAdapter(this);
在这个有个设置地图Camera的方法
aMap.moveCamera(),这个方法的话没有动画效果,如果需要动画效果可以使用,这个方法有3种
aMap.animateCamera(CameraUpdate cameraUpdate);
或者
aMap.animateCamera(CameraUpdateFactory.zoomTo(12), new AMap.CancelableCallback() {
@Override
public void onFinish() {
//移动完成的操作
}
@Override
public void onCancel() {
//取消移动的操作
}
});
一般情况下第一种就能满足我们的业务需要,不需要设置回调函数。
设置完初始化参数之后我们开始设置自定义的Marker。
/**
* 给地图设置marker标签
* @param barName
* @param latLng
* @Author: zxb
* @CreateDate 2020-7-31 17:59
*/
public void setMarker(int barName, LatLng latLng){
String[] cityNameList = cityName.split(","); //这个是不同布局需要显示的数据
LayoutInflater mInflater = LayoutInflater.from(this);
//自定的布局文件
View view = mInflater.inflate(R.layout.item_map, null);
TextView textView = view.findViewById(R.id.num);
RelativeLayout rl_map = view.findViewById(R.id.rl_map);
LinearLayout layout_city = view.findViewById(R.id.layout_city);
TextView info_window = view.findViewById(R.id.info_window);
//我们这里根据不同的参数只显示不同的布局,这里是将布局写在一个文件中,也可以分开
if(isEmpty){
rl_map.setVisibility(View.GONE);
layout_city.setVisibility(View.VISIBLE);
info_window.setText(cityNameList[barName-1]);
}else{
textView.setText(barName+"");
rl_map.setVisibility(View.VISIBLE);
layout_city.setVisibility(View.GONE);
}
Bitmap bitmap =convertViewToBitmap(view);
//绘制marker,将marker添加在地图控件中
Marker marker = aMap.addMarker(new MarkerOptions()
.position(latLng)
.icon(BitmapDescriptorFactory.fromBitmap(bitmap))
.title(barName + "").anchor((float) 0.5,(float) 0.5)
.draggable(false));
markers.put(barName,marker); //将merker放入集合中,以便方便进行其他操作
}
/**
* @Author: zxb
* @CreateDate: 2020-7-31 14:59
* @Description: 将View转化成Bitmap
* @param view
* @return
*/
public static Bitmap convertViewToBitmap(View view) {
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
return bitmap;
}
这里面我们通过convertViewToBitmap(view) 这个方法将布局文件转化成bitmap 放进入.icon(BitmapDescriptorFactory.fromBitmap(bitmap))方法中,其实还有很多其他的方法可以使用
//传入的是bitmap对象
BitmapDescriptorFactory.fromBitmap(bitmap);
//传入的是file对象
BitmapDescriptorFactory.fromFile(file);
//传入的是View对象
BitmapDescriptorFactory.fromView(view);
...
还有很多,我们在使用时可以参考api进行设置,这里不多说了。这里还有个anchor 参数,这个参数用户设置marker的旋转,marker默认是在坐标中点上方显示,设置x,y方向上移动的百分比。设置anchor((float) 0.5,(float) 0.5) 刚好使marker中点和坐标点重合。
3、marker添加之后我们可以设置marker的点击效果,弹出窗体。在初始化的时候我们设置了aMap.setInfoWindowAdapter(this)方法,这个是自定义窗体的实现方法我们重写字方法。getInfoWindow(Marker marker);
//此方法返回的是窗体的view对象
@Override
public View getInfoWindow(Marker marker) {
if (infoWindow == null) {
//根据判断可以弹出不同类型的窗体
if(isEmpty){
infoWindow = LayoutInflater.from(this).inflate(R.layout.amap_info_window, null);
}else{
infoWindow = LayoutInflater.from(this).inflate(R.layout.custom_map_popup, null);
}
}
render(marker, infoWindow);
return infoWindow;
}
@Override
public View getInfoContents(Marker marker) {
return null;
}
/**
* 自定义infoWindow窗口
*/
private void render(Marker marker, View infoWindow) {
if(isEmpty){
}else {
ImageView img = infoWindow.findViewById(R.id.img_pop_poiimg);
LinearLayout imgClose = infoWindow.findViewById(R.id.layout_close);
TextView title = infoWindow.findViewById(R.id.tv_pop_poiname);
Button btnDetail = infoWindow.findViewById(R.id.btn_pop_poiright);
String num = marker.getTitle();
int index = Integer.valueOf(num);
PlanDetailBean bean = clientDetailsList.get(index - 1);
GlideManager.loadImg(PlanDetailBean.getImg(bean), img, R.drawable.lbt);
title.setText(PlanDetailBean.getSpotName(bean));
imgClose.setOnClickListener(v -> {
marker.hideInfoWindow();
});
btnDetail.setOnClickListener(v -> {
Bundle bundle = new Bundle();
bundle.putInt("id", bean.getTravelPlanTypeId());
bundle.putInt("type", bean.getTravelPlanType());
if (bean.getTravelPlanType() == 0) {
FastUtil.startActivity(mContext, AttractionsDetailAcitvity.class, bundle);
} else {
FastUtil.startActivity(mContext, OtherDetailAcitvity.class, bundle);
}
});
}
}
在我们需要直接弹出marker时可以使用marker.showInfoWindow();直接弹出窗体,也可以使用marker.hideInfoWindow();来进行窗体的关闭事件。
至此自定义marker的事件就全部完成了,在有的时候我们需要添加很多的marker,这个时候有的marker可能无法完全在地图中展示出来,这时候我们可以使用 LatLngBounds.Builder 这个对象来操作,让所有的marker 都可以显示在视野范围内,调用newbounds.include(latLng)将点加入,地图会根据设置来进行自适应缩放。在使用aMap.moveCamera(CameraUpdateFactory.newLatLngBounds(newbounds.build(),
100));//第二个参数为四周留空宽度. 来将点移到屏幕中心。
// ①构建 LatLngBounds 对象
LatLngBounds.Builder newbounds = LatLngBounds.builder();
/** ②
*通过遍历 ,将需要显示在视野范围内的点添加进入newbounds 中,
*调用 newbounds.include(latLng);
*/
for(int i = 0; i< clientDetailsList.size(); i++){
PlanDetailBean bean = clientDetailsList.get(i);
latLng = PlanDetailBean.getLocation(bean);
latLngs.add(latLng);
setMarker((i+1), latLng);
newbounds.include(latLng);
}
//③ 在移动Camera中,将构建的点移到需要的位置
if(clientDetailsList.size()>1){
aMap.moveCamera(CameraUpdateFactory.newLatLngBounds(newbounds.build(),
100));//第二个参数为四周留空宽度.
}else{
aMap.moveCamera(CameraUpdateFactory.changeLatLng(latLngs.get(selectPosition)));
}
其中CameraUpdateFactory.newLatLngBounds(newbounds.build(),100) 第二个参数为距离屏幕周边的留白范围,可以根据自己的需要来进行设置。
希望上面的内容可以帮到诸位,谢谢大家!!!