Skip to content
View on GitHubSample viewer app

Change the style of a Web Map Service (WMS) layer.

Image of apply style to WMS layer

Use case

Layers hosted on WMS may have different pre-set styles available to apply to them. Swapping between these styles can help during visual examination of the data. For example, increasing the contrast of satellite images can help in identifying urban and agricultural areas within forested areas.

How to use the sample

Once the layer loads, the toggle button will be enabled. Click it to toggle between the first and second styles of the WMS layer.

How it works

  1. Create a WmsLayer specifying the URL of the service and the layer names you want WmsLayer(url, names).
  2. When the layer is done loading, get it's list of style strings using wmsLayer.layerInfos.firstOrNull()?.styles.
  3. Set one of the styles using wmsSublayer.currentStyle = styleString.

Relevant API

  • WmsLayer
  • WmsSublayer
  • WmsSublayerInfo

About the data

This sample uses a public service managed by the State of Minnesota and provides composite imagery for the state and the surrounding areas.

Tags

imagery, styles, visualization, WMS

Sample Code

ApplyStyleToWMSLayerViewModel.ktApplyStyleToWMSLayerViewModel.ktMainActivity.ktApplyStyleToWMSLayerScreen.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
/* 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.applystyletowmslayer.components

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.arcgismaps.geometry.SpatialReference
import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.Viewpoint
import com.arcgismaps.mapping.layers.WmsLayer
import com.arcgismaps.mapping.layers.WmsSublayer
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

class ApplyStyleToWmsLayerViewModel(app: Application) : AndroidViewModel(app) {
    // WMS layer displaying Minnesota's county boundaries with multiple styles.
    private val wmsLayer = WmsLayer(
        url = "https://imageserver.gisdata.mn.gov/cgi-bin/mncomp?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities",
        layerNames = listOf("mncomp")
    )

    // Map used by the MapView.
    val arcGISMap = ArcGISMap(SpatialReference(wkid = 26915)).apply {
        // apply a min scale
        minScale = 7_000_000.0
        // Add the WMS layer to the map's operational layers
        operationalLayers.add(wmsLayer)
    }

    // MapViewProxy used to perform viewpoint operations.
    val mapViewProxy = MapViewProxy()

    // Message dialog ViewModel for error reporting.
    val messageDialogVM = MessageDialogViewModel()

    // Flow of available WMS styles.
    private val _styles = MutableStateFlow<List<String>>(emptyList())
    val styles = _styles.asStateFlow()

    // Selected style index.
    private val _selectedStyleIndex = MutableStateFlow(0)
    val selectedStyleIndex = _selectedStyleIndex.asStateFlow()

    // The WMS sublayer for which we will change the style.
    private var wmsSublayer: WmsSublayer? = null

    init {
        viewModelScope.launch {
            createAndLoadWmsLayer()
        }
    }

    /**
     * Creates the WMS layer, loads it, zooms to its full extent, and exposes its styles.
     */
    private suspend fun createAndLoadWmsLayer() {
        wmsLayer.load().onSuccess {
            // Zoom to the full extent of the WMS layer, if available
            wmsLayer.fullExtent?.let { fullExtent ->
                mapViewProxy.setViewpointAnimated(Viewpoint(boundingGeometry = fullExtent))
            }

            // Get the first WMS sublayer
            wmsSublayer = wmsLayer.sublayers.value.firstOrNull() as? WmsSublayer

            // Obtain available styles from the WMS layer info
            val styles = wmsLayer.layerInfos.firstOrNull()?.styles ?: emptyList()
            if (styles.isEmpty()) {
                messageDialogVM.showMessageDialog("No styles found for the WMS layer.")
                return@onSuccess
            }

            _styles.value = styles
            // Set initial selection to the first available style
            _selectedStyleIndex.value = 0
            wmsSublayer?.currentStyle = styles[0]
        }.onFailure { error ->
            messageDialogVM.showMessageDialog(error)
        }
    }

    /**
     * Updates the selected style by index and applies it to the WMS sublayer.
     */
    fun updateSelectedStyle(index: Int) {
        val styles = _styles.value
        if (index in styles.indices) {
            _selectedStyleIndex.value = index
            wmsSublayer?.currentStyle = styles[index]
        }
    }
}

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