Show grid

View on GitHubSample viewer app

Display coordinate system grids including Latitude/Longitude, MGRS, UTM and USNG on a map view. Also, toggle label visibility and change the color of grid lines and grid labels.

Image of show grid

Use case

Grids are often used on printed maps, but can also be helpful on digital maps, to identify locations on a map.

How to use the sample

Tap on the Grid options button in the toolbar to open a settings view. You can select type of grid from Grid Type (LatLong, MGRS, UTM and USNG) and modify its properties like label visibility, grid line color, and grid label color.

How it works

  1. Create an instance of one of the Grid types.
  2. Grid lines and labels can be styled per grid level with setLineSymbol(gridLevel, lineSymbol) and setTextSymbol(gridLevel, textSymbol) methods on the grid.
  3. The label position can be set with grid.labelPosition method on the grid.
  4. For the LatitudeLongitudeGrid type, you can specify a label format of DecimalDegrees or DegreesMinutesSeconds.
  5. To set the grid, use the MapView.grid(myGrid) method on the map view.

Relevant API

  • Grid
  • LatitudeLongitudeGrid
  • MapView
  • MgrsGrid
  • SimpleLineSymbol
  • TextSymbol
  • UsngGrid
  • UtmGrid

Tags

coordinates, degrees, graticule, grid, latitude, longitude, mgrs, minutes, seconds, usng, utm

Sample Code

MainActivity.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
/* Copyright 2023 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.showgrid

import android.os.Bundle
import android.util.Log
import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.arcgismaps.ApiKey
import com.arcgismaps.ArcGISEnvironment
import com.arcgismaps.Color
import com.arcgismaps.geometry.Point
import com.arcgismaps.geometry.SpatialReference
import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.BasemapStyle
import com.arcgismaps.mapping.Viewpoint
import com.arcgismaps.mapping.symbology.HorizontalAlignment
import com.arcgismaps.mapping.symbology.LineSymbol
import com.arcgismaps.mapping.symbology.SimpleLineSymbol
import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle
import com.arcgismaps.mapping.symbology.TextSymbol
import com.arcgismaps.mapping.symbology.VerticalAlignment
import com.arcgismaps.mapping.view.GridLabelPosition
import com.arcgismaps.mapping.view.LatitudeLongitudeGrid
import com.arcgismaps.mapping.view.LatitudeLongitudeGridLabelFormat
import com.arcgismaps.mapping.view.MgrsGrid
import com.arcgismaps.mapping.view.UsngGrid
import com.arcgismaps.mapping.view.UtmGrid
import com.esri.arcgismaps.sample.showgrid.databinding.ShowGridActivityMainBinding
import com.esri.arcgismaps.sample.showgrid.databinding.PopupDialogBinding
import com.google.android.material.button.MaterialButton
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar

class MainActivity : AppCompatActivity() {

    // set up data binding for the activity
    private val activityMainBinding: ShowGridActivityMainBinding by lazy {
        DataBindingUtil.setContentView(this, R.layout.show_grid_activity_main)
    }

    private val mapView by lazy {
        activityMainBinding.mapView
    }

    private val menuButton: MaterialButton by lazy {
        activityMainBinding.menuButton
    }

    // create a point to focus the map on in Quebec province
    private val center: Point = Point(
        -7702852.905619, 6217972.345771, SpatialReference(3857)
    )

    // the selected line color of the grid
    private var lineColor: Color = Color.white

    // the selected label color of the grid
    private var labelColor: Color = Color.white

    // the selected label position of the grid
    private var labelPosition: GridLabelPosition = GridLabelPosition.AllSides

    // boolean set if the layer is visible
    private var isLabelVisible = true

    // create a popup dialog to manage grid settings
    private val popUpDialogBinding by lazy {
        PopupDialogBinding.inflate(layoutInflater)
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // authentication with an API key or named user is
        // required to access basemaps and other location services
        ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.ACCESS_TOKEN)
        lifecycle.addObserver(mapView)

        mapView.apply {
            // create a map with imagery basemap
            map = ArcGISMap(BasemapStyle.ArcGISImagery)
            // set the initial viewpoint of the map
            setViewpoint(Viewpoint(center, 23227.0))
            // set defaults on grid
            grid = LatitudeLongitudeGrid()
        }

        val dialog = MaterialAlertDialogBuilder(this@MainActivity).apply {
            setView(popUpDialogBinding.root)
            setTitle(getString(R.string.change_grid_button))
        }.create()

        // set up options in popup menu
        // create drop-down list of different layer types
        setupLayerDropdown(popUpDialogBinding)

        // create drop-down list of different line colors
        setupLineColorDropdown(popUpDialogBinding)

        // create drop-down list of different label colors
        setupLabelColorDropdown(popUpDialogBinding)

        // create drop-down list of different label positions
        setupLabelPositionDropdown(popUpDialogBinding)

        // setup the checkbox to change the visibility of the labels
        setupLabelsCheckbox(popUpDialogBinding)

        // display pop-up box when button is clicked
        menuButton.setOnClickListener {
            dialog.show()
        }
    }

    /**
     * Sets up the [popupDialogBinding] for selecting a grid type
     * and handles behavior for when a new grid type is selected.
     */
    private fun setupLayerDropdown(popupDialogBinding: PopupDialogBinding) {
        popupDialogBinding.gridTypeDropdown.apply {
            // set the grid type adapter
            setAdapter(ArrayAdapter(
                applicationContext,
                com.esri.arcgismaps.sample.sampleslib.R.layout.custom_dropdown_item,
                resources.getStringArray(R.array.layers_array))
            )

            // set the grid type click listener
            onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
                when (position) {
                    0 -> {
                        // LatitudeLongitudeGrid can have a label format of DecimalDegrees or DegreesMinutesSeconds
                        mapView.grid = LatitudeLongitudeGrid().apply {
                            labelFormat = LatitudeLongitudeGridLabelFormat.DecimalDegrees
                        }
                        mapView.setViewpoint(Viewpoint(center, 23227.0))
                    }
                    1 -> {
                        mapView.grid = MgrsGrid()
                        mapView.setViewpoint(Viewpoint(center, 23227.0))
                    }
                    2 -> {
                        mapView.grid = UtmGrid()
                        mapView.setViewpoint(Viewpoint(center, 10000000.0))
                    }
                    3 -> {
                        mapView.grid = UsngGrid()
                        mapView.setViewpoint(Viewpoint(center, 23227.0))
                    }
                    else -> return@OnItemClickListener showError("Unsupported option")
                }

                // make sure settings persist on grid type change
                setLabelVisibility(isLabelVisible)
                changeGridColor(lineColor)
                changeLabelColor(labelColor)
            }
        }
    }

    /**
     * Sets up the [popupDialogBinding] for selecting a grid color and
     * handles behavior for when a new line color is selected.
     */
    private fun setupLineColorDropdown(popupDialogBinding: PopupDialogBinding) {
        popupDialogBinding.gridColorDropdown.apply {
            // set the grid color adapter
            setAdapter(ArrayAdapter(
                applicationContext,
                com.esri.arcgismaps.sample.sampleslib.R.layout.custom_dropdown_item,
                resources.getStringArray(R.array.colors_array))
            )

            // set the grid color click listener
            onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
                lineColor = when (position) {
                    0 -> Color.red
                    1 -> Color.white
                    2 -> Color.blue
                    else -> return@OnItemClickListener showError("Unsupported option")
                }
                changeGridColor(lineColor)
            }
        }
    }

    /**
     * Sets up the [popupDialogBinding] for selecting a label color
     * and handles behavior for when a new label color is selected.
     */
    private fun setupLabelColorDropdown(popupDialogBinding: PopupDialogBinding) {
        popupDialogBinding.labelColorDropdown.apply {
            setAdapter(ArrayAdapter(
                applicationContext,
                com.esri.arcgismaps.sample.sampleslib.R.layout.custom_dropdown_item,
                resources.getStringArray(R.array.colors_array))
            )
            onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
                // change grid labels color
                labelColor = when (position) {
                    0 -> Color.red
                    1 -> Color.white
                    2 -> Color.blue
                    else -> return@OnItemClickListener showError("Unsupported option")
                }
                changeLabelColor(labelColor)
            }
        }
    }

    /**
     * Sets up the [popupDialogBinding] for selecting a label position relative to the grid
     * and handles behavior for when a label position is selected.
     */
    private fun setupLabelPositionDropdown(popupDialogBinding: PopupDialogBinding) {
        popupDialogBinding.labelPositionDropdown.apply {
            setAdapter(ArrayAdapter(
                applicationContext,
                com.esri.arcgismaps.sample.sampleslib.R.layout.custom_dropdown_item,
                resources.getStringArray(R.array.positions_array))
            )

            onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
                // set the label position
                labelPosition = when (position) {
                    0 -> GridLabelPosition.AllSides
                    1 -> GridLabelPosition.BottomLeft
                    2 -> GridLabelPosition.BottomRight
                    3 -> GridLabelPosition.Center
                    4 -> GridLabelPosition.Geographic
                    5 -> GridLabelPosition.TopLeft
                    6 -> GridLabelPosition.TopRight
                    else -> return@OnItemClickListener showError("Unsupported option")
                }
                changeLabelPosition(labelPosition)
            }
        }
    }

    /**
     * Sets up the [popupDialogBinding] for the checkbox making labels visible or invisible.
     */
    private fun setupLabelsCheckbox(popupDialogBinding: PopupDialogBinding) {
        popupDialogBinding.labelsCheckBox.apply {
            isChecked = true
            // hide and show label visibility when the checkbox is clicked
            setOnClickListener {
                isLabelVisible = isChecked
                setLabelVisibility(isLabelVisible)
            }
        }
    }

    /**
     * Sets the labels visibility based on [isVisible].
     */
    private fun setLabelVisibility(isVisible: Boolean) {
        val grid = mapView.grid ?: return
        grid.labelVisibility = isVisible
    }

    /**
     * Sets the [color] of the grid lines.
     */
    private fun changeGridColor(color: Color) {
        val grid = mapView.grid ?: return
        val gridLevels = grid.levelCount
        for (gridLevel in 0 until gridLevels) {
            val lineSymbol: LineSymbol =
                SimpleLineSymbol(SimpleLineSymbolStyle.Solid, color, (gridLevel + 1).toFloat())
            grid.setLineSymbol(gridLevel, lineSymbol)
        }
    }

    /**
     * Sets the [labelColor] of the labels on the grid.
     */
    private fun changeLabelColor(labelColor: Color) {
        val grid = mapView.grid ?: return
        val gridLevels = grid.levelCount
        for (gridLevel in 0 until gridLevels) {
            val textSymbol = TextSymbol().apply {
                color = labelColor
                size = 14f
                horizontalAlignment = HorizontalAlignment.Left
                verticalAlignment = VerticalAlignment.Bottom
                haloColor = Color.black
                haloWidth =  5f
            }
            grid.setTextSymbol(gridLevel, textSymbol)
        }
    }

    /**
     * Sets the [labelPosition] of the labels on the grid.
     */
    private fun changeLabelPosition(labelPosition: GridLabelPosition) {
        val grid = mapView.grid ?: return
        grid.labelPosition = labelPosition
    }

    private fun showError(message: String) {
        Log.e(localClassName, message)
        Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show()
    }
}

private val Color.Companion.blue: Color
    get() {
        return fromRgba(0, 0, 255, 255)
    }

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