Skip to content

Commit 91f673e

Browse files
gunt0001Copilotshubham7109
authored
Sample - Monitor changes to draw status (#430)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Shubham Sharma <shubhamsharma@esri.com>
1 parent ab73081 commit 91f673e

File tree

9 files changed

+343
-0
lines changed

9 files changed

+343
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Monitor changes to draw status
2+
3+
Get the draw status of your map view or scene view to know when all layers in the map or scene have finished drawing.
4+
5+
![Image of monitor changes to draw status](monitor-changes-to-draw-status.png)
6+
7+
## Use case
8+
9+
Display an indicator of layers drawing.
10+
11+
## How to use the sample
12+
13+
1. Pan and zoom around the map.
14+
2. Observe the draw status text in the toolbar and the progress indicator while the map is drawing.
15+
16+
## How it works
17+
18+
1. Create an `ArcGISMap`.
19+
2. Pass the `ArcGISMap` to the Compose `MapView`.
20+
3. Use the MapView's `onDrawStatusChanged` callback to receive `DrawStatus` updates
21+
22+
## Relevant API
23+
24+
* ArcGISMap
25+
* DrawStatus
26+
* MapView
27+
28+
## Tags
29+
30+
draw, loading, map, render
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"category": "Maps",
3+
"description": "Get the draw status of your map view or scene view to know when all layers in the map or scene have finished drawing.",
4+
"formal_name": "MonitorChangesToDrawStatus",
5+
"ignore": false,
6+
"images": [
7+
"monitor-changes-to-draw-status.png"
8+
],
9+
"keywords": [
10+
"draw",
11+
"loading",
12+
"map",
13+
"render",
14+
"ArcGISMap",
15+
"DrawStatus",
16+
"MapView"
17+
],
18+
"language": "kotlin",
19+
"redirect_from": "",
20+
"relevant_apis": [
21+
"ArcGISMap",
22+
"DrawStatus",
23+
"MapView"
24+
],
25+
"snippets": [
26+
"src/main/java/com/esri/arcgismaps/sample/monitorchangestodrawstatus/components/MonitorDrawStatusViewModel.kt",
27+
"src/main/java/com/esri/arcgismaps/sample/monitorchangestodrawstatus/MainActivity.kt",
28+
"src/main/java/com/esri/arcgismaps/sample/monitorchangestodrawstatus/screens/MonitorDrawStatusScreen.kt"
29+
],
30+
"title": "Monitor changes to draw status"
31+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
plugins {
2+
alias(libs.plugins.arcgismaps.android.library)
3+
alias(libs.plugins.arcgismaps.android.library.compose)
4+
alias(libs.plugins.arcgismaps.kotlin.sample)
5+
alias(libs.plugins.gradle.secrets)
6+
}
7+
8+
secrets {
9+
// this file doesn't contain secrets, it just provides defaults which can be committed into git.
10+
defaultPropertiesFileName = "secrets.defaults.properties"
11+
}
12+
13+
android {
14+
namespace = "com.esri.arcgismaps.sample.monitorchangestodrawstatus"
15+
buildFeatures {
16+
buildConfig = true
17+
}
18+
}
19+
20+
dependencies {
21+
// Only module specific dependencies needed here
22+
}
254 KB
Loading
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
<uses-permission android:name="android.permission.INTERNET" />
5+
6+
<application>
7+
<activity
8+
android:exported="true"
9+
android:name=".MainActivity"
10+
android:label="@string/monitor_changes_to_draw_status_app_name" />
11+
</application>
12+
13+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/* Copyright 2025 Esri
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*
15+
*/
16+
17+
package com.esri.arcgismaps.sample.monitorchangestodrawstatus
18+
19+
import android.os.Bundle
20+
import androidx.activity.ComponentActivity
21+
import androidx.activity.compose.setContent
22+
import androidx.compose.material3.MaterialTheme
23+
import androidx.compose.material3.Surface
24+
import androidx.compose.runtime.Composable
25+
import com.arcgismaps.ApiKey
26+
import com.arcgismaps.ArcGISEnvironment
27+
import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme
28+
import com.esri.arcgismaps.sample.monitorchangestodrawstatus.screens.MonitorDrawStatusScreen
29+
30+
class MainActivity : ComponentActivity() {
31+
32+
override fun onCreate(savedInstanceState: Bundle?) {
33+
super.onCreate(savedInstanceState)
34+
// authentication with an API key or named user is
35+
// required to access basemaps and other location services
36+
ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.ACCESS_TOKEN)
37+
38+
setContent {
39+
SampleAppTheme {
40+
MonitorChangesToDrawStatusApp()
41+
}
42+
}
43+
}
44+
45+
@Composable
46+
private fun MonitorChangesToDrawStatusApp() {
47+
Surface(color = MaterialTheme.colorScheme.background) {
48+
MonitorDrawStatusScreen(
49+
sampleName = getString(R.string.monitor_changes_to_draw_status_app_name)
50+
)
51+
}
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* Copyright 2025 Esri
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*
15+
*/
16+
17+
package com.esri.arcgismaps.sample.monitorchangestodrawstatus.components
18+
19+
import android.app.Application
20+
import androidx.lifecycle.AndroidViewModel
21+
import androidx.lifecycle.viewModelScope
22+
import com.arcgismaps.mapping.ArcGISMap
23+
import com.arcgismaps.mapping.BasemapStyle
24+
import com.arcgismaps.mapping.Viewpoint
25+
import com.arcgismaps.geometry.Point
26+
import com.arcgismaps.geometry.SpatialReference
27+
import com.arcgismaps.mapping.view.DrawStatus
28+
import com.esri.arcgismaps.sample.sampleslib.components.MessageDialogViewModel
29+
import kotlinx.coroutines.flow.MutableStateFlow
30+
import kotlinx.coroutines.flow.asStateFlow
31+
import kotlinx.coroutines.launch
32+
33+
/**
34+
* ViewModel for the Monitor changes to draw status sample.
35+
*
36+
* Exposes an ArcGISMap and a flow indicating whether the map is currently drawing
37+
* so the UI can react (show a progress indicator and status text).
38+
*/
39+
class MonitorDrawStatusViewModel(application: Application) : AndroidViewModel(application) {
40+
41+
// Create a map shown by the sample
42+
val arcGISMap: ArcGISMap = ArcGISMap(BasemapStyle.ArcGISTopographic).apply {
43+
// Center the map on San Francisco
44+
initialViewpoint = Viewpoint(
45+
center = Point(
46+
x = -13623300.0,
47+
y = 4548100.0,
48+
spatialReference = SpatialReference.webMercator()
49+
),
50+
scale = 32e4
51+
)
52+
}
53+
54+
// Flow exposing whether the map is currently drawing.
55+
// true when DrawStatus is InProgress, false otherwise.
56+
private val _mapIsDrawing = MutableStateFlow(false)
57+
val mapIsDrawing = _mapIsDrawing.asStateFlow()
58+
59+
// Message dialog view model to show errors if map load fails
60+
val messageDialogVM = MessageDialogViewModel()
61+
62+
init {
63+
// Load the map and surface any errors via the MessageDialogViewModel.
64+
viewModelScope.launch {
65+
arcGISMap.load().onFailure { error ->
66+
// Surface the error so the UI can present a dialog
67+
messageDialogVM.showMessageDialog(error)
68+
}
69+
}
70+
}
71+
72+
/**
73+
* Update the draw status observed from the MapView composable.
74+
*/
75+
fun updateDrawStatus(drawStatus: DrawStatus) {
76+
_mapIsDrawing.value = drawStatus == DrawStatus.InProgress
77+
}
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/* Copyright 2025 Esri
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*
15+
*/
16+
17+
package com.esri.arcgismaps.sample.monitorchangestodrawstatus.screens
18+
19+
import androidx.compose.foundation.layout.Box
20+
import androidx.compose.foundation.layout.Column
21+
import androidx.compose.foundation.layout.fillMaxSize
22+
import androidx.compose.foundation.layout.padding
23+
import androidx.compose.material3.CircularProgressIndicator
24+
import androidx.compose.material3.MaterialTheme
25+
import androidx.compose.material3.Surface
26+
import androidx.compose.material3.Text
27+
import androidx.compose.material3.Scaffold
28+
import androidx.compose.runtime.Composable
29+
import androidx.compose.runtime.getValue
30+
import androidx.compose.ui.Alignment
31+
import androidx.compose.ui.Modifier
32+
import androidx.compose.ui.draw.shadow
33+
import androidx.compose.ui.unit.dp
34+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
35+
import androidx.lifecycle.viewmodel.compose.viewModel
36+
import com.arcgismaps.toolkit.geoviewcompose.MapView
37+
import com.esri.arcgismaps.sample.monitorchangestodrawstatus.components.MonitorDrawStatusViewModel
38+
import com.esri.arcgismaps.sample.sampleslib.components.MessageDialog
39+
import com.esri.arcgismaps.sample.sampleslib.components.SampleTopAppBar
40+
41+
/**
42+
* Main screen for the Monitor changes to draw status sample.
43+
*
44+
* The composable observes the ViewModel's mapIsDrawing flow and updates the UI
45+
* when the draw status changes. The MapView's onDrawStatusChanged callback
46+
* is used to notify the ViewModel of draw status changes.
47+
*/
48+
@Composable
49+
fun MonitorDrawStatusScreen(sampleName: String) {
50+
val viewModel: MonitorDrawStatusViewModel = viewModel()
51+
52+
// Observe whether the map is currently drawing
53+
val mapIsDrawing by viewModel.mapIsDrawing.collectAsStateWithLifecycle(false)
54+
55+
Scaffold(
56+
topBar = { SampleTopAppBar(title = sampleName) },
57+
content = { padding ->
58+
Column(modifier = Modifier
59+
.fillMaxSize()
60+
.padding(padding)) {
61+
62+
Box(modifier = Modifier.fillMaxSize()) {
63+
// Pass in the ArcGISMap from the ViewModel and the draw status callback.
64+
MapView(
65+
modifier = Modifier
66+
.fillMaxSize(),
67+
arcGISMap = viewModel.arcGISMap,
68+
// Forward draw status updates to the ViewModel
69+
onDrawStatusChanged = viewModel::updateDrawStatus
70+
)
71+
72+
// Top overlay text showing current draw status
73+
Surface(
74+
modifier = Modifier
75+
.align(Alignment.TopCenter)
76+
.padding(8.dp),
77+
color = MaterialTheme.colorScheme.surface.copy(alpha = 0.9f),
78+
tonalElevation = 2.dp
79+
) {
80+
Text(
81+
modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp),
82+
text = if (mapIsDrawing) "Drawing…" else "Drawing completed.",
83+
style = MaterialTheme.typography.labelLarge
84+
)
85+
}
86+
87+
// Center overlay: show a circular progress indicator while drawing
88+
if (mapIsDrawing) {
89+
Surface(
90+
modifier = Modifier
91+
.align(Alignment.Center)
92+
.shadow(8.dp),
93+
tonalElevation = 8.dp
94+
) {
95+
CircularProgressIndicator(modifier = Modifier.padding(24.dp))
96+
}
97+
}
98+
}
99+
100+
// Message dialog shown when ViewModel surfaces an error
101+
viewModel.messageDialogVM.apply {
102+
if (dialogStatus) {
103+
MessageDialog(
104+
title = messageTitle,
105+
description = messageDescription,
106+
onDismissRequest = ::dismissDialog
107+
)
108+
}
109+
}
110+
}
111+
}
112+
)
113+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<resources>
2+
<string name="monitor_changes_to_draw_status_app_name">Monitor changes to draw status</string>
3+
</resources>

0 commit comments

Comments
 (0)