之前做了一个图片处理的app,把本地图片的经纬度存到手机本地数据库,然后在app中的“图片位置”页面的地图上的对应位置显示该图片,并有点聚合功能,能动态调整地图展示整屏Marker。效果如下:

       

android 高德addTileOverlay android 高德地图拍照功能_高德地图

      本功能使用的是高德地图的API,是在高德“点聚合效果”demo的基础上改的(高德官网提供的聚合点demo下载),下面的代码里很多类用的都是这个demo上的,如果缺少类请在demo里找。加载的图片都是手机本地的图片。点击自定义marker图片会获取该点聚合下的所有图片路径。

       在工程-app下的build.gradle中添加高德地图的依赖:

//高德3d地图
    compile 'com.amap.api:3dmap:5.6.0'
    compile 'com.amap.api:map2d:5.2.0'
    //定位
    compile 'com.amap.api:location:3.7.0'
    compile 'com.amap.api:search:5.5.0'

      在要展示点聚合页面的activity里:

@Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();//方法必须重写

        //清空之前的数据,重新获取数据。
        clusterItems.clear();
        pointList.clear();
        uriList.clear();
        addresList.clear();
        getPointList();

        mClusterOverlay = new ClusterOverlay(aMap,clusterItems,dip2px(getApplicationContext(),clusterRadius),getApplicationContext());
        mClusterOverlay.setClusterRenderer(this);
        mClusterOverlay.setOnClusterClickListener(this);
    }

    private int clusterRadius = 60;//聚合范围的大小(指点像素单位距离内的点会聚合到一个点显示)
    private MarkerOverlay markerOverlay;
    private ClusterOverlay mClusterOverlay;
    private List<LatLng> pointList = new ArrayList<>();//图片的经纬度list
    private List<String> uriList = new ArrayList<>();//图片的URI list
    private List<ClusterItem> clusterItems=new ArrayList<>();//聚合元素的list。ClusterItem是高德点聚合demo里的类,是点聚合的bean
    private List<LocalFile> addresList = new ArrayList<>();//
    //获取要显示的marker的经纬度集合
    private List<LatLng> getPointList() {
        addresList = helper.queryAddressDate();//从数据库获取含有经纬度的图片的list
        for (LocalFile localFile : addresList) {       
            String dateStr = localFile.getDateStr();
            int mediaId = localFile.getMediaID();
            String originalUri = localFile.getOriginalUri();
            LatLng latLng = new LatLng(localFile.getLatitude(),localFile.getLongitude());
            RegionItem regionItem = new RegionItem(latLng,"",originalUri,mediaId);
            clusterItems.add(regionItem);
            pointList.add(latLng);
            uriList.add(originalUri);
        }
        return pointList;
    }

    //方法必须重写
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(markerOverlay!=null) {
            markerOverlay.removeFromMap();
            if (locationClient != null) {
                locationClient.onDestroy();
                locationClient = null;
                locationClientOption = null;
            }
        }
        if(mClusterOverlay != null) {
            mClusterOverlay.onDestroy();
        }
        if(mapView!=null) {
            mapView.onDestroy();
        }
    }

 //点击点聚合图片,会获取该点聚合下的所有图片信息
 @Override
    public void onClusterClick(Marker marker, List<ClusterItem> clusterItems) {
        Log.e("onClusterClick",clusterItems.toString()+",mediaId="+clusterItems.get(0).getMediaId());
        List<LocalFile> addrFileList=new ArrayList<>();
        LocalFile localFile;
        for (ClusterItem clusterItem : clusterItems){
            localFile=new LocalFile();
            localFile.setMediaID(clusterItem.getMediaId());
            localFile.setOriginalUri(clusterItem.getUriStr());
            addrFileList.add(localFile);
        }
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList(MY_ADDR_LIST, (ArrayList<? extends Parcelable>) addrFileList);
        ActivityHelper.jumpWithBundleNoFinish(this,MyAddressListActivity.class,bundle);

        //点击会继续放大地图
       /* LatLngBounds.Builder builder = new LatLngBounds.Builder();
        for (ClusterItem clusterItem:clusterItems){
            builder.include(clusterItem.getPosition());
        }
        LatLngBounds latLngBounds = builder.build();
        aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds,0));*/
    }

下面的代码是ClusterOverlay.java内的,ClusterOverlay类是点聚合的关键类,自定义的点聚合marker图片就在这部分。

private List<Marker> mAddMarkers = new ArrayList<Marker>();

     /**
     * 将聚合元素添加至地图上
     */
    private void addClusterToMap(List<Cluster> clusters) {
        ArrayList<Marker> removeMarkers = new ArrayList<>();
        removeMarkers.addAll(mAddMarkers);

//        AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);//移动地图时marker图片会闪烁
        AlphaAnimation alphaAnimation = new AlphaAnimation(1, 1);
        MyAnimationListener myAnimationListener = new MyAnimationListener(removeMarkers);
        for (Marker marker : removeMarkers) {
            marker.setAnimation(alphaAnimation);
            marker.setAnimationListener(myAnimationListener);
            marker.startAnimation();
        }

//        Map map = new HashMap();
        List<Bitmap> bitmapList=new ArrayList<>();
        for (int i=0;i<clusters.size();i++){
            Cluster cluster=clusters.get(i);
            String uriStr = cluster.getClusterItems().get(0).getUriStr();
            Log.e("icon=",uriStr);
            //根据图片的uri获取图片的绝对路径
            String imgPath = getRealPathFromUri(mContext, Uri.parse(uriStr));
            Bitmap bitmap = getImgCompressBitmapByFileDescriptor(imgPath);
//            map.put(i,bitmap);
            bitmapList.add(bitmap);
        }

        for (int i=0;i<bitmapList.size();i++){
            addSingleClusterToMap(clusters.get(i),bitmapList.get(i));
        }

        /*for (Cluster cluster : clusters) {
            addSingleClusterToMap(cluster);
        }*/
    }

    /**
     * 将单个聚合元素添加至地图显示
     * @param cluster
     */
    private void addSingleClusterToMap(Cluster cluster, Bitmap bitmap) {
        int clusterCount = cluster.getClusterCount();//点聚合的数量
        String clusterNum=String.valueOf(clusterCount);
        //如果数量超过99张,则显示99+
        if(clusterCount>99) {
            clusterNum="99+";
        }
        //点聚合的页面布局,就是自定义的点聚合部分
        View view = View.inflate(mContext, R.layout.view_poi_overlay_item, null);
        //CircleImageView是自定义的圆形imageview
        CircleImageView ivPoiImg = (CircleImageView) view.findViewById(R.id.iv_poi_img);
        TextView tvNum = (TextView) view.findViewById(R.id.tv_num);
        tvNum.setText(clusterNum);//要把int类型转换为String类型,否则会误认为是resourceId报异常。
        ivPoiImg.setImageBitmap(bitmap);

        LatLng latlng = cluster.getCenterLatLng();
        MarkerOptions markerOptions = new MarkerOptions();
//        markerOptions.anchor(0.5f, 0.5f).icon(getBitmapDes(cluster.getClusterCount())).position(latlng);
        markerOptions.anchor(0.5f, 0.5f).icon(BitmapDescriptorFactory.fromView(view)).position(latlng);
        Marker marker = mAMap.addMarker(markerOptions);
//        marker.setAnimation(mADDAnimation);
        marker.setObject(cluster);

//        marker.startAnimation();
        cluster.setMarker(marker);
        mAddMarkers.add(marker);
    }

自定义点聚合marker图片的布局文件view_poi_overlay_item.xml,其中CircleImageView引用于compile 'de.hdodenhof:circleimageview:2.2.0',控件的宽高可以自己设定,不必按照下面从dimens文件里引用的:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="@dimen/poi_item_width_height"
    android:layout_height="@dimen/poi_item_width_height"
    android:id="@+id/rl_poi_img_bg">

    <de.hdodenhof.circleimageview.CircleImageView
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/iv_poi_img"
        android:layout_width="@dimen/poi_item_width_height"
        android:layout_height="@dimen/poi_item_width_height"
        android:src="@mipmap/ic_launcher"
        app:civ_border_width="@dimen/my_header_border_size"
        app:civ_border_color="@color/white"
        android:layout_centerHorizontal="true"/>
    <TextView
        android:id="@+id/tv_num"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:background="@drawable/tv_badge"
        android:text="99"
        android:padding="2dp"
        android:gravity="center"
        android:textColor="@color/white"
        android:textSize="@dimen/text_size_9"/>

</RelativeLayout>

点聚合数字的样式tv_badge.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    android:useLevel="false">

    <solid android:color="@color/orange_normal"/>
    <size android:width="@dimen/poi_text_badge_w_h"
        android:height="@dimen/poi_text_badge_w_h"/>
</shape>

另外MarkerOverlay.java里的addToMap()方法也要添加自定义的marker图片布局:

/**
     * 添加Marker到地图中。
     */
    public void addToMap(final List<String> uriList) {
        try {
            final Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    View view;
                    CircleImageView ivPoiImg;
                    ImageLoader imageLoader = ImageLoader.getInstance();
                    imageLoader.init(ImageLoaderConfiguration.createDefault(context));
                    for (int i = 0; i < pointList.size(); i++) {
                        final LatLng latLng = pointList.get(i);

//                        view = View.inflate(context, R.layout.view_poi_overlay_item, null);
//                        ivPoiImg = (CircleImageView) view.findViewById(R.id.iv_poi_img);

                        Log.e(TAG, "addToMap,uriList.get(i):" + uriList.get(i) + ",pointList.get(i):" + pointList.get(i));
                        Uri imgUri = Uri.parse(uriList.get(i));
                        String realPath = getRealPathFromUri(context, imgUri);
                        Log.e(TAG, "realPath:" + realPath + ",imgUri:" + imgUri);

                        final int finalI = i;
                        imageLoader.loadImage(uriList.get(i), new SimpleImageLoadingListener() {
                            @Override
                            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                                super.onLoadingComplete(imageUri, view, loadedImage);
                                view = View.inflate(context, R.layout.view_poi_overlay_item, null);
                                CircleImageView ivPoiImg = (CircleImageView) view.findViewById(R.id.iv_poi_img);
                                ivPoiImg.setImageBitmap(loadedImage);

                                final Marker marker = aMap.addMarker(new MarkerOptions()
                                        .position(latLng)
//                                      .icon(BitmapDescriptorFactory.fromResource(R.mipmap.bg_poi_overlay)));
                                        .icon(BitmapDescriptorFactory.fromView(view)));
//                                      .icon(BitmapDescriptorFactory.fromBitmap(realPath)));
//                                      .icon(getBitmapDescriptor(context,i,uriList)));

                                marker.setObject(finalI);
                                mMarkers.add(marker);
                            }
                        });

                /*Glide.with(context)
                        .load(uriList.get(i))
                        .crossFade()
                        .placeholder(R.drawable.detailpic_no)
                        .error(R.drawable.error)
                        .thumbnail(0.1f)
                        .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                        .into(new SimpleTarget<GlideDrawable>() {
                            @Override
                            public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
                                View view = View.inflate(context, R.layout.view_poi_overlay_item, null);
                                CircleImageView ivPoiImg = (CircleImageView) view.findViewById(R.id.iv_poi_img);
                                //会oom
                                ivPoiImg.setImageBitmap(drawableToBitmap(resource));

                                final Marker marker = aMap.addMarker(new MarkerOptions()
                                        .position(latLng)
                                        .icon(BitmapDescriptorFactory.fromView(view)));

                                marker.setObject(finalI);
                                mMarkers.add(marker);
                            }
                        });*/
                    }
                }
            };
            new Thread(){
                public void run(){
                    //不写会Can't create handler inside thread that has not called Looper.prepare()
                    new Handler(Looper.getMainLooper()).post(runnable);
                }
            }.start();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

这样基本上已经完成了。

说明:源码中LocalImageHelper是数据库操作类,就是对数据库的增删改查。这个自己写吧,就不贴我的代码了。代码中这个类是查找数据库中图片bean的集合,然后在地图中显示。