《ArcGIS Runtime SDK for Android開發筆記》——離在線一體化技術:離線矢量數據編輯

一、前言

在上一篇咱們已經實現了離線地理數據庫的下載,這一篇咱們着重介紹離線數據庫的加載與編輯。html

因爲ArcGIS Runtime SDK for Android 10.2.X版本並沒提供要素繪製功能,因此本篇中的要素繪製部分基於以前開源的Drawtools3.0工具實現。java

本DEMO主要實現了:離線地理數據庫加載、要素樣式模板加載,要素新建、要素選擇並開啓編輯狀態、要素刪除等操做。因爲內容較多涉及編輯部分僅詳細介紹對Geodatabase的要素添加、要素刪除、要素更新部分,其他請自行查閱源代碼。android

轉載請註明出處:http://www.cnblogs.com/gis-luq/p/5858055.html git

二、離線要素編輯實現過程

2.一、加載本地離線要素

ArcGIS Runtime SDK for Android中提供了具體的Geodatabase類和FeatureLayer圖層來加載.geodatabase文件,經常使用的類包括Geodatabase、GeodatabaseFeatureTable、GeodatabaseFeature、GeodatabaseFeatureServiceTable等,分別用來打開geodatabase數據文件、獲取要素圖層、獲取圖層中的具體要素,以及獲取在線的要素服務。具體來說,加載.geodatabase文件的步驟有以下幾步:數據庫

一、  實例化一個Geodatabase對象,這個類有兩個構造函數,都須要指定本地數據庫的存儲路徑;api

二、  建立一個GeodatabaseFeatureTable對象實例,用來獲取須要的圖層;ide

三、  建立一個FeatureLayer來存儲獲取的圖層,並將獲取的圖層加載到地圖中;函數

四、  調用dispose()方式釋放資源。工具

 /**
     * 讀取Geodatabase中離線地圖信息
     * @param geodatabsePath 離線Geodatabase文件路徑
     */
    private void addFeatureLayer(String geodatabsePath) {

        Geodatabase localGdb = null;
        try {
            localGdb = new Geodatabase(geodatabsePath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        layerList = new ArrayList<>();
        // 添加FeatureLayer到MapView中
        if (localGdb != null) {
            for (GeodatabaseFeatureTable gdbFeatureTable : localGdb.getGeodatabaseTables()) {
                if (gdbFeatureTable.hasGeometry()){
                    FeatureLayer layer = new FeatureLayer(gdbFeatureTable);
                    mMapView.addLayer(layer);
                }
            }
        }
    }

2.二、加載本地要素樣式模板post

    

繪製要素時每每會須要知道待繪製要素的圖層名稱以及要素的符號化樣式,這裏咱們以geodatabse中的FeatureLayer爲例演示要素樣式模板獲取流程。

   /**
     * 添加要素繪製樣式模板
     * 獲取圖層要素模板並添加到featureTempleteView
     * @param layer
     */
    private void addFeatureTemplate(FeatureLayer layer) {
        List<FeatureTemplate> featureTemp = ((GeodatabaseFeatureTable) layer.getFeatureTable()).getFeatureTemplates();
        for (FeatureTemplate featureTemplate : featureTemp) {
            GeodatabaseFeature g = null;
            try {
                g = ((GeodatabaseFeatureTable) layer.getFeatureTable()).createFeatureWithTemplate(featureTemplate, null);
                Renderer renderer = layer.getRenderer();
                Symbol symbol = renderer.getSymbol(g);
                float scale = context.getResources().getDisplayMetrics().density;
                int widthInPixels = (int) (35 * scale + 0.5f);
                Bitmap bitmap = SymbolHelper.getLegendImage(symbol, widthInPixels, widthInPixels);

                //將要素樣式模板賦值給imgButton
                ImageButton imageButton = new ImageButton(context);
                imageButton.setImageBitmap(bitmap);
                imageButton.setTag(layer);//保存當前待編輯圖層
                ((LinearLayout)featureTempleteView).addView(imageButton);//添加到要素樣式模板列表
                imageButton.setOnClickListener(new ImageButtonOnClickListener());
            } catch (TableException e) {
                e.printStackTrace();
                Toast.makeText(MainActivity.this, "Error:" + e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
            }
        }
    }

2.二、編輯本地離線要素

要素編輯最核心的是FeatureTable中的增刪改方法,經過這些方法能夠實現本地數據庫中要素編輯操做。

FeatureTable中的經常使用方法以下:

2.2.一、要素添加

private FeatureLayer selectFeatureLayer;//當前選中圖層
private Graphic selectGraphic = null;//待添加要素(零時圖層中獲取)
try {
    GeodatabaseFeatureTable geodatabaseFeatureTable = (GeodatabaseFeatureTable)selectFeatureLayer.getFeatureTable();
    GeodatabaseFeature gdbFeature = new GeodatabaseFeature(null, selectGraphic.getGeometry(), geodatabaseFeatureTable);
    long fid = geodatabaseFeatureTable.addFeature(gdbFeature);// 添加要素
    Log.d(TAG,"要素添加成功,Feature ID:"+fid);
} catch (TableException e) {
    e.printStackTrace();
}

2.2.二、要素刪除

private FeatureLayer selectFeatureLayer;//當前選中圖層
private Feature selectFeature = null;//當前選中要素
GeodatabaseFeatureTable geodatabaseFeatureTable = (GeodatabaseFeatureTable)selectFeatureLayer.getFeatureTable();
try {
   if (selectFeature!=null){
       eodatabaseFeatureTable.deleteFeature(selectFeature.getId());//刪除要素
   }
} catch (TableException e) {
    e.printStackTrace();
}

2.2.三、要素矢量信息更新

private FeatureLayer selectFeatureLayer;//當前選中圖層
private Feature selectFeature = null;//當前選中要素
private Graphic selectGraphic = null;//待更新要素(零時圖層中獲取)
try {
    GeodatabaseFeatureTable geodatabaseFeatureTable = (GeodatabaseFeatureTable)selectFeatureLayer.getFeatureTable();
    geodatabaseFeatureTable.updateFeature(selectFeature.getId(),selectGraphic.getGeometry());//更新要素
    Log.d(TAG,"要素更新成功");
} catch (TableException e) {
    e.printStackTrace();
}

擴展說明:如何選中要素,以及如何處理具備壓蓋關係的要素選擇問題?

針對這兩個問題咱們一併處理,首先擴展MapOnTouchListener類,實現長按出現放大鏡,並選中要素。選中要素時咱們採用遍歷當前全部圖層的方式,找出每一個圖層中第一個被選中的要素,而後彈窗提示供用戶選擇。

//全局定義信息
private List<FeatureLayer> layerList;//矢量圖層列表

private GraphicsLayer graphicsLayer = null;//零時圖層
private FeatureLayer selectFeatureLayer;//當前選中圖層
private Graphic selectGraphic = null;//當前選中要素(零時圖層)
private Feature selectFeature = null;//當前選中要素

要素選中擴展事件。

/**
 * 地圖窗口默認Touch事件
 * 支持長按放大鏡選種要素
 */
public class MapSelectFeatureOnTouchListener extends MapOnTouchListener{

    public MapSelectFeatureOnTouchListener(Context context, MapView view) {
        super(context, view);
    }

    @Override
    public boolean onLongPressUp(MotionEvent point) {
        handleTap(point);
        //長按放大鏡選擇事件
        super.onLongPressUp(point);
        return true;
    }

    @Override
    public boolean onSingleTap(final MotionEvent e) {
        //單擊響應事件
        return true;
    }

    /**
     * 獲取當前選中要素
     * @param point
     */
    private void handleTap(MotionEvent point) {
        MotionEvent screePoint = point;

        //選中圖層信息
        final List<SelectFeatureInfo> selectFeatureInfoList = new ArrayList<>();
        //記錄當前選中要素信息,涉及多個圖層狀況
        for (int i=0;i<layerList.size();i++){
            FeatureLayer featureLayer = layerList.get(i);
            featureLayer.setSelectionColor(Color.YELLOW);
            featureLayer.setSelectionColorWidth(10);
            long[] selids = featureLayer.getFeatureIDs(screePoint.getX(), screePoint.getY(), 1);
            if (selids.length >= 1) {
                SelectFeatureInfo selectFeatureInfo = new SelectFeatureInfo();
                selectFeatureInfo.featureLayer = featureLayer;
                selectFeatureInfo.selectFeatureID = selids[0];
                selectFeatureInfoList.add(selectFeatureInfo);
            }
        }

        //根據待選圖層肯定是否彈窗選擇
        if(selectFeatureInfoList.size()>1){
            //當前選中要素大於1個圖層
            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
            builder.setTitle("請確認選擇哪一個圖層要素?");
            //指定下拉列表的顯示數據
            final String[] layerNamelist = getSelectFeatureInfoListName(selectFeatureInfoList);
            //設置一個下拉的列表選擇項
            builder.setItems(layerNamelist, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    Toast.makeText(MainActivity.this, "選擇的圖層爲:" + layerNamelist[which], Toast.LENGTH_SHORT).show();
                    SelectFeatureInfo selectFeaInfo = getFeatureLayerbyName(selectFeatureInfoList,layerNamelist[which]);
                    setSelectFeature(selectFeaInfo);//根據選中圖層信息選中當前要素
                }
            });
            builder.show();
        }else if(selectFeatureInfoList.size()==1) {
            SelectFeatureInfo selectFeaInfo = selectFeatureInfoList.get(0);
            setSelectFeature(selectFeaInfo);//根據選中圖層信息選中當前要素
        }

    }

    /**
     * 設置選中圖層的要素選中信息
     * @param selectFeaInfo 待選圖層信息
     */
    private void setSelectFeature(SelectFeatureInfo selectFeaInfo) {
        clearFeatureSelection();//設置選中狀態前,清空已選擇要素
        selectFeaInfo.featureLayer.selectFeature(selectFeaInfo.selectFeatureID);
        selectFeatureLayer = selectFeaInfo.featureLayer;
        selectFeature = selectFeatureLayer.getFeature(selectFeaInfo.selectFeatureID);
        switch (selectFeature.getGeometry().getType()){
            case POINT:
            case MULTIPOINT:
                selectGraphic = new Graphic(selectFeature.getGeometry(), DrawSymbol.markerSymbol, null);
                break;
            case LINE:
            case POLYLINE:
                selectGraphic = new Graphic(selectFeature.getGeometry(), DrawSymbol.mLineSymbol,null);
                break;
            case ENVELOPE:
            case POLYGON:
                selectGraphic = new Graphic(selectFeature.getGeometry(), DrawSymbol.mFillSymbol, null);
                break;
            default:
                break;
        }
    }

    /**
     * 經過圖層名稱獲取要素
     * @param name 圖層名稱
     * @return 選中圖層信息
     */
    private SelectFeatureInfo getFeatureLayerbyName(List<SelectFeatureInfo> selectFeatureInfoList,String name){
        SelectFeatureInfo selectinfo= null;
        for (int i=0;i<selectFeatureInfoList.size();i++){
            FeatureLayer tmplayer = selectFeatureInfoList.get(i).featureLayer;
           if (tmplayer.getName().equals(name)){
               selectinfo = selectFeatureInfoList.get(i);//選中圖層信息
           }
        }
        return selectinfo;
    }

    /**
     * 獲取待選擇要素列表名稱
     * @param selectFeatureInfoList 待選中要素列表信息
     * @return
     */
    private String[] getSelectFeatureInfoListName(List<SelectFeatureInfo> selectFeatureInfoList) {
        List<String> lsname = new ArrayList<>();
        for (int i=0;i<selectFeatureInfoList.size();i++){
            lsname.add(selectFeatureInfoList.get(i).featureLayer.getName());
        }
        return lsname.toArray(new String[lsname.size()]);
    }

    /**
     * 記錄當前選中要素信息
     */
    public class SelectFeatureInfo{
        public FeatureLayer featureLayer ;//當前選中要素
        public long selectFeatureID ;//當前選中要素ID
    }
} 

三、完整代碼

完整代碼不按期更新,具體請查閱DEMOt源代碼,託管地址:http://git.oschina.net/gis-luq/RuntimeOfflineEdit

 四、運行後編輯結果(以備同步測試使用)

轉載請註明出處:http://www.cnblogs.com/gis-luq/p/5858055.html 

相關內容列表

《ArcGIS Runtime SDK for Android開發筆記》——離在線一體化技術:概述

《ArcGIS Runtime SDK for Android開發筆記》——離在線一體化技術:離線矢量數據下載

《ArcGIS Runtime SDK for Android開發筆記》——離在線一體化技術:離線矢量數據編輯

《ArcGIS Runtime SDK for Android開發筆記》——離在線一體化技術:離線矢量數據同步

《ArcGIS Runtime SDK for Android開發筆記》——數據製做篇:發佈具備同步能力的FeatureService服務

相關文章
相關標籤/搜索