Skip to content

Latest commit

 

History

History

README.md

GeoView-Compose

The GeoView-Compose module provides @Composable implementations of the MapView, SceneView and LocalSceneView with a Compose-idiomatic API.

image

View the API Reference for the geoview-compose module here.

Features

Display a Map

Displaying a map on the screen looks like this:

val arcGISMap = remember { ArcGISMap(BasemapStyle.ArcGISImagery) }
MapView(
	modifier = Modifier.fillMaxSize(),
	arcGISMap = arcGISMap
)

Respond to User Input

The composable MapView, SceneView, and LocalSceneView exposes gesture events as lambda callback parameters:

val arcGISMap = remember { ArcGISMap(BasemapStyle.ArcGISImagery) }
MapView(
	modifier = Modifier.fillMaxSize(),
	arcGISMap = arcGISMap,
	onSingleTapConfirmed = { singleTapConfirmedEvent ->
		val x = singleTapConfirmedEvent.screenCoordinate.x
		val y = singleTapConfirmedEvent.screenCoordinate.y
		Log.i("MapView", "Single tap at $x, $y")
	}
)

Set a Viewpoint

To set a viewpoint, create a MapViewProxy and call setViewpoint() on it after the MapView is displayed on screen:

val point = Point(-117.182541, 34.055569, SpatialReference.wgs84())
val scale = 170000.0
val mapViewProxy = remember { MapViewProxy() }

Button(
    onClick = {
        mapViewProxy.setViewpoint(point, scale)
    }
) {
    Text("Set Viewpoint")
}
MapView(
    modifier = Modifier.fillMaxSize(),
    arcGISMap = remember { ArcGISMap(BasemapStyle.ArcGISImagery) },
    mapViewProxy = mapViewProxy,
)

Note that the viewpoint of the MapView will automatically be persisted across configuration changes and process death. How this behaves can be customized by supplying the viewpointPersistence parameter to the MapView

MapView(
    modifier = Modifier.fillMaxSize(),
    arcGISMap = remember { ArcGISMap(BasemapStyle.ArcGISImagery) },
    viewpointPersistence = ViewpointPersistence.ByBoundingGeometry
)

Examples of how to use MapViewpointOperation and SceneViewpointOperation are available in the respective microapps:

Display the Device Location

A LocationDisplay can be used to display the device's location as a blue dot on a MapView:

val arcGISMap = remember { ArcGISMap(BasemapStyle.ArcGISImagery) }
val scope = rememberCoroutineScope()
val locationDisplay = rememberLocationDisplay {
	start(scope)
}
MapView(
	modifier = Modifier.fillMaxSize(),
	arcGISMap = remember { ArcGISMap(BasemapStyle.ArcGISImagery) },
	locationDisplay = locationDisplay
)

An example of how to display the device location is available in the MapView Location Display App.

Identify a Feature

To identify a feature, create a MapViewProxy and call identify() on it after the MapView is displayed on screen

val mapViewProxy = remember { MapViewProxy() }
val arcGISMap = remember { ArcGISMap(BasemapStyle.ArcGISImagery) }
val scope = rememberCoroutineScope()
MapView(
	modifier = Modifier.fillMaxSize(),
	arcGISMap = arcGISMap,
	mapViewProxy = mapViewProxy,
	onSingleTapConfirmed = { singleTapConfirmedEvent ->
		scope.launch {
			mapViewProxy.identify(featureLayer, singleTapConfirmedEvent.screenCoordinate, 20.dp)
		}
	}
)

An example of how to identify features and graphics is available in the MapView Identify App.

Display a Callout

To display a Callout, use the content lambda parameter of the MapView, SceneView, or LocalSceneView to call the Callout composable function:

MapView(
    modifier = Modifier.fillMaxSize(),
    arcGISMap = arcGISMapWithFeatureLayer,
    onSingleTapConfirmed = { identifyGeoElement(it) },
    content = {
        if (selectedGeoElement != null) {
            Callout(
                modifier = Modifier.wrapContentSize(),
                shapes = CalloutDefaults.shapes(
                    cornerRadius = 15.dp,
                    leaderSize = DpSize(width = 12.dp, height = 10.dp)
                ),
                colorScheme = CalloutDefaults.colors(
                    borderColor = MaterialTheme.colorScheme.outlineVariant,
                    backgroundColor = MaterialTheme.colorScheme.background
                ),
                leaderPosition = LeaderPosition.Automatic,
                geoElement = selectedGeoElement,
                tapLocation = tapLocation
            ) {
                Column { // Callout content
                    Text(text = "Tapped Point: ${tapLocation.x},${tapLocation.y}")
                }
            }
        }
    }
)

An example of how to use the Callout on a point or geo-element is available in the Callout App.

Display an OverviewMap

The Overview Map is a small, secondary Map View (sometimes called an "inset map"), that can be superimposed on an existing MapView, SceneView, or LocalSceneView, which shows a representation of the main view's current viewpoint.

Screenshot Screenshot

Basic usage for displaying an Overview Map

A simple workflow is to display the Overview Map on top of a MapView and use the viewpoint and visible area callbacks to update the overview.

There are two overloads of the Overview Map - one to use when creating an overview of a MapView and the other to use when creating an overview of a SceneView or LocalSceneView.

Use the following code to create the UI for a MapView overview

val viewpoint: MutableState<Viewpoint?> = remember { mutableStateOf(null) }
val visibleArea: MutableState<Polygon?> = remember { mutableStateOf(null) }

Box {
    MapView(
        modifier = Modifier.fillMaxSize(),
        arcGISMap = remember {
            ArcGISMap(BasemapStyle.ArcGISDarkGray)
        },
        onViewpointChangedForCenterAndScale = {
            viewpoint.value = it
        },
        onVisibleAreaChanged = {
            visibleArea.value = it
        }
    )
    OverviewMap(
        viewpoint = viewpoint.value,
        visibleArea = visibleArea.value,
        modifier = Modifier
            .size(250.dp, 200.dp)
            .padding(20.dp)
            .align(Alignment.TopEnd)
    )
}

or, for a SceneView or LocalSceneView overview

val viewpoint: MutableState<Viewpoint?> = remember { mutableStateOf(null) }

Box {
    SceneView(
        modifier = Modifier.fillMaxSize(),
        arcGISScene = remember {
            ArcGISScene(BasemapStyle.ArcGISDarkGray)
        },
        onViewpointChangedForCenterAndScale = {
            viewpoint.value = it
        },
    )
    OverviewMap(
        viewpoint = viewpoint.value,
        modifier = Modifier
            .size(250.dp, 200.dp)
            .padding(20.dp)
            .align(Alignment.TopEnd)
    )
}

Note that the overloads for OverviewMap can take a Symbol that defines how the parent view's visible map is symbolized in the overview. Any symbol provided must be suitable for a polygon geometry if the overview is for a MapView and suitable for a point geometry if the overview is for a SceneView or LocalSceneView.

Example

To see it in action, try out the Overview Map micro-app and refer to MainScreen.kt in the project.

Other Examples:

Other microapps that demonstrate various workflows with the composable MapView,SceneView, and LocalSceneView are available: