ArcGIS for Android Runtime100 基本操作(二)——地图控件的常见操作

      以前我刚开始学习ArcGIS时候,看得最常见的一篇博客是Ersi中国官方写的一篇《ArcGIS for Android地图控件的5大常见操作》,地址是http://blog.csdn.net/arcgis_mobile/article/details/7801467。不过不知道啥原因后来这篇博客删掉了,但是网络上还是能看到到处转的这篇博文。

      这篇博文特别对于MapView的常见用法做了比较详细的描述,非常有用。不过在Runtime100里,大多数方法也都有了变化,我也就基于这篇博文的内容,在基于Runtime100的内容做一下更新吧。


      地图常见的操作有缩放、旋转、平移、获取范围、比例尺、分辨率等信息,以及常用的手势操作,其中,经常使用到的功能和常见问题有以下几个:

  1. 将地图缩放到指定的比例尺/分辨率/级别;
  2. 设置地图的最大最小缩放级别;
  3. 获取地图上某点的经纬度坐标;
  4. 地图的手势操作;
    下面内容会为您详细解答以上问题。


1、底图、比例尺、空间参考系和范围


      ArcGIS forAndroid中,MapView具有很多与地图操作有关的方法,其中,与地图的比例尺、空间参考系、范围有关的方法如下。

     因为在100里很多地图相关的内容都交给了ArcGISMap类来管理,所以先看看ArcGISMap类里的相关相关方法。

返回类型 方法 说明
Basemap getBasemap() 获取当前地图中的底图
double getMaxScale() 获取当前地图中的最大比例尺
double getMinScale() 获取当前地图中的最小比例尺
LayerList getOperationalLayers() 获取当前地图中的加载的图层
SpatialReference getSpatialReference() 获取当前地图中的空间参考系
Viewpoint getInitialViewpoint() 获取当前地图中的Viewpoint
void setBasemap(Basemap basemap) 设置当前地图的底图
void setInitialViewpoint(Viewpoint viewpoint) 设置当前地图中的Viewpoint
void setMaxScale(double maxScale) 设置当前地图中的最大比例尺
void setMinScale(double minScale) 设置当前地图中的最大比例尺


      其中Basemap,LayerList,Viewpoint都是100里新增加的类,分别表示底图,业务图层集合以及地图上当前可视范围内容。具体的使用可以看看链接的API。


      对于MapView里还保留的方法有:

返回类型 方法 说明
BackgroundGrid getBackgroundGrid() 获取地图背景格网
ArcGISMap getMap() 获取加载的ArcGISMap
double getMapRotation() 获取地图的旋转角度
double getMapScale() 获取地图的比例尺
SpatialReference getSpatialReference() 获取地图的空间参考系
void setBackgroundGrid(BackgroundGrid backgroundGrid) 设置地图背景格网
void setMap(ArcGISMap map) 设置加载的ArcGISMap


     我们可以看到,Esri对100里地图设置相关的策略就是用MapView仅作为一个容器,而ArcGISMap才是作为实际控制地图展示的类。我们可以在MapView里进行比例尺和旋转角度的查询,但是要设置最大最小比例尺,只能在MapView里先获取到对应ArcGISMap再进行设置。

      这一类的代码很简单,唯一有点问题的是如何隐藏背景格网,其方法为:

BackgroundGrid mainBackgroundGrid = new BackgroundGrid();
mainBackgroundGrid.setColor(0xffffffff);
mainBackgroundGrid.setGridLineColor(0xffffffff);
mainBackgroundGrid.setGridLineWidth(0);
mMapView.setBackgroundGrid(mainBackgroundGrid);


2、地图的平移、缩放和旋转

      

      在Arcgis 10.2里设置中心点平移是用的Mapview.centerAt(Point ponit,Boolean animated)方法实现,而100里,我们可以看到将这个方法进行了更改,除了直接设置中心点平移以外,还可以返回一个接口用以异步监听平移事件。

      除了设置中心点平移的方法外,与之类似的还有旋转,缩放等,其API如下所示:


ArcGIS for Android Runtime100 基本操作(二)——地图控件的常见操作


      整理下就是:

返回类型 方法 说明
ListenableFuture<Boolean> setViewpointAsync(Viewpoint viewpoint, float durationSeconds, AnimationCurve) 设置当前地图的Viewpoint
ListenableFuture<Boolean> setViewpointCenterAsync(Point point) 设置地图中心点(平移)
ListenableFuture<Boolean> setViewpointCenterAsync(Point center, double scale) 设置地图中心点和比例尺(平移和缩放)
ListenableFuture<Boolean> setViewpointGeometryAsync(Geometry boundingGeometry) 缩放地图到图形范围
ListenableFuture<Boolean> setViewpointGeometryAsync(Geometry boundingGeometry, double padding) 缩放地图到图形范围,并有一定外边距范围
ListenableFuture<Boolean> setViewpointRotationAsync(double angleDegrees) 设置地图的角度(旋转)
ListenableFuture<Boolean> setViewpointScaleAsync(double scale) 设置地图的比例尺(缩放)

      比起以前来,操作类的方法都多了个异步过程,返回的是ListenableFuture接口,包含addDoneListener和removeDoneListener方法,用以监听操作完成后的开启和关闭一个线程,例子为:

mMapView.setViewpointCenterAsync(clickPoint).addDoneListener(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(MainActivity.this,"平移到这里",Toast.LENGTH_SHORT).show();
    }
});

      这样在平移结束后会执行弹出提示的方法。


      对于缩放的话,比起10.2的版本,少了zoomin()和zoomout的方法,所以在100里如果要一级一级缩放地图只能采用设置当前地图比例尺的方法:

Double scales=mMapView.getMapScale();
mMapView.setViewpointScaleAsync(scales*2);
mMapView.setViewpointScaleAsync(scales*0.5);


3、地图上点坐标的获取


      地图上的坐标一般涉及到屏幕坐标转换为地图坐标,以及地图坐标转换为屏幕坐标。在100里,这两个功能实现的方法分别为:

返回类型 方法 说明
android.graphics.Point screenToLocation(Point screenPoint) 屏幕上的点转地图上的点
com.esri.arcgisruntime.geometry.Point locationToScreen(Point mapPoint) 地图上的点转屏幕上的点

      这两个方法很简单,不过注意的是两个Point的类型不一样。屏幕点的Point是用的Android本来自带的Point类,而地图上的点是用的100包里的Point类。不过想想也很符合道理,屏幕采点主要用于和Android设备本身相关的操作,而地图上的点都用于GIS里接下来的一些采集、分析、查询等。

      结合上一节平移举个例子为:

mMapView.setOnTouchListener(new DefaultMapViewOnTouchListener(this, mMapView) {
    @Override
    public boolean  onSingleTapConfirmed(MotionEvent v) {
        android.graphics.Point screenPoint=new android.graphics.Point(Math.round(v.getX()), Math.round(v.getY()));
        Point clickPoint = mMapView.screenToLocation(screenPoint);
        mMapView.setViewpointCenterAsync(clickPoint).addDoneListener(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this,"平移到这里",Toast.LENGTH_SHORT).show();
            }
        });
        Log.i("sss",clickPoint.toString());
        return true;
    }
});

4、地图上的手势操作


      在100里,将和地图相关的手势操作全部都封装到了一个DefaultMapViewOnTouchLisetener接口里。我们使用的时候只需要写一个监听接口,然后在接口里重写不同的手势方法就可以监听到不同的手势动作,这一点上非常方便。监听方法如下所示:

返回类型 方法 说明
abstract boolean onDoubleTouchDrag(MotionEvent e) 双击并拖动屏幕的监听方法
abstract boolean onMultiPointerTap(MotionEvent e) 多次点击屏幕的监听方法
abstract boolean onRotate(MotionEvent e, double angle) 旋转屏幕手势的监听方法
abstract boolean onUp(MotionEvent e) 当手指触摸屏幕抬起时候的监听方法
boolean onDoubleTap(MotionEvent e) 双并拖动屏幕的监听方法
boolean onDown(MotionEvent e) 当手指触摸到屏幕时候的监听方法
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) 当手指快速划过屏幕时候的监听方法
void onLongPress(MotionEvent e) 长按屏幕的监听方法
boolean onScale(ScaleGestureDetector detector) 双指触碰屏幕后靠近或者远离的监听方法
boolean onScaleBegin(ScaleGestureDetector detector) 当双指靠近手势开始时候监听方法
void onScaleEnd(ScaleGestureDetector detector) 当双指靠近手势结束时候监听方法
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) 当屏幕旋转时候的监听方法
boolean onSingleTapConfirmed(MotionEvent e) 在单击和双击屏幕之间时间的监听方法
boolean onSingleTapUp(MotionEvent e) 在单击事件手指离开屏幕时候的监听方法
boolean onTouch(View view, MotionEvent event) 触碰事件发送到某个View的监听方法

      可以看到监听手势的方法非常丰富,足以实现我们大部分的需求,一亿个例子来说明下如何使用手势的监听事件吧:

mMapView.setOnTouchListener(new DefaultMapViewOnTouchListener(this, mMapView) {
    @Override
    public boolean  onSingleTapConfirmed(MotionEvent v) {
        android.graphics.Point screenPoint=new android.graphics.Point(Math.round(v.getX()), Math.round(v.getY()));
        Point clickPoint = mMapView.screenToLocation(screenPoint);
        mMapView.setViewpointCenterAsync(clickPoint).addDoneListener(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this,"平移到这里",Toast.LENGTH_SHORT).show();
            }
        });
        return true;
    }
    @Override
    public boolean onDoubleTapEvent(MotionEvent e){
        Toast.makeText(MainActivity.this,"双击了一下",Toast.LENGTH_SHORT).show();
        return true;
    }
    @Override
    public void onLongPress(MotionEvent e){
        Toast.makeText(MainActivity.this,"长按了地图一下",Toast.LENGTH_SHORT).show();
    }
});

      可以看出100里对于屏幕的手势监听事件比以前简洁而强大了许多。

      PS:这一章表格的排版是在EXCEL里进行的,不知道为啥粘贴在博客里样式就都乱了。