Editing existing geometries
This topic covers the steps that are required to enable the device to edit existing feature geometries.
What do I need to enable editing of existing geometries?
There are three basic steps required to enable the device to edit existing features:
- Select the feature to be edited and display the geometry to the user.
- Provide tools for the user to edit the geometry, for example, drag vertices or perform geometry operations such as split, merge, or cut.
- Apply the edits to the server.
Selecting features
The feature layer includes a special selection mode to make feature selections easy. When you instantiate the feature layer, you can set this using the ArcGISFeatureLayer.MODE class and pass it to the constructor or the ArcGISFeatureLayer.OPTIONS class. In this mode, features are only retrieved from the server when they are selected. As a backdrop to this layer, you can provide an additional dynamic map service layer to show all available features; this is recommended for various performance reasons. To select features, you need to create a Query object and call the selectFeatures() method on the feature layer and pass in a callback. Please refer to the AttributeEditor sample within the ArcGIS Rumtime SDK for Android to show how to do this.
Providing editing tools
To provide editing tools, you need to hook up various touch listeners on the MapView object to respond to user events. This could include clicking a vertex on a polygon so that it can be moved. The GeometryEngine class, which provides local geometric operations on the device (rather than a geometry service running on an instance of ArcGIS Server), provides lots of methods to help you perform geometry edits. For selecting a vertex, GeometryEngine has a getNearestVertex() method, which takes a point and a geometry (the selected feature in this case) and returns the vertex in the geometry closest to the point. You can then show this vertex on the screen and provide additional touch listeners so that the user can move it.
GeometryEngine also provides a large array of geometric operations such as clips, buffers, and unions. These can be used in conjunction with new graphic features on the map to edit existing selected features, such as clipping an existing polygon using a newly drawn polygon.
Applying the edits
Editing the geometry of an existing feature is a feature update (rather than an addition or deletion, which are the other editing operation types). To do this, you use the ArcGISFeatureLayer.applyEdits() asynchronous method. Updated graphics are passed in as the third argument. The updated Graphic object does not have to include many attributes, but it must include the ObjectID attribute for the edit to succeed. The following method shows this:
/**
* Applies updates to an existing geometry.
*/
public void applyGeometryUpdates(Geometry geometry, String ObjectID, ArcGISFeatureLayer featureLayer, SimpleMarkerSymbol symbol) {
// set the object Id and geometry on a graphic
Map<String, Object> attr = new HashMap<String, Object>();
attr.put(featureLayer.getObjectIdField(), ObjectID);
graphic = new Graphic(geometry, symbol, attr, null);
featureLayer.applyEdits(null, null, new Graphic[] { graphic },
new CallbackListener<FeatureEditResult[][]>() {
public void onError(Throwable error) {
// TODO implement error code
}
public void onCallback(FeatureEditResult[][] editResult) {
// Check the response for success or failure
if (editResult[2] != null && editResult[2][0] != null && editResult[2][0].isSuccess()) {
// TODO implement success logic
}
}
});
}
A new CallbackListener needs to be created to handle the asynchronous response from the applyEdits() method. The onCallback() method receives a FeatureEditResult[ ][ ] multidimensional array object. This result object contains FeatureEditResult objects for every addition, deletion, and update. In the code above, editResult[0] provide addition results; editResult[1], deletion results; and editResult[2], update results. FeatureEditResult is returned for every feature edit. The case above expects one result, which would be referenced by the following: editResult[2][0].
The onCallback() method is called even if there is an error with the edits, so you need to add some code like the above to check for success or failure. The onError() method will also fire after this method if there has been an error.