在使用地图模块中很多时候我们都需要在地图中使用自定义的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) 第二个参数为距离屏幕周边的留白范围,可以根据自己的需要来进行设置。

希望上面的内容可以帮到诸位,谢谢大家!!!