需求:
ArcGIS Runtime SDK for Android 100在场景视图中点击模型,如何弹窗显示模型的属性信息
最终效果图:
仅演示了属性弹窗显示,如果觉得弹窗的界面丑,请自行调整UI样式。
测试版本:
arcgis runtime for android100.10
思路:
1、ArcGIS SceneServices有7种不同的数据类型, 但是ArcGIS Runtime只支持4种,如下:
- 3D Objects (in
ArcGISSceneLayer
) - Point features (
ArcGISSceneLayer
) - Integrated mesh (in
ArcGISSceneLayer
ORIntegratedMeshLayer
) - Point cloud (in
PointCloudLayer
only)
其中如果是3d object(传统建模数据)或者点要素生成的三维场景服务,则可以支持点击查询对应要素的属性信息。
2、代码思路:通过点击场景视图中的模型,弹窗显示模型的属性信息。
package com.esri.arcgisruntime.scenelayerselection;
import java.util.List;
import java.util.concurrent.ExecutionException;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.PopupWindow;
import android.widget.Toast;
import com.esri.arcgisruntime.concurrent.ListenableFuture;
import com.esri.arcgisruntime.data.Feature;
import com.esri.arcgisruntime.layers.ArcGISSceneLayer;
import com.esri.arcgisruntime.loadable.LoadStatus;
import com.esri.arcgisruntime.mapping.ArcGISScene;
import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource;
import com.esri.arcgisruntime.mapping.Basemap;
import com.esri.arcgisruntime.mapping.GeoElement;
import com.esri.arcgisruntime.mapping.Surface;
import com.esri.arcgisruntime.mapping.view.Camera;
import com.esri.arcgisruntime.mapping.view.DefaultSceneViewOnTouchListener;
import com.esri.arcgisruntime.mapping.view.IdentifyLayerResult;
import com.esri.arcgisruntime.mapping.view.SceneView;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private SceneView mSceneView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// create a scene and add a basemap to it
ArcGISScene scene = new ArcGISScene();
scene.setBasemap(Basemap.createImagery());
// set the scene to the scene view
mSceneView = findViewById(R.id.sceneView);
mSceneView.setScene(scene);
// add base surface with elevation data
Surface surface = new Surface();
final String elevationService = getString(R.string.world_elevation_url);
surface.getElevationSources().add(new ArcGISTiledElevationSource(elevationService));
scene.setBaseSurface(surface);
// add a scene layer of Harvard buildings to the scene
final String buildings = getString(R.string.brest_buildings);
ArcGISSceneLayer sceneLayer = new ArcGISSceneLayer(buildings);
scene.getOperationalLayers().add(sceneLayer);
// add a camera and initial camera position
Camera camera = new Camera(48.378, -4.494, 200, 345, 65, 0);
mSceneView.setViewpointCamera(camera);
// zoom to the layer's extent when loaded
sceneLayer.addDoneLoadingListener(() -> {
if (sceneLayer.getLoadStatus() == LoadStatus.LOADED) {
// when the scene is clicked, identify the clicked feature and select it
mSceneView.setOnTouchListener(new DefaultSceneViewOnTouchListener(mSceneView) {
@Override
public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
// clear any previous selection
sceneLayer.clearSelection();
android.graphics.Point screenPoint = new android.graphics.Point(Math.round(motionEvent.getX()),
Math.round(motionEvent.getY()));
// identify clicked feature
ListenableFuture<IdentifyLayerResult> identify = mSceneView
.identifyLayerAsync(sceneLayer, screenPoint, 10, false, 1);
identify.addDoneListener(() -> {
try {
// get the identified result and check that it is a feature
IdentifyLayerResult result = identify.get();
List<GeoElement> geoElements = result.getElements();
if (!geoElements.isEmpty()) {
Log.d(TAG, "geoelement not empty");
GeoElement geoElement = geoElements.get(0);
if (geoElement instanceof Feature) {
// select the feature
sceneLayer.selectFeature((Feature) geoElement);
Log.d("attributes", geoElement.getAttributes().toString());
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setMessage(geoElement.getAttributes().toString());
dialog.show();
}
}
} catch (InterruptedException | ExecutionException e) {
String error = "Error while identifying layer result: " + e.getMessage();
Log.e(TAG, error);
Toast.makeText(MainActivity.this, error, Toast.LENGTH_LONG).show();
}
});
return true;
}
});
} else if (sceneLayer.getLoadStatus() == LoadStatus.FAILED_TO_LOAD) {
String error = "Error loading scene layer " + sceneLayer.getLoadStatus();
Log.e(TAG, error);
Toast.makeText(this, error, Toast.LENGTH_LONG).show();
}
});
}
@Override
protected void onPause() {
super.onPause();
mSceneView.pause();
}
@Override
protected void onResume() {
super.onResume();
mSceneView.resume();
}
@Override
protected void onDestroy() {
super.onDestroy();
mSceneView.dispose();
}
}
其实就是官网的这个代码,只是我加了一个以对话框的方式弹窗显示。
官网链接:https://developers.arcgis.com/android/java/sample-code/scene-layer-selection/