Skip to content
View on GitHubSample viewer app

Set the map's reference scale and which feature layers should honor the reference scale.

Image of Set reference scale sample

Use case

Setting a reference scale on a map fixes the size of symbols and text to the desired height and width at that scale. As you zoom in and out, symbols and text will increase or decrease in size accordingly. When no reference scale is set, symbol and text sizes remain the same size relative to the map view.

Map annotations are typically only relevant at certain scales. For instance, annotations to a map showing a construction site are only relevant at that construction site's scale. When the map is zoomed out, that information shouldn't scale with the map view but should instead remain scaled with the map.

How to use the sample

When the sample loads, tap or click the "Map Settings" button. Use the "Reference Scale" picker to set the map's reference scale (1:500,000, 1:250,000, 1:100,000, or 1:50,000). Then tap or click the "Set to Reference Scale" button to set the map scale to the reference scale.

Tap or click "Layers" to show a list of the map's feature layers. Tap or click a layer to toggle whether that layer should honor the reference scale. Tap or click Done to dismiss the settings view.

How it works

  1. Get and set the referenceScale property on the ArcGISMap object.
  2. Get and set the scaleSymbols property on individual FeatureLayer objects.

Relevant API

  • FeatureLayer
  • Map

Additional information

The map reference scale should normally be set by the map's author and not exposed to the end user like it is in this sample.

Tags

map, reference scale, scene

Sample Code

SetReferenceScaleViewModel.ktSetReferenceScaleViewModel.ktMainActivity.ktSetReferenceScaleScreen.kt
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* Copyright 2025 Esri
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.esri.arcgismaps.sample.setreferencescale.components

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.PortalItem
import com.arcgismaps.mapping.layers.FeatureLayer
import com.arcgismaps.portal.Portal
import com.arcgismaps.toolkit.geoviewcompose.MapViewProxy
import com.esri.arcgismaps.sample.sampleslib.components.MessageDialogViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

/**
 * ViewModel to manage map, reference scale and layer toggles for the SetReferenceScale sample.
 */
class SetReferenceScaleViewModel(application: Application) : AndroidViewModel(application) {

    // Create the map from the Isle of Wight portal item.
    val arcGISMap = ArcGISMap(
        item = PortalItem(
            portal = Portal("https://www.arcgis.com"),
            itemId = "3953413f3bd34e53a42bf70f2937a408"
        )
    ).apply {
        // Set the initial reference scale.
        referenceScale = 250_000.0
    }

    // Proxy for controlling the MapView viewpoint scale.
    val mapViewProxy = MapViewProxy()

    // Reference scale options.
    val referenceScaleOptions = listOf(500_000.0, 250_000.0, 100_000.0, 50_000.0)

    // Expose the selected reference scale as a StateFlow.
    private val _selectedReferenceScale = MutableStateFlow(arcGISMap.referenceScale)
    val selectedReferenceScale = _selectedReferenceScale.asStateFlow()

    // Expose the current map scale as a StateFlow (NaN until the MapView reports a scale).
    private val _mapScale = MutableStateFlow(Double.NaN)
    val mapScale = _mapScale.asStateFlow()

    // Expose a list of layers with the map's reference scale state.
    private val _layers = MutableStateFlow<List<LayerToggleState>>(emptyList())
    val layers = _layers.asStateFlow()

    // Helper for showing errors/messages in the UI.
    val messageDialogVM = MessageDialogViewModel()

    init {
        // Load the map then build the layers list.
        viewModelScope.launch {
            arcGISMap.load().onSuccess {
                val layerStates = arcGISMap.operationalLayers
                    .filterIsInstance<FeatureLayer>()
                    .map { layer ->
                        // If layer is a FeatureLayer, access its properties.
                        LayerToggleState(
                            name = layer.name,
                            scaleSymbols = layer.scaleSymbols
                        )
                    }
                _layers.value = layerStates
            }.onFailure { throwable ->
                messageDialogVM.showMessageDialog(throwable)
            }
        }
    }

    /**
     * Called when new reference scale is selected and update the map's reference scale.
     */
    fun onReferenceScaleSelected(index: Int) {
        val scale = referenceScaleOptions[index]
        _selectedReferenceScale.value = scale
        arcGISMap.referenceScale = scale
    }

    /**
     * Called by the MapView when the map scale changes.
     */
    fun onMapScaleChanged(scale: Double) {
        _mapScale.value = scale
    }

    /**
     * Toggle whether a [FeatureLayer] instance operational layer honors the map reference scale.
     */
    fun onLayerScaleSymbolToggled(toggleState: LayerToggleState, enabled: Boolean) {
        // Set the new value for the layer's scale symbols.
        val newLayerState = toggleState.copy(scaleSymbols = enabled)
        // Update the new layer state on the map.
        arcGISMap.operationalLayers
            .filterIsInstance<FeatureLayer>()
            .find { newLayerState.name == it.name }?.apply {
                scaleSymbols = newLayerState.scaleSymbols
            }
        // Update the UI state.
        _layers.value = _layers.value.map { existingLayerState ->
            if (existingLayerState.name == newLayerState.name) newLayerState else existingLayerState
        }
    }

    /**
     * Set the map scale to the currently selected reference scale using the [mapViewProxy].
     */
    fun setMapScaleToReference() {
        viewModelScope.launch {
            mapViewProxy.setViewpointScale(_selectedReferenceScale.value)
        }
    }
}

// Data class representing a UI row for an operational layer of the map.
data class LayerToggleState(val name: String, val scaleSymbols: Boolean)

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.