How do I select which layers are visible in my MMPK app

1497
6
12-27-2017 12:03 PM
MervynLotter
Occasional Contributor III

Hi there

I have developed a simple offline app using the Open Mobile Map (mmpk) template. I would now like to provide the user with the ability to select which MMPK layers should be displayed in the app (interactively). This would be similar to the Table Of Contents where a user can select which layers to display.

I was unable to find any templates or examples of this and would really appreciate some code or examples to study and apply to my offline app.

Thank you and I wish all of you all of the best for the New Year.

Regards

Mervyn

Tags (2)
0 Kudos
6 Replies
nakulmanocha
Esri Regular Contributor

MMPK is basically collection of maps. Each map has a basemap and operationalLayers irrespective of it is an online map or offline. You will be able to get the layers using map.operationalLayers property. It returns the Layer model. Every layer has a layerVisible property which you can use. This is already done in MapViewer template. Please check the source code for MapViewer if you would like

Map QML Type | ArcGIS for Developers 

Nakul

0 Kudos
MervynLotter
Occasional Contributor III

Hi Nakul

Thank you for quick reply. Unfortunately, for my level of expertise, the

MapViewer app is not that easy to navigate and understand. I now know how

to import "controls' but I am not sure how to call up the "views" - not

even sure if they do get called. Under the "MapPage.qml" view folder I

found reference to the mapView.map.operationalLayers (see below) but I dont

even know how to link these to a menu or list of options or MyApp.qml code.

function procLayers (layers) {

if (!layers) layers = mapView.map.operationalLayers

var count = layers.count || layers.length

for (var i=count; i--;) {

var layer

try {

layer = layers.get(i)

} catch (err) {

layer = layers

}

if (!layer) continue

if (layer.subLayerContents.length) {

procLayers(layer.subLayerContents)

} else {

mapView.contentListModel.append({

"checkBox": layer.visible,

"name": layer.name,

"layerId": layer.layerId

})

}

layer.onLoadErrorChanged.connect(function () {

//app.messageDialog.show(layer.loadError.message,

layer.loadError.additionalMessage)

mapView.layersWithErrorMessages.append({

"layer": layer,

"verified": false

})

})

}

}

Is there perhaps a simpler example that you can provide for

operationalising the selection of layers or a perhaps a document that

explains how the MapViewer app is structured and functions?

I know this is now off the point but I find the availability of help

and resources limited for those non-programmers trying to get to grips

with AppStudio. The ArcGIS Runtime SDK for Qt site

(https://developers.arcgis.com/qt/latest/qml/sample-code/sample-qt-main-page.htm)

is somewhat useful but not all of the example code works seamlessly in

AppStudio. I tried cutting and pasting several of the code snippets

this evening and only some worked.I did change the import statements

before trying to run the code but I wish there was a dedicated website

site for AppStudio related code snippets and help.

Regards

Mervyn

0 Kudos
nakulmanocha
Esri Regular Contributor

Please create a Esri support ticket if you would like. They can't give you a complete sample. But atleast can provide you a simple proof of concept on how to use operational Layer List model and will be able to help you better understand on how runtime works. 

MervynLotter
Occasional Contributor III

Hi Nakul

This does seem somewhat drastic for what I thought was a relatively simple request but I am happy to do so. Googling "Esri support" directs me to (1) Esri's Community Support, which is GeoNet, and (2) Esri's Technical Support, which is obviously Esri's technical support.

I guess with AppStudio on Geonet there are greater restrictions than with other Esri products in terms of 3rd party software licensing and public sharing of code. I never really thought about that before. I will contact Esri's Technical support for assistance.

I apologise if my request or response was unreasonable.

Best of wishes for 2018!

Regards

Mervyn 

0 Kudos
BrookeReams
New Contributor

Hi Mervyn,

The code below is a page in one of my apps that allows the layers in the map to be toggled on and off.  I've also included a screenshot of what this page looks like.  From my map page, I've defined a QML object for my Layers page like this:

LayersPage {
        id: layersPage
        primaryColor: app.primaryColor
        darkGray: app.darkGray
        lightGray: app.lightGray
        fontFamily: app.fontSourceRobotoReg.name
        headerFont: app.fontSourceRobotoMed.name
    }

I call the show() method to show the Layers page, and pass the operational layers in the map, like this:

layersPage.show(mapView.map.operationalLayers)


Below is the code for the Layers page.  The ListView is used to display the layers in the model (mapView.map.operationalLayers).

import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.1
import QtGraphicalEffects 1.0
import ArcGIS.AppFramework 1.0
import ArcGIS.AppFramework.Controls 1.0
Page {
    id: pageLayers
    anchors.fill: parent
    visible: false
    Material.background: "white"
    // Scale factor
    property real scaleFactor: AppFramework.displayScaleFactor
    property color primaryColor: "blue"
    property color darkGray: "darkgray"
    property color lightGray: "lightgray"
    property string fontFamily
    property string headerFont
    signal layerToggled(int index)
    function show(layersListModel) {
        listViewLayers.model = layersListModel
        visible = true
    }
    function hide() {
        visible = false
    }
    header: ToolBar {
        id: toolbar
        width: parent.width
        height: 56*scaleFactor
        Material.background: primaryColor
        RowLayout {
            anchors.fill: parent
            ToolButton {
                indicator: Image {
                    width: parent.width*0.5
                    height: parent.height*0.5
                    anchors.centerIn: parent
                    horizontalAlignment: Qt.AlignRight
                    verticalAlignment: Qt.AlignVCenter
                    source: "assets/images/left_arrow.png"
                    fillMode: Image.PreserveAspectFit
                }
                onClicked: {
                    pageLayers.hide()
                }
            }
            Item {
                Layout.preferredWidth: 25*scaleFactor
                Layout.fillHeight: true
            }
            Label {
               text: "Layers"
               Material.foreground: "white"
               font.family: headerFont
               font.pixelSize: 20*scaleFactor
            }
            Item {
                Layout.fillWidth: true
                Layout.fillHeight: true
            }
        }
    }
    ListView {
        id: listViewLayers
        width: parent.width
        height: parent.height - 10*scaleFactor
        anchors {
            top: parent.top
            topMargin: 10*scaleFactor
        }
        clip: true
        delegate: RowLayout {
            width: parent.width
            height: 60*scaleFactor
            Item {
                Layout.preferredWidth: 20*scaleFactor
                Layout.fillHeight: true
            }
            Switch {
                checked: layerVisible
                Material.accent: primaryColor
                onCheckedChanged: {
                    layerToggled(index)
                    layerVisible = checked
                }
            }
            Item {
                Layout.fillWidth: true
                Layout.fillHeight: true
            }
            Label {
                Layout.preferredWidth: parent.width - 30*scaleFactor
                text: name
                font.family: fontFamily
                font.pixelSize: 16*scaleFactor
                Material.foreground: darkGray
                wrapMode: Text.WrapAtWordBoundaryOrAnywhere
            }
            Item {
                Layout.preferredWidth: 35*scaleFactor
                Layout.fillHeight: true
            }
        }
    }
}

I hope that helps.  Let me know if you have any questions.

MervynLotter
Occasional Contributor III

Hi Brooke

Thank you so much for sharing the example. Very much appreciated.

I shall take a look and let you know if I have any questions.

Regards

Mervyn

0 Kudos