【高德地图】Android高德地图绘制标记点Marker

2024-06-04 2647阅读

📖第4章 Android高德地图绘制标记点Marker

      • ✅绘制默认 Marker
      • ✅绘制多个Marker
      • ✅绘制自定义 Marker
      • ✅Marker点击事件
      • ✅Marker动画效果
      • ✅Marker拖拽事件
      • ✅绘制默认 Infowindow
        • 🚩隐藏InfoWindow 弹框
        • ✅绘制自定义 InfoWindow
          • 🚩实现 InfoWindow 样式和内容
          • 🚩可触发的 InfoWindow 事件
          • 🚩自定义复杂的 InfoWindow

            ✅绘制默认 Marker

            效果如下图:

            【高德地图】Android高德地图绘制标记点Marker 第1张

            通过aMap.addMarker()来添加标记点marker,而经纬度等信息需要通过MarkerOptions来设置,示例代码如下:

             //marker标记物
            LatLng latLng = new LatLng(31.042119,121.410428);
             final Marker marker = aMap.addMarker(new MarkerOptions().position(latLng).title("测试地点").snippet("这里是测试内容"));
            

            Marker 常用属性

            名称说明
            position在地图上标记位置的经纬度值。必填参数
            title点标记的标题
            snippet点标记的内容
            draggable点标记是否可拖拽
            visible点标记是否可见
            anchor点标记的锚点
            alpha点的透明度

            anchor锚点可以精确控制标记图标相对于标记点(经纬度)的位置,以满足不同场景下的需求。比如您可能希望将锚点设置为标记图标的其他部分,例如顶部中心或左侧中心。默认锚点位置是底部中心

            anchor(0.0f, 0.5f); // 左侧中心
            anchor(1.0f, 0.5f); // 右部中心
            anchor(1.0f, 1.0f); // 底部右侧
            anchor(0.5f, 0.0f); // 顶部中心
            

            alpha透明度是用来表示对象的可见度或不透明度的属性。应用场景:

            1. 标记动画:实现标记的淡入淡出效果,以改善用户体验
            // 创建标记并设置透明度为0.5
            MarkerOptions markerOptions = new MarkerOptions()
                    .position(new LatLng(latitude, longitude))
                    .icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_icon))
                    .alpha(0.5f); // 设置透明度为0.5
            Marker marker = aMap.addMarker(markerOptions);
            // 在动画中逐渐将透明度变为1.0
            ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(marker, "alpha", 0.5f, 1.0f);
            alphaAnimator.setDuration(1000);
            alphaAnimator.start();
            
            1. 突出显示标记: 在一组标记中突出显示特定的标记,可以使目标标记更加显眼。
            // 创建多个标记
            MarkerOptions targetMarkerOptions = new MarkerOptions()
                    .position(new LatLng(targetLatitude, targetLongitude))
                    .icon(BitmapDescriptorFactory.fromResource(R.drawable.target_marker_icon))
                    .alpha(1.0f); // 目标标记的透明度为1.0
            Marker targetMarker = aMap.addMarker(targetMarkerOptions);
            MarkerOptions otherMarkerOptions = new MarkerOptions()
                    .position(new LatLng(otherLatitude, otherLongitude))
                    .icon(BitmapDescriptorFactory.fromResource(R.drawable.other_marker_icon))
                    .alpha(0.5f); // 其他标记的透明度为0.5
            Marker otherMarker = aMap.addMarker(otherMarkerOptions);
            
            1. 动态显示与隐藏:将透明度设置为0.0时,标记将完全不可见,而设置为1.0时,则完全可见。
            // 创建标记并设置透明度为0.0,标记开始时不可见
            MarkerOptions markerOptions = new MarkerOptions()
                    .position(new LatLng(latitude, longitude))
                    .icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_icon))
                    .alpha(0.0f); // 设置透明度为0.0
            Marker marker = aMap.addMarker(markerOptions);
            // 在动画中逐渐将透明度变为1.0,标记逐渐变得可见
            ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(marker, "alpha", 0.0f, 1.0f);
            alphaAnimator.setDuration(1000);
            alphaAnimator.start();
            

            ✅绘制多个Marker

            效果如下图:

            【高德地图】Android高德地图绘制标记点Marker 第2张

            不管是创建默认的Marker还是自定义的Marker都一样,都是通过MarkerOptions设置Marker的信息,再通过aMap.addMarker(markerOption)在地图上添加。

            示例代码如下:

                    //样本数据
                    List positon = new ArrayList();
                    positon.add(new LatLng(31.041742,121.411517));
                    positon.add(new LatLng(31.041370,121.411699));
                    positon.add(new LatLng(31.041563,121.412198));
                    //绘制自定义marker
                    MarkerOptions options = new MarkerOptions();
                    for (int i = 0; i  
            

            ✅绘制自定义 Marker

            效果如下图:

            【高德地图】Android高德地图绘制标记点Marker 第3张

            绘制自定义 Marker的自定义icon图标是通过BitmapDescriptorFactory来处理,它能将图标资源文件转换成位图(Bitmap)对象,以便在地图上使用。示例代码如下:

                    //绘制自定义marker
                    LatLng latLng2 = new LatLng(31.041991,121.409628);
                    MarkerOptions markerOption = new MarkerOptions();
                    markerOption.position(latLng2);
                    markerOption.title("测试2").snippet("我是自定义marker");
                    markerOption.draggable(true);//设置Marker可拖动
                    markerOption.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory
                            .decodeResource(getResources(),R.drawable.icon_marker_orange)));
                    markerOption.setFlat(false);//设置marker平贴地图效果
                    aMap.addMarker(markerOption);
            

            至于icon图标可以在阿里巴巴矢量图标库里面下载png格式的图片即可。

            🚩扩展:在自定义的marker中绘制文字等其他信息

            应用场景:需要在地图上看见该标记点中的数据信息,可以是姓名简称,数字等信息。 效果如下图:

            【高德地图】Android高德地图绘制标记点Marker 第4张

            一共两个步骤:

            • 绘制带文本的图片,格式为BitmapDescriptor类型
            • 在地图上添加标记点
                      //绘制自定义带文字的marker
                      BitmapDescriptor withDataIcon = drawIcon(R.drawable.icon_marker_orange, "李", Color.WHITE);
                      LatLng latLng2 = new LatLng(31.041991,121.409628);
                      MarkerOptions markerOption = new MarkerOptions();
                      markerOption.position(latLng2);
                      markerOption.title("测试").snippet("我是携带数据的marker");
                      markerOption.draggable(true);//设置Marker可拖动
                      markerOption.icon(withDataIcon);
                      markerOption.setFlat(false);//设置marker平贴地图效果
                      aMap.addMarker(markerOption);
              

              drawIcon方法如下:

                  /**
                   * 绘制带文字的marker
                   * @param markerStyle 图片资源
                   * @param text        文字
                   * @param textColor   文字颜色
                   * @return
                   */
                  private BitmapDescriptor drawIcon(int markerStyle, String text, int textColor) {
                      Bitmap bitmap = null;
                      BitmapDescriptor icon = null;
                      try {
                          bitmap = BitmapFactory.decodeResource(getResources(), markerStyle);//图片转bitmap位图
                          int markerStyleWidth = bitmap.getWidth();//获取bitmap位图的宽
                          int markerStyleHeight = bitmap.getHeight();//获取bitmap位图的高
                          Bitmap mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);//复制Bitmap对象
                          Canvas canvas = new Canvas(mutableBitmap); //创建Canvas对象
                          Paint paint = new Paint();//创建Paint对象,用于定义绘制文本的样式
                          paint.setColor(textColor);//设置文字颜色
                          paint.setTextSize(getResources().getDimensionPixelSize(R.dimen.text_size));//设置文字大小
                          //获取文本边界
                          Rect textBounds = new Rect();
                          paint.getTextBounds(text, 0, text.length(), textBounds);
                          int textWidth = textBounds.width();//文本宽度
                          int textHeight = textBounds.height();//文本高度
                          //计算文字在图片上的坐标,使其在图片居中位置
                          float x = (markerStyleWidth - textWidth) / 2.0f;//x表示绘制文本起始点的横坐标,从左开始
                          float y = (markerStyleHeight + textHeight) / 2.0f - 20;//x表示绘制文本起始点的纵坐标,从顶部开始
                          canvas.drawText(text, x, y, paint); //使用Canvas绘制文本
                          icon = BitmapDescriptorFactory.fromBitmap(mutableBitmap);// 最后将Bitmap 转换为 BitmapDescriptor
                          return icon;
                      } finally {
                          if (bitmap != null){
                              bitmap.recycle();
                          }
                          if (icon != null){
                              icon.recycle();
                          }
                      }
                  }
              

              注意:

              • Bitmap和BitmapDescriptor是一个占用内存的对象,需要及时回收以防止内存泄漏。虽然Java有垃圾回收机制,但它是在适当的时机,例如在内存紧张或空闲时,扫描不再被引用的对象并将其释放,在某些情况下,手动释放资源仍然是一个良好的习惯。
              • R.dimen.text_size是在values文件下的dimens.xml资源文件中定义的,如果你没有则创建一个并添加下面代码。
                    14sp
                
                

                ✅Marker点击事件

                点击 Marker 时会回调AMap.OnMarkerClickListener,监听器的实现示例如下:

                 //设置marker点击事件
                 aMap.setOnMarkerClickListener(this);
                

                重写onMarkerClick方法

                    /**
                     * marker 点击监听事件
                     * 返回 true 则表示接口已响应事件,否则返回false
                     * @param marker
                     * @return
                     */
                    @Override
                    public boolean onMarkerClick(Marker marker) {
                        return false;
                    }
                

                ✅Marker动画效果

                将动画效果放在点击marker时可以更好看到变化,自地图 SDK V4.0.0 版本起,SDK 提供了给 Marker 设置动画的方法,具体实现方法如下:

                    /**
                     * marker 点击监听事件
                     * 返回 true 则表示接口已响应事件,否则返回false
                     * @param marker
                     * @return
                     */
                    @Override
                    public boolean onMarkerClick(Marker marker) {
                        //180度旋转动画
                        Animation animation = new RotateAnimation(marker.getRotateAngle(),marker.getRotateAngle()+180,0,0,0);
                        long duration = 1000L;
                        animation.setDuration(duration);
                        animation.setInterpolator(new LinearInterpolator());
                        marker.setAnimation(animation);
                        marker.startAnimation();
                        return false;
                    }
                

                ✅Marker拖拽事件

                拖拽 Marker 时会回调AMap.OnMarkerDragListener,监听器的实现示例如下:

                //设置marker拖拽监听事件
                 aMap.setOnMarkerDragListener(this);
                
                    /**
                     * 当marker开始被拖动时回调此方法, 这个marker的位置可以通过getPosition()方法返回。
                     * @param marker
                     */
                    @Override
                    public void onMarkerDragStart(Marker marker) {
                        Log.d("MainActivity", "Start: "+marker.getPosition());
                    }
                    /**
                     *  在marker拖动过程中回调此方法, 这个marker的位置可以通过getPosition()方法返回。
                     * @param marker
                     */
                    @Override
                    public void onMarkerDrag(Marker marker) {
                        Log.d("MainActivity", "Drag: "+marker.getPosition());
                    }
                    /**
                     * 在marker拖动完成后回调此方法, 这个marker的位置可以通过getPosition()方法返回。
                     * @param marker
                     */
                    @Override
                    public void onMarkerDragEnd(Marker marker) {
                        Log.d("MainActivity", "End: "+marker.getPosition());
                    }
                

                【高德地图】Android高德地图绘制标记点Marker 第5张

                ✅绘制默认 Infowindow

                默认 Infowindow是不用创建的,当我们创建marker时自带有的,SDK 为用户提供了默认的 InfoWindow 样式,只显示 Marker 对象的两个属性,一个是 title 和另一个 snippet。

                调用 Marker 类的 showInfoWindow() 和 hideInfoWindow() 方法可以控制显示和隐藏。

                当改变 Marker 的 title 和 snippet 属性时,再次调用 showInfoWindow(),可以更新 InfoWindow 显示内容。

                【高德地图】Android高德地图绘制标记点Marker 第6张

                🚩隐藏InfoWindow 弹框

                在什么时候去隐藏InfoWindow 弹框,一般情况可以在点击map地图的其他地方关闭它,实现方式如下:

                • 首先设置marker和map点击监听事件
                  //设置marker点击事件
                  aMap.setOnMarkerClickListener(this);
                  //地图点击监听事件
                  aMap.setOnMapClickListener(this);
                  
                  • 然后在marker点击事件中记录当前点击的marker和Infowindow是否弹框的布尔值
                     private Marker current;//记录当前点击的marker
                    private boolean isMarkerClicked = false;//判断是否Infowindow弹框
                    @Override
                        public boolean onMarkerClick(Marker marker) {
                            current = marker;
                            isMarkerClicked = true;
                            return false;
                        }
                    
                    • 最后在onMapClick地图点击事件中隐藏Infowindow弹框
                          /**
                           * map地图点击监听事件
                           */
                          @Override
                          public void onMapClick(LatLng latLng) {
                              if (!isMarkerClicked) {
                                  if (current != null && current.isInfoWindowShown()) {
                                      current.hideInfoWindow();//隐藏当前Infowindow弹框
                                  }
                              }
                              isMarkerClicked = false; // 重置标记状态
                          }
                      

                      ✅绘制自定义 InfoWindow

                      实现 InfoWindowAdapter接口,其中有两个方法需要实现,依次来看一下:

                      public interface InfoWindowAdapter {
                              View getInfoWindow(Marker marker);
                              View getInfoContents(Marker marker);
                      }
                      

                      View getInfoWindow(Marker marker)

                      • 当实现此方法并返回有效值时(返回值不为空,则视为有效),SDK 将不会使用默认的样式,而采用此方法返回的样式(即 View)。默认会将Marker 的 title 和 snippet 显示到 InfoWindow 中。
                      • 如果此时修改了 Marker 的 title 或者 snippet 内容,再次调用类 Marker 的 showInfoWindow() 方法,InfoWindow 内容不会更新。
                      • 自定义 InfoWindow 之后所有的内容更新都需要用户自己完成。
                      • 当调用 Marker 类的 showInfoWindow() 方法时,SDK 会调用 getInfoWindow(Marker marker) 方法和 getInfoContents(Marker marker) 方法(之后会提到),在这些方法中更新 InfoWindow 的内容即可。

                        注意:如果此方法返回的 View 没有设置 InfoWindow 背景图,SDK 会默认添加一个背景图。

                        View getInfoContents(Marker marker)

                        此方法和 getInfoWindow(Marker marker) 方法的实质是一样的,唯一的区别是:

                        • 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框。

                          简而言之,getInfoContents(Marker marker) 只允许你自定义 InfoWindow 的内容,而不能改变整个窗口的外观和边框。SDK 会在你自定义的内容外面添加一个默认的边框。这可能是为了确保 InfoWindow 在地图上有一致的外观,以保持用户体验的统一性。如果你希望完全自定义整个 InfoWindow 的外观,包括边框,那么应该使用 getInfoWindow(Marker marker) 方法。

                          🚩实现 InfoWindow 样式和内容

                          【高德地图】Android高德地图绘制标记点Marker 第7张

                          实现 InfoWindow 样式和内容的步骤如下:

                          • 设置InfoWindow适配器
                          • 在getInfoWindow返回一个自定义View组件 = R.layout.custom_info_window。
                            implements AMap.InfoWindowAdapter//实现接口
                             aMap.setInfoWindowAdapter(this);//设置InfoWindow适配器
                            

                            实现getInfoWindow和getInfoContents方法

                                View infoWindow = null;
                                @Override
                                public View getInfoWindow(Marker marker) {
                                    if (infoWindow == null) {
                                        infoWindow = LayoutInflater.from(this).inflate(R.layout.custom_info_window, null);
                                    }
                                    render(marker, infoWindow);
                                    return infoWindow;
                                }
                                @Override
                                public View getInfoContents(Marker marker) {
                                    return null;
                                }
                                public void render(Marker marker, View view) {
                                    //如果想修改自定义Infow中内容,请通过view找到它并修改
                                    String title = marker.getTitle();
                                    TextView titleUi = view.findViewById(R.id.title);
                                    titleUi.setText(title);
                                    String snippet = marker.getSnippet();
                                    TextView snippetUi = view.findViewById(R.id.snippet);
                                    snippetUi.setText(snippet);
                                }
                            

                            R.layout.custom_info_window组件:

                            
                                
                                
                            
                            
                            🚩可触发的 InfoWindow 事件

                            点击 InfoWindow 时会回调 AMap.OnInfoWindowClickListener,监听器的实现示例如下:

                            OnInfoWindowClickListener listener = new OnInfoWindowClickListener() {
                                @Override
                                public void onInfoWindowClick(Marker marker) {
                                    
                                    marker.setTitle("infowindow clicked");
                                }
                            };
                            //绑定信息窗点击事件
                            aMap.setOnInfoWindowClickListener(listener);
                            

                            简单点说就是可以自定义点击 InfoWindow 后的行为,例如改变标题、展示更多信息或触发其他操作。它有哪些使用场景和用途:

                            • 刷新 InfoWindow 内容: 在点击事件中,您可以修改 InfoWindow 的内容,使其动态刷新,显示最新的信息。这对于实时更新的信息非常有用。
                            • **交互式地图体验:**例如点击时显示更多的内容、点击后关闭InfoWindow弹框,marker.hideInfoWindow()即可。
                            • **与标记点关联的操作:**例如,在地图上显示商家的标记点,点击 InfoWindow 可以跳转到商家详情页面。

                              等等还要其他的,这里就举例这几种。

                              🚩自定义复杂的 InfoWindow

                              根据需求,你可能需求对标记点进行各种操作,如下图:

                              【高德地图】Android高德地图绘制标记点Marker 第8张

                              其实绘制自定义 InfoWindow本质上就是两步,先设置InfoWindow适配器,其次在view组件中自定义要显示的样式或按钮。

                              在这种自定义可能会遇到居中显示问题,如何点击标点时让其在屏幕中心,或者在屏幕中心下方一点点使其能都刚好在屏幕中心完全显示。只需在onMarkerClick点击事件中实现如下逻辑:

                              • 将marker位置坐标下移一小段距离显示
                              • 注意实现onMarkerClick前需要 aMap.setOnMarkerClickListener(this);设置
                                    @Override
                                    public boolean onMarkerClick(Marker marker) {
                                        // 当前点击的marker位置坐标
                                        LatLng markerLatLng = marker.getPosition();
                                        // 计算新坐标(下移一小段距离)
                                        double offsetLat = 0.003; 
                                        LatLng newCenterLatLng = new LatLng(markerLatLng.latitude + offsetLat, markerLatLng.longitude);
                                        // 创建一个新的 CameraPosition,设置新的方向为 0(北方向)
                                        CameraPosition newPosition = new CameraPosition.Builder()
                                                .target(newCenterLatLng)
                                                .bearing(0) // 将方向设置为 0(北方向)
                                                .zoom(15) // 设置缩放级别
                                                .build();
                                        // 移动地图中心点
                                        aMap.animateCamera(CameraUpdateFactory.newCameraPosition(newPosition));
                                        return true; // 返回 true 表示消费了点击事件,不再传递给其他监听器
                                    }
                                

                                【高德地图】Android高德地图绘制标记点Marker 第9张

                                ✅第1,2章 Android搭建3D高德地图详细教

                                ✅第 3 章 初始化定位并显示小蓝点

                                ✅第 4 章Android高德地图绘制标记点Marker

                                ✅第 5 章Android高德地图控件交互详细介绍


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]