ArcGIS for Android地圖控制項的5大常見操作轉,arcgisandroid
http://blog.csdn.net/arcgis_mobile/article/details/7801467
GIS的開發中,什麼時候都少不了地圖操作。ArcGIS for Android中,地圖組件就是MapView,MapView是基於Android中ViewGroup的一個類(參考),也是ArcGIS Runtime SDK for Android中的地圖容器,與很多ArcGIS API中的Map、MapControl類的作用是一樣的。
地圖常見的操作有縮放、旋轉、平移、擷取範圍、比例尺、解析度等資訊,以及常用的手勢操作,其中,經常使用到的功能和常見問題有以下幾個:
1)將地圖縮放到指定的比例尺/解析度/層級;
2)設定地圖的最大最小縮放層級;
3)擷取地圖上某點的經緯度座標;
4)地圖的手勢操作;
5)地圖無法顯示。
下面內容會為您詳細解答以上問題。
1、擷取/設定比例尺、解析度、中心點、範圍;
ArcGIS forAndroid中,MapView具有很多與地圖操作有關的方法,其中,與地圖的比例尺、解析度、中心點、範圍有關的方法如下:
擷取/設定地圖的中心點、範圍、解析度、比例尺 |
傳回型別 |
方法 |
說明 |
Void |
centerAt(Point centerPt, Boolean animated) |
將地圖置中到指定的點 |
Point |
getCenter() |
擷取地圖中心點 |
Polygon |
getExtent() |
擷取地圖最小外包矩形 |
Envelope |
getMapBoundaryExtent() |
擷取地圖的邊界 |
Void |
setExtent(Geometry geometry) |
將地圖放大到指定的範圍,並將該geometry的bound作為地圖當前的extent |
Void |
setExtent(Geometry geometry, int padding) |
將地圖放大到指定的geometry以便geometry適應地圖的bound |
Double |
getMaxResolution() |
擷取地圖最大解析度 |
Void |
setMaxResolution(double maxResolution) |
設定地圖最大解析度 |
Double |
getMinResolution() |
擷取地圖最小解析度 |
Void |
setMinResolution(double minResolution) |
設定地圖最小解析度 |
Double |
getResolution() |
擷取當前地圖解析度 |
Void |
setResolution(double res) |
設定當前地圖解析度 |
Double |
getScale() |
擷取當前地圖比例尺 |
Void |
setScale(double scale) |
設定當前地圖比例尺 |
要擷取/設定地圖的比例尺、初始解析度、範圍、中心點等資訊,直接使用上述方法即可,非常簡單,在此不贅述,範例程式碼如下:
map.setScale(18489297.737236);//設定地圖初始化時的比例尺;
map.setAllowRotationByPinch(true);//設定是否允許地圖通過pinch方式旋轉;
map.setRotationAngle(15.0);//設定地圖的旋轉角度;
……
2、地圖縮放、平移和旋轉;
與縮放和旋轉有關的地圖事件如下:
地圖縮放、旋轉 |
傳回型別 |
方法 |
說明 |
Void |
zoomin() |
|
Void |
zoomout() |
|
Void |
zoomTo(Point centerPt, float factor) |
將地圖放蕩到指定點 |
Void |
zoomToResolution(Point centerPt, double res) |
將地圖放大到指定解析度 |
Void |
zoomToScale(Point centerPt, double scale) |
將地圖放大到指定比例尺 |
Double |
getRotationAngle() |
返回當前地圖旋轉角度(單位degree) |
Void |
setRotationAngle(double degree) |
將地圖按照指定的角度(單位degree)旋轉,度數為正數則按逆時針方向旋轉 |
Void |
setRotationAngle(double degree, float pivotX, float pivotY) |
將地圖按指定的點和角度旋轉,角度為正數按逆時針 |
Void |
setAllowRotationByPinch(boolean allowRotationByPinch) |
允許/取消pinch旋轉 |
Boolean |
isAllowRotationByPinch() |
是否允許pinch時旋轉 |
2.1 平移
MapView的方法中,沒有專門針對平移操作,主要原因在於,MapView中已經預設支援平移操作,即使用滑鼠或手勢拖動地圖時就會平移地圖,所以無需設定;
2.2 縮放至指定的解析度/比例尺和連續放大n倍
一般的切片地圖服務,在其REST服務的目錄下都能查到切片的等級、等級對應的解析度和比例尺,每個等級之間的解析度和比例尺之間呈2倍的關係。
ArcGIS Android中沒有像Web中的那種指標控制項,沒有直接的地圖層級的控制,通常層級控制通過解析度或比例尺來實現。可以用getResolution()和getscale()方法擷取當前地圖的比例尺和解析度,然後利用2的倍數關係,使用zoomTo()/zoomToScale()/zoomToResolution()來達到“控制地圖縮放層級”的目的:
放大/縮小1倍:
map.zoomin()、map.zoomout();
連續放大/縮小n倍:
map.zoomTo(point centerPt, float factor);如:map.zoomTo(centerPt,2n),其中,n為放大或縮小的倍數;
map.zoomToScale(Point centerPt, double scale) ;如:map.zoomToScale(centerPt, map.getScale()/2n)/map.zoomToScale(pt,map.getScale()*2n),其中,n為放大或縮小的倍數;
map.zoomToResolution(point centerPt, double res):map.zoomToResolution(centerPt,map.getResolution()/2n)/map.zoomToResolution(centerPt,map.getResolution() *2n),其中,n為放大或縮小的倍數;
在zoomTo(point centerPt, float factor)中,centerPt指在哪個點放大,factor參數用來計算新的解析度,計算公式為:新的解析度 = 當前解析度/factor。這個意思也就是說,想在當前解析度下放大3倍,則新解析度 = 當前解析度/(23),因為每一級之間解析度呈2的倍數關係,放大三級,解析度就是23倍,factor =23。 從中可以看出,地圖層級每增加1級,解析度/2,比例尺/2,故如果想將地圖連續放大n級,factor =2n。如果想將地圖連續縮小n級,則 factor =2-n。
在zooToScale(Point centerPt, double scale)和zoomToResolution(point centerPt, double res)中,scale和res都指實際的解析度和比例尺,故按照2的倍數關係直接乘除即可。
2.3 設定地圖最大最小縮放層級
有時候我們需要設定地圖放大或縮小到某個層級之後,不允許使用者再放大或縮小,用以下兩個方法很容易做到:
map.setMaxResolution(MaxResolution);
map.setMinResolution(MinResolution);
這兩個方法設定了地圖的最大、最小解析度,也就限制了地圖的縮放層級,當地圖達到最大、最小解析度時,地圖將不能再被縮小或者放大,以免使用者無限制的縮放地圖或看到更多的內容。
在初始化時將地圖設定為某種層級(找到該層級對應的解析度、比例尺):
map.setResolution(該層級對應的解析度);
至於如何擷取當前地圖等級,沒辦法,先擷取resolution,然後去rest服務類別目錄中對照取其層級吧。
2.4 旋轉地圖
可以使用setRotationAngle(double degree)和setRotationAngle(doubledegree, float pivotX, float pivotY)來實現將地圖旋轉一定的角度,要實現通過手勢進行旋轉,需要通過setOnPinchListener(OnPinchListener onPinchListener)監聽來實現。如:
public void onCreate(Bundle savedInstanceState, OnPinchListener onPinchListener) { super.onCreate(savedInstanceState); setContentView(R.layout.main); map = (MapView)findViewById(R.id.map); …… map.setAllowRotationByPinch(true); //是否允許使用Pinch方式旋轉地圖 map.setRotationAngle(15.0); //初始化時將地圖旋轉15度,參數為正時按逆時針方向旋轉。 } |
3、擷取地圖上某點的座標
擷取地圖上某點的座標主要使用下列幾個方法,其中,主要使用toMapPoint()方法實現擷取地圖上的點座標資訊:
傳回型別 |
方法 |
說明 |
SpatialReference |
getSpatialReference() |
返回地圖的座標系統 |
Point |
toMapPoint(float screenx, float screeny) |
將螢幕座標轉換成地圖座標系下的ArcGIS geometry Point座標 |
Point |
toMapPoint(Point src) |
將螢幕座標轉換成地圖座標系下的ArcGIS geometry Point座標 |
Point |
toScreenPoint(Point src) |
將地圖座標系下的ArcGIS geometry Point座標轉換成螢幕座標 |
如,在長按地圖時擷取滑鼠點的座標代碼如下:
// 長按顯示滑鼠點座標及比例尺 this.map.setOnLongPressListener(new OnLongPressListener() { private static final long serialVersionUID = 1L; @Override public void onLongPress(float x,float y) { com.esri.core.geometry.Point pt = map.toMapPoint(x, y); mapcenter.setText("X:"+ pt.getX() +"Y:"+ pt.getY()); labelxy.setText("當前地圖解析度為:" +map.getResolution()); mapscale.setText("當前地圖比例尺為:" +map.getScale()); } }); |
運行結果如下:
4、手勢操作
預設情況下,MapView響應以下手勢:
1)單一手指雙擊和pinch-out放大地圖;
2)兩個或多個手指pinch-in縮小地圖;
3)單個手指拖拽平移地圖。
其它手勢監聽有:
手勢事件 |
傳回型別 |
方法/事件監聽 |
說明 |
OnLongPressListener |
getOnLongPressListener() |
擷取地圖長按事件監聽 |
OnPanListener |
getOnPanListener() |
擷取地圖平移事件監聽 |
OnPinchListener |
getOnPinchListener() |
擷取地圖捏夾事件監聽 |
OnSingleTapListener |
getOnSingleTapListener() |
擷取地圖單擊事件監聽 |
OnZoomListener |
getOnZoomListener() |
擷取縮放監聽 |
void |
setOnLongPressListener(OnLongPressListeneronLongPressListener) |
設定地圖長按事件監聽 |
Void |
setOnPanListener(OnPanListener onPanListener) |
設定地圖平移事件監聽 |
Void |
setOnPinchListener(OnPinchListener onPinchListener) |
設定地圖捏夾事件監聽 |
Void |
setOnSingleTapListener(OnSingleTapListener onSingleTapListener) |
設定地圖單擊事件監聽 |
Void |
setOnZoomListener(OnZoomListener onZoomListener) |
設定縮放監聽 |
5、關於地圖顯示不出來的問題
許多新手在使用ArcGIS RuntimeSDk for Android開發時,最簡單的HelloWorld程式都會遇到問題,按照教程的步驟,添加了MapView,添加了切片圖層,一切就緒,地圖卻始終出不來,遇到這個問題可先從以下幾個方面尋找原因:
1)如果添加了多個圖層,請確保多個圖層的地理參考一致;
2)是服務類型是否對應;
3)圖層聲明在xml布局檔案中;
4)如果只是添加了一個底圖圖層仍然出不來底圖,那麼十有八九是extent的問題。首先,MapView控制項必須至少包含一個圖層,其次,該圖層最好為其指定initExtent,在xml中代碼如下:
<</SPAN>com.esri.android.map.MapView android:id="@+id/map" android:layout_width="fill_parent" android:layout_height="fill_parent" initExtent="-20037507.0672, -30240971.9584, 20037507.0672, 30240971.9584"> </</SPAN>com.esri.android.map.MapView> |
該initExtent來自哪裡呢?還是地圖服務類別目錄中:
取兩個中的任一個,或者自訂一個包含於上述兩個範圍中的extent均可,推薦使用full extent。
6、其它常用方法
除了上述提到的各種方法和監聽之外,還有一些與地圖相關的,也比較常用的方法和監聽如下:
其它屬性和事件 |
傳回型別 |
方法/事件監聽 |
說明 |
OnStatusChangedListener |
getOnStatusChangedListener() |
擷取地圖狀態改變事件監聽 |
Void |
setOnStatusChangedListener(OnStatusChangedListeneronStatusChangedListener) |
設定地圖狀態改變事件監聽 |
Boolean |
isLoaded() |
MapView初始化之後返回true |
Void |
setEsriLogoVisible(Boolean visible) |
開啟或關閉地圖上的ESRI的logo標籤 |
Void |
setMapBackground(int bkColor, int gridColor, float gridSize, float gridLineSize) |
設定地圖背景顏色 |