ArcGIS for Android Runtime100 基本操作(二)——地图控件的常见操作
以前我刚开始学习ArcGIS时候,看得最常见的一篇博客是Ersi中国官方写的一篇《ArcGIS for Android地图控件的5大常见操作》,地址是http://blog.csdn.net/arcgis_mobile/article/details/7801467。不过不知道啥原因后来这篇博客删掉了,但是网络上还是能看到到处转的这篇博文。
这篇博文特别对于MapView的常见用法做了比较详细的描述,非常有用。不过在Runtime100里,大多数方法也都有了变化,我也就基于这篇博文的内容,在基于Runtime100的内容做一下更新吧。
地图常见的操作有缩放、旋转、平移、获取范围、比例尺、分辨率等信息,以及常用的手势操作,其中,经常使用到的功能和常见问题有以下几个:
- 将地图缩放到指定的比例尺/分辨率/级别;
- 设置地图的最大最小缩放级别;
- 获取地图上某点的经纬度坐标;
- 地图的手势操作;
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如下所示:
整理下就是:
返回类型 | 方法 | 说明 |
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里进行的,不知道为啥粘贴在博客里样式就都乱了。