Android 基于百度地图 自由多边形覆盖物demo

需要实现的功能

1、按住多边形可自由拖动 

2、长按多边形顶点可以自由拖动多边形顶点 

3、点击多边形线条可以生成新的点 

4、点击多边形顶点可以删除多边形顶点

     先上效果图。



百度地图支持的各种地图覆盖物:地图标注(Marker)、几何图形(点、折线、弧线、多边形等)、POI检索结果覆盖物、线路规划结果覆盖物等。
自定义图层:定位图层、地形图图层、热力图图层、瓦片图层。   

我使用的 百度地图版本:v5_0_0

代码可以查看github    https://github.com/oldbirdy/polygonDemoByBaidu 



首先在Application中初始化百度地图SDK

public class DemoApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        // 在使用 SDK 各组间之前初始化 context 信息,传入 ApplicationContext
        SDKInitializer.initialize(this);
        //自4.3.0起,百度地图SDK所有接口均支持百度坐标和国测局坐标,用此方法设置您使用的坐标类型.
        //包括BD09LL和GCJ02两种坐标,默认是BD09LL坐标。
        SDKInitializer.setCoordType(CoordType.BD09LL);
    }
}

Activity中处理覆盖物的拖拽

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_overlay);

        mMapView = (MapView) findViewById(R.id.bmapView);
        mBaiduMap = mMapView.getMap();
        MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(14.0f);
        mBaiduMap.setMapStatus(msu);
        combinationOverlayList = new ArrayList<>();
        initOverlay();

    }
       //初始化基础数据
    public void initOverlay() {
        LatLng llA = new LatLng(39.963175, 116.400244);
        LatLng llB = new LatLng(39.942821, 116.369199);
        LatLng llC = new LatLng(39.939723, 116.425541);
        LatLng llD = new LatLng(39.906965, 116.401394);
        list = new ArrayList<>();
        list.add(llA);
        list.add(llB);
        list.add(llD);
        list.add(llC);

        final CombinationOverlay combinationOverlay = new CombinationOverlay(mMapView,list);
        combinationOverlayList.add(combinationOverlay);

        LatLng southwest = new LatLng(39.92235, 116.380338);
        LatLng northeast = new LatLng(39.947246, 116.414977);
        LatLngBounds bounds = new LatLngBounds.Builder().include(northeast)
                .include(southwest).build();

        MapStatusUpdate u = MapStatusUpdateFactory
                .newLatLng(bounds.getCenter());
        mBaiduMap.setMapStatus(u);

        mBaiduMap.setOnMapTouchListener(new BaiduMap.OnMapTouchListener() {
            @Override
            public void onTouch(MotionEvent motionEvent) {

                if(motionEvent.getAction()==MotionEvent.ACTION_DOWN){   //按下的时候 做处理
                    tempOverlay = null;
                    lastx =  motionEvent.getX();
                    lasty = motionEvent.getY();
                    Point point = new Point( (int)(motionEvent.getX()),(int) (motionEvent.getY()));
                    LatLng latlng = mBaiduMap.getProjection().fromScreenLocation(point);
//                    MapStatus.Builder builder = new MapStatus.Builder();

                    for(int i=0;i<combinationOverlayList.size();i++){
                       List<LatLng> list  = combinationOverlayList.get(i).getLatLngList();
                        if(SpatialRelationUtil.isPolygonContainsPoint(list,latlng)){   //判断是否在多边形里面
                            //在多边形内部
//                            createPopupView("提示消息", new OnClickListener() {
//                                @Override
//                                public void onClick(View v) {
//
//                                }
//                            }, new OnClickListener() {
//                                @Override
//                                public void onClick(View v) {
//
//                                }
//                            });
//                            infoWindow = new InfoWindow(popupView,latlng,0);
//                            mBaiduMap.showInfoWindow(infoWindow);
                            tempOverlay = combinationOverlayList.get(i);
                            mBaiduMap.getUiSettings().setScrollGesturesEnabled(false);
                            mBaiduMap.hideInfoWindow();
                            break;
                        }
                    }

                }else if(motionEvent.getAction()==MotionEvent.ACTION_MOVE){
                    if(tempOverlay!=null){
                        //全部根据手指的移动将其转化成百度坐标
                        if(!isDrag){
                            offsetx = motionEvent.getX() - lastx;
                            offsety = motionEvent.getY() - lasty;
                            lastx =  motionEvent.getX();
                            lasty = motionEvent.getY();
                            tempOverlay.updateOverlayByPolygon(offsetx,offsety);
                        }

                    }
                }else if(motionEvent.getAction()==MotionEvent.ACTION_UP){
                    if( tempOverlay != null){
                        mBaiduMap.getUiSettings().setScrollGesturesEnabled(true);
                    }
                }
            }
        });
        
        mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latLng) {

            }

            @Override
            public boolean onMapPoiClick(MapPoi mapPoi) {
                return false;
            }
        });
        //Marker点击事件
        mBaiduMap.setOnMarkerClickListener(new OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {

                return updateMarkerClick(marker);
            }
        });
           //markertu
        mBaiduMap.setOnMarkerDragListener(new OnMarkerDragListener() {
            public void onMarkerDrag(Marker marker) {
                updateMarkerDrag(marker);
            }

            public void onMarkerDragEnd(Marker marker) {
                isDrag = false;
            }

            public void onMarkerDragStart(Marker marker) {
                isDrag = true;
            }
        });
        mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latLng) {
                mBaiduMap.hideInfoWindow();

            }

            @Override
            public boolean onMapPoiClick(MapPoi mapPoi) {
                return false;
            }
        });
        mBaiduMap.setOnPolylineClickListener(new BaiduMap.OnPolylineClickListener() {
            @Override
            public boolean onPolylineClick(Polyline polyline) {
                mBaiduMap.hideInfoWindow();
                return updateLineClick(polyline);
            }
        });
    }

    /**
     * 更新marker点击
     * @param marker
     * @return
     */
    private boolean updateMarkerClick(final Marker marker) {
       for(int i=0;i < combinationOverlayList.size();i++){
           if(combinationOverlayList.get(i).getMarkerList().contains(marker)){

               Button button = new Button(getApplicationContext());
               button.setBackgroundResource(R.drawable.popup);
               LatLng ll = marker.getPosition();
               button.setText("删除当前点");
               button.setTextColor(Color.BLACK);
               final int finalI = i;
               button.setOnClickListener(new OnClickListener() {
                   public void onClick(View v) {
                       combinationOverlayList.get(finalI).updateOverlayByRemoveOneMarker(marker);

                   }
               });
               infoWindow = new InfoWindow(button,ll,-47);

               mBaiduMap.showInfoWindow(infoWindow);
               return true;
           }
       }
        return false;
    }

    /**
     * 更新线段点击
     * @param polyline
     * @return
     */
    private boolean updateLineClick(Polyline polyline){
        for(int i=0;i<combinationOverlayList.size();i++){
            if(combinationOverlayList.get(i).getPolylineList().contains(polyline)){
                combinationOverlayList.get(i).updateOverlayByLineClick(polyline);
                return true;
            }
        }
        return false;
    }

    private void updateMarkerDrag(Marker marker) {
        for(int i=0;i<combinationOverlayList.size();i++){
            if(combinationOverlayList.get(i).getMarkerList().contains(marker)){
                combinationOverlayList.get(i).updateOverlayByMarker(marker);
            }
        }

    }
自定义的一个组合覆盖物。会生成相应的覆盖物界面。根据覆盖物上的点,线,面的事件去更新整个覆盖物的状态
public class CombinationOverlay {
    private MapView mMapView;
    private BaiduMap mBaiduMap;
    private List<LatLng> latLngList;

    BitmapDescriptor bdA = BitmapDescriptorFactory
            .fromResource(R.drawable.icon_marka);

    private List<List<LatLng>> lineListList;
    private Polygon polygonOverlay;
    private List<Marker> markerList;
    private List<Polyline> polylineList;

    private Stroke stroke = new Stroke(5, 0xAA00FF00);

    public CombinationOverlay(MapView mMapView, List<LatLng> latLngList) {
        this.mMapView = mMapView;
        this.latLngList = latLngList;
        if(latLngList.size()<3){
            throw new IllegalArgumentException("点数小于3,无法构成多边形");
        }
        mBaiduMap = mMapView.getMap();
        initZiyuan();
    }

    private void initZiyuan() {
        PolygonOptions polygonOptions = new PolygonOptions();
        polygonOptions.points(latLngList);
        polygonOptions.stroke(stroke);
        polygonOptions.fillColor(0xAAFFFF00);
        polygonOverlay = (Polygon)mBaiduMap.addOverlay(polygonOptions);

        markerList = new ArrayList<>();
        for(int i = 0;i < latLngList.size();i++){
//            latLngList =
            MarkerOptions markerOptions = new MarkerOptions().position(latLngList.get(i)).icon(bdA).draggable(true);
            Marker marker= (Marker)mBaiduMap.addOverlay(markerOptions);
            markerList.add(marker);
        }

      
        lineListList = new ArrayList<>();
        polylineList = new ArrayList<>();
        for(int i=0;i<latLngList.size();i++){
            List<LatLng> latLngLineList = new ArrayList<>();
            latLngLineList.add(latLngList.get(i));
            if(i < latLngList.size()-1){
                latLngLineList.add(latLngList.get(i+1));
            }else{
                latLngLineList.add(latLngList.get(0));
            }
            lineListList.add(latLngLineList);
            PolylineOptions polylineOptions =  new PolylineOptions().points(latLngLineList).color(0xAAFFFF00).focus(true).width(10);
            Polyline polyline  = (Polyline)mBaiduMap.addOverlay(polylineOptions);
            polylineList.add(polyline);
        }
    }

    public Polygon getPolygonOverlay() {
        return polygonOverlay;
    }

    public void setPolygonOverlay(Polygon polygonOverlay) {
        this.polygonOverlay = polygonOverlay;
    }

    public List<Marker> getMarkerList() {
        return markerList;
    }

    public void setMarkerList(List<Marker> markerList) {
        this.markerList = markerList;
    }

    public List<Polyline> getPolylineList() {
        return polylineList;
    }

    public void setPolylineList(List<Polyline> polylineList) {
        this.polylineList = polylineList;
    }

    public List<LatLng> getLatLngList() {
        return latLngList;
    }

    /**
     * 更新覆盖物的位置
     */
    public void updateOverlayByMarker(Marker marker){
       int position =  markerList.indexOf(marker);
       if(position==-1){
           return;
       }
       latLngList.set(position,marker.getPosition());
       polygonOverlay.setPoints(latLngList);
       if(position==0){  //第一个点   更新第一条线和最后一条线
           lineListList.get(position).set(0,marker.getPosition());  //更新第一个点的坐标
           polylineList.get(position).setPoints(lineListList.get(position));

           lineListList.get(lineListList.size()-1).set(1,marker.getPosition()); //更新第二个点
           polylineList.get(polylineList.size()-1).setPoints(lineListList.get(polylineList.size()-1 ));
       }else{
           lineListList.get(position).set(0,marker.getPosition());  //更新第一个点
           polylineList.get(position).setPoints(lineListList.get(position));

           lineListList.get(position-1).set(1,marker.getPosition());
           polylineList.get(position-1).setPoints(lineListList.get(position-1));
       }
    }

    /**
     * 根据偏移量更新显示位置
     * @param offsetx
     * @param offsety
     */
    public void updateOverlayByPolygon(float offsetx,float offsety){
        latLngList =  MapUtils.getLatLngByOffset(mMapView,latLngList,offsetx,offsety);
        polygonOverlay.setPoints( latLngList);
        for(int i=0;i < markerList.size();i++){
            markerList.get(i).setPosition(latLngList.get(i));
        }

        lineListList.clear();
        for(int i=0;i<latLngList.size();i++){
            List<LatLng> latLngLineList = new ArrayList<>();
            latLngLineList.add(latLngList.get(i));
            if(i < latLngList.size()-1){
                latLngLineList.add(latLngList.get(i+1));
            }else{
                latLngLineList.add(latLngList.get(0));
            }
            lineListList.add(latLngLineList);

            polylineList.get(i).setPoints(latLngLineList);
        }
//

    }



    /**
     * 点击线条触发
     * @param polyline
     */
    public void updateOverlayByLineClick(Polyline polyline){
        int positon = polylineList.indexOf(polyline);
        if(-1==positon){
            return;
        }
        LatLng latLng = MapUtils.getCenterOfLines(mMapView,polyline.getPoints());  //得到中心点
        latLngList.add(positon+1,latLng);
        removeCombinationOverlay();
        initZiyuan();
    }


    public void updateOverlayByRemoveOneMarker(Marker marker){
        int positon = markerList.indexOf(marker);
        if(-1==positon){
            return;
        }
        if(markerList.size()<4){
            Toast.makeText(mMapView.getContext(), "不能移除当前点,移除后无法构成多边形", Toast.LENGTH_SHORT).show();
        }else{
            latLngList.remove(positon);
            removeCombinationOverlay();
            initZiyuan();
        }
        mBaiduMap.hideInfoWindow();
    }



    /**
     * 移除覆盖物
     */
    public void removeCombinationOverlay(){
        polygonOverlay.remove();

        for(int i=0;i<markerList.size();i++){
            markerList.get(i).remove();
        }

        for(int i=0;i<polylineList.size();i++){
            polylineList.get(i).remove();
        }
        markerList.clear();
        polylineList.clear();
        lineListList.clear();

    }

}
一个工具类:
    
public class MapUtils {

    /**
     * 获取线段中心点坐标
     * @param mPoints
     * @return
     */
    public static LatLng getCenterOfLines(MapView mapView, @Size(2) List<LatLng> mPoints){
        if(mPoints.size()!=2){
            throw new IllegalArgumentException("线段点个数应为2个");
        }
        Projection projection = mapView.getMap().getProjection();
        Point point0 = projection.toScreenLocation(mPoints.get(0));
        Point point1 = projection.toScreenLocation(mPoints.get(1));
        Point point =  getCenterOfScrrenTwoPoint(point0,point1);
        return projection.fromScreenLocation(point);
    }

    /**
     * 获取屏幕上两点的中心坐标
     * @return
     */
    public static Point getCenterOfScrrenTwoPoint(Point point0,Point point1){
        return new Point((int)((point0.x+point1.x)/2),(int)((point0.y+point1.y)/2));
    }

    /**
     * 根据偏移量获取新的坐标值
     * @param list
     * @param offsetx
     * @param offsety
     * @return
     */
    public static List<LatLng> getLatLngByOffset(MapView mapView,List<LatLng> list,float offsetx,float offsety){
        Projection projection = mapView.getMap().getProjection();

        for(int i=0;i<list.size();i++){
            Point tempPoint = projection.toScreenLocation(list.get(i));
            tempPoint.offset((int)offsetx,(int)offsety);
            list.set(i,projection.fromScreenLocation(tempPoint));
        }
        return list;
    }

    //计算多边形重心  也可计算面积
    public static LatLng getCenterOfGravityPoint(List<LatLng> mPoints) {
        double area = 0.0;//多边形面积
        double Gx = 0.0, Gy = 0.0;// 重心的x、y
        for (int i = 1; i <= mPoints.size(); i++) {
            double iLat = mPoints.get(i % mPoints.size()).latitude;
            double iLng = mPoints.get(i % mPoints.size()).longitude;
            double nextLat = mPoints.get(i - 1).latitude;
            double nextLng = mPoints.get(i - 1).longitude;
            double temp = (iLat * nextLng - iLng * nextLat) / 2.0;
            area += temp;
            Gx += temp * (iLat + nextLat) / 3.0;
            Gy += temp * (iLng + nextLng) / 3.0;
        }
        Gx = Gx / area;
        Gy = Gy / area;
        return new LatLng(Gx, Gy);
    }
}




猜你喜欢

转载自blog.csdn.net/xu_coding/article/details/80371814
今日推荐