Android基于高德地图完全自定义Marker的实现方法

前言

相信做地图社交类APP开发的大家都知道,一般情况下,为了整体的美观和用户体验度,我们需要定制化Marker的样式。本文中实现的方式都是基于高德地图的,百度地图也类似,大家可以照葫芦画瓢,废话不多说,先来看看最终效果:

实现思路:

先来看看高德官方提供的设置Marker图标的方法:

我们可以看到setIcon()方法,里面的参数BitmapDescriptor就是我们最终需要的东西。那么到底该如何得到这个BitmapDescriptor对象呢,其实很简单,该对象可以通过BitmapDescriptorFactory工厂类获取,BitmapDescriptorFactory提供了以下方法来得到BitmapDescriptor对象:

/**
 * 1.通过资源id获取
 */
public static BitmapDescriptor fromResource(int var0) {
 ......
}
/**
 * 2.通过自定义的view获取
 */
 public static BitmapDescriptor fromView(View var0) {
 ......
}

/**
 * 3.通过具体路径资源获取
 */
 public static BitmapDescriptor fromPath(String var0) {
 ......
}

/**
 * 4.通过具体Assets资源获取
 */
 public static BitmapDescriptor fromAsset(String var0) {
 ......
}
/**
 * 5.通过具体文件获取
 */
public static BitmapDescriptor fromFile(String var0) {
 ......
}

/**
 * 6.通过bitmap获取
 */
 public static BitmapDescriptor fromBitmap(Bitmap var0) {
 ......
}

从以上官方提供的方法可以看到,得到BitmapDescriptor对象的方式有多种,我们可以根据自己需要自行选择。但是,为了应对频繁的需求变化,我们肯定要选择更为动态,灵活的方式来应付我们的需求变化,我们就可以选择fromView()和fromBitmap()两种方式来得到BitmapDescriptor对象了。这里选用fromBitmap()方式来得到BitmapDescriptor对象吧,因为采用fromView()方法获取后有个巨坑,这个后面再说。

如果我们要根据需求自定义Marker,当然是希望能够让它可大可小,可动可静了,那就非view莫属了。只要我们可以自定义view布局,然后转化成bitmap不就OK了吗,好,说干就干,我们以自定义Makrer样式并加载网络图片为例,开干!

1、定制化Marker布局,加载网络图片:

我们就以实现以下Marker的样式为例:

这个样式比较简单,只要一个CircleImageView外面套一个固定的容器就可以了,直接看布局代码:

marker_bg.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="40dp"
 android:layout_height="47dp"
 android:layout_gravity="center">
 <RelativeLayout
 android:layout_width="40dp"
 android:layout_height="47dp"
 android:layout_centerHorizontal="true"
 android:layout_alignParentBottom="true"
 android:background="@mipmap/act_map_business_bg">
 <de.hdodenhof.circleimageview.CircleImageView
  android:id="@+id/marker_item_icon"
  android:layout_width="32dp"
  android:layout_height="32dp"
  android:src="@mipmap/userheadholder"
  android:layout_centerHorizontal="true"
  android:layout_marginTop="1dp" />
 </RelativeLayout>
</RelativeLayout>

下面看一下代码中如何使用:

/**
 * by moos on 2017/11/13
 * func:定制化marker的图标
 * @return
 */
 private void customizeMarkerIcon(String url, final OnMarkerIconLoadListener listener){
 final View markerView = LayoutInflater.from(this).inflate(R.layout.marker_bg,null);
 final CircleImageView icon = (CircleImageView) markerView.findViewById(R.id.marker_item_icon);

 Glide.with(this)
  .load(url+"!/format/webp")
  .asBitmap()
  .thumbnail(0.2f)
  .diskCacheStrategy(DiskCacheStrategy.NONE)
  .centerCrop()
  .into(new SimpleTarget<Bitmap>(){
   @Override
   public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
   //待图片加载完毕后再设置bitmapDes
   icon.setImageBitmap(bitmap);
   bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(convertViewToBitmap(markerView));
   listener.markerIconLoadingFinished(markerView);
   }
  });

 }

......

/**
 * by moos on 2017/11/15
 * func:自定义监听接口,用来marker的icon加载完毕后回调添加marker属性
 */
 public interface OnMarkerIconLoadListener{
 void markerIconLoadingFinished(View view);
 }

这部分代码也不是很难,我就简单讲讲思路。首先加载布局后,拿到里面的控件CircleImageView,并使用常用的Glide图片加载框架来加载网络图片。可能会有人问,为什么关闭Glide的缓存设置呢?关注到这点的人还是比较细心的,我们使用glide加载大量marker布局的时候,如果社会了缓存选项,那么就可能会出现相同图片只显示一张的状况,这个如果不信的话可以自行实验。下面来说说另一个问题,也就是刚刚我们为什么选择fromBitmap()而不是fromView()方法,因为之前用fromView()时发现添加的第一个marker并不会加载出图片,而只是显示默认的占位图。即使通过在Glide加载图片的回调方法onResourceReady()设置也依然无效,这个问题大家不信邪也可以试试看看,这就是最终为什么选择fromBitmap()方法的原因。这里还使用了自定义的接口来传入markerView,方便后面的二次开发,然后在回调方法markerIconLoadingFinished()方法中设置marker的图标。

将view转化为bitmap对象:

/**
 * by mos on 2017.11.13
 * func:view转bitmap
 */
 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;
 }

网上相关方法很多,这里就不介绍了,有兴趣可以去百度一下。

批量添加自定义的Marker到地图上:

先来看看代码:

/**
  * by moos on 2017/11/15
  * func:添加marker到地图上显示
  */
 BitmapDescriptor bitmapDescriptor ;
 private void addMarker(final ImageNearBean.DataBean.ExhibitionListBean bean) {
  double lat;
  double lon;
  lat = bean.getLatitude();
  lon = bean.getLongitude();
  LatLng latLng = new LatLng(lat, lon, false);
  loge("添加maker前的类型为==="+bean.getUserType());

  String url = bean.getUserLogo();
  final MarkerOptions markerOptions = new MarkerOptions();
  markerOptions.setFlat(true);
  markerOptions.anchor(0.5f, 0.5f);
  markerOptions.position(new LatLng(lat, lon));
  customizeMarkerIcon(url, bean.getTeamName(),new OnMarkerIconLoadListener() {
   @Override
   public void markerIconLoadingFinished(View view) {
    //bitmapDescriptor = BitmapDescriptorFactory.fromView(view);
    markerOptions.icon(bitmapDescriptor);
    Marker marker;
    marker = mAMap.addMarker(markerOptions);
    //marker.setObject(cluster);
   }
  });

 }

 /**
  * by moos on 2017/11/15
  * func:批量添加marker到地图上
  */
 private void addMarkersToMap(){

  runOnUiThread(new Runnable() {
     @Override
     public void run() {
      for(int i = 0;i<allBussinessBean.size();i++){
       addMarker(allBussinessBean.get(i));
      }
     }
    });
 }

既然marker样式定制完毕,BitmapDescriptor也拿到了,那么下面就简单了,应该就不需要我多说了,只要注意一点,批量添加marker一般比较耗时,尽量放在子线程处理。

到这里,自定义marker就实现了,这应该可以适用于多数情况了,一路看下来,是不是也挺简单的,只要用心思考研究就好了,而且搞定后有很强的工作动力有木有!

代码地址:https://github.com/Moosphan/AMapMarker-master (本地下载)此代码包含了自定义marker和marker的聚合功能,如果觉得对您有帮助,欢迎star~也同样欢迎提出想法和需求来进一步完善它.

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Android开发之高德地图实现定位

    在应用开发中,地图开发是经常需要使用的"组件",Google Map虽然有官方教程,无奈用不起来,原因你懂的~~那么国内比较出名的是就是百度地图和高德地图,由于个人喜好,所以选择了高德地图LBS,废话不说,上干货. 1.注册开发者,创建应用 这个几乎是所有开放平台都通用的做法,无外乎注册帐号,成为开发者,然后创建一个Android应用,会为你分配一个key绑定你的服务. 注册key.PNG 2.下载SDK,导入jar包,add to library jar包.PNG 第一个是2D地图的

  • Android之高德地图定位SDK集成及地图功能实现

    一:百度高德官方网站,然后去创建应用 网址:http://lbs.amap.com/ 1.找到控制台创建一个应用 2.添加key名称,注意命名规范,还有就是下面的SHA1和包名 3.点击右边的Gradle再选择signingReport下面会有个命令,稍等几分钟得到SHA1 4.添加包名 5.得到key 二:下载定位SDK,下载下来有地图SDK和定位SDK,然后导入项目,导入再Add As Library,so文件按自己需求来 下载地址:http://lbs.amap.com/api/andro

  • Android中GPS坐标转换为高德地图坐标详解

    一.坐标分类 地图坐标大致分为几种: 1.GPS.WGS84,也就是原始坐标体系,这是国际公认的世界标准坐标体系: 2.GCJ-02,又称为"火星坐标",国家测绘局在02年发布的坐标体系,在国内,至少得使用此坐标体系,比如:google.高德.腾讯地图等: 3.其他特殊坐标体系,一般都是由火星坐标通过偏移算法计算得出的,比如百度使用的是BD-09坐标,搜狗使用的是自己的搜狗坐标. 二.坐标转换 1.使用高德地图sdk转换 public AMapLocation fromGpsToAma

  • 关于Android高德地图的简单开发实例代码(DEMO)

    废话不多说了,直接给大家上干货了. 以下为初次接触时 ,练手的DEMO import android.app.Activity; import android.app.ProgressDialog; import android.content.ContentValues; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatab

  • Android 仿高德地图可拉伸的BottomSheet的示例代码

    前言 最近项目中需要用到高德地图搜索结果后的结果展示的可拉伸控件. gaode.gif 而我看到这个效果图,觉得这个就是一个slidingpanel,但是翻阅了一些发现用google自带的bottomsheet实现更方便 什么是BottomSheet? Bottom Sheet是Design Support Library23.2 版本引入的一个类似于对话框的控件,可以暂且叫做底部弹出框吧. Bottom Sheet中的内容默认是隐藏起来的,只显示很小一部分,可以通过在代码中设置其状态或者手势操

  • Android调用高德地图定位的方法

    在App中使用地图定位十分常见,购物功能的可以直接定位当前位置,发动态功能可以定位当前位置发出,社交功能可以定位周边用户等等.这里我使用高德地图定位当前位置并显示地址和经纬度. github代码传送门 先上效果图: 实现步骤: 1. 创建应用获取key: 接入第三方无一例外,去高德地图官网注册账号并创建应用.填入包名和keystore的Sha1. 创建应用 获取Sha1,输入命令keytool -v -list -keystore keystore文件路径,我在这里通过控制台获取调试版的: 进入

  • Android实现高德地图显示及定位

    本文实例为大家分享了Android实现高德地图显示及定位的具体代码,供大家参考,具体内容如下 先看看效果 1.要实现高德地图的定位,首先要下载高德地图的SDK 下载地址 然后在高德地图官网上登录你注册的账号并且去控制台-–>应用管理-–>添加新key  获取到自己的key值  获取key的具体方法的官网地址 2.通过解压得到.Jar文件并放到libs文件中,手动添加到依赖库中(右键Add--)  3.如果你的地图SDK是3D的需要在main中创建 jniLibs 文件夹并把你解压出来的其他文件

  • Android基于高德地图poi的仿微信获取位置功能实例代码

    1.打开页面自动定位,同时搜索周边所有poi 2.点击搜索按钮,输入关键子,获取关键字搜索结果 3.选取listview中的一项即可定位到该位置,或者获取任何消息 4.文件类 1.MapActivity public class MapActivity extends Activity implements PoiSearch.OnPoiSearchListener { private MapView mMapView = null; private AMap aMap; private MyL

  • Android高德地图poi检索仿微信发送位置实例代码

    最近项目需求把发送定位模块改成类似微信发送位置给好友的效果,我使用了高德地图实现了一个demo,效果图如下: 从主界面中我们可以看到中心标记上面显示的就是我们定位的地址,下面是一个listview列表,第一条item的数据就是我们定位得到的地址,下面其余的都是我们根据定位得到的经纬度通过poi周边搜索得到的地址.我们进行了如下操作: 我们点击列表的item,中心标记会移动到该item对象的地址上面去. 我们手动移动地图的时候,中心标记的地址会发生相应的变化并且下面的列表也会发生相应的变化. 根据

  • Android 高德地图之poi搜索功能的实现代码

    废话不多说,先看效果,如果大家感觉不错,请参考实现代码 这个功能我是用Fragmentdialog里面做的,也遇到不少坑 第一,就是设置背景的drawable为纯白色导致键盘弹出的时候,recyclerview的布局被顶上去导致出现白色布局,有点扎眼;最后改成了设置为和背景色一个颜色就和好了 Window window = getDialog().getWindow(); WindowManager.LayoutParams lp = window.getAttributes(); lp.gra

随机推荐