Skip To Content ArcGIS for Developers Sign In Dashboard

KML tour

A KML tour


// Copyright 2019 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:
// 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.

using ArcGISRuntime.Samples.Managers;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Ogc;
using Esri.ArcGISRuntime.UI.Controls;
using Foundation;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using UIKit;

namespace ArcGISRuntimeXamarin.Samples.PlayKmlTours
        "Play a KML tour",
        "Display tours in KML files.",
    public class PlayKmlTours : UIViewController
        // Hold references to UI controls.
        private SceneView _mySceneView;
        private UIBarButtonItem _playButton;
        private UIBarButtonItem _pauseButton;
        private UIBarButtonItem _resetButton;
        private UIActivityIndicatorView _loadingIndicator;

        // The KML tour controller provides player controls for KML tours.
        private readonly KmlTourController _tourController = new KmlTourController();

        public PlayKmlTours()
            Title = "Play a KML tour";

        private async void Initialize()
            // Load the scene with a basemap and a terrain surface.
            _mySceneView.Scene = new Scene(Basemap.CreateImagery());
            _mySceneView.Scene.BaseSurface.ElevationSources.Add(new ArcGISTiledElevationSource(new Uri("")));

            // Get the URL to the data.
            string filePath = DataManager.GetDataFolder("f10b1d37fdd645c9bc9b189fb546307c", "Esri_tour.kmz");
            Uri kmlUrl = new Uri(filePath);

            // Create the KML dataset and layer.
            KmlDataset dataset = new KmlDataset(kmlUrl);
            KmlLayer layer = new KmlLayer(dataset);

            // Add the layer to the map.

                // Load the dataset.
                await dataset.LoadAsync();

                // Find the first KML tour.

                // Handle absence of tour gracefully.
                if (_tourController.Tour == null)
                    throw new InvalidOperationException("No tour found. Can't enable touring for a KML file with no tours.");

                // Listen for changes to the tour status.
                _tourController.Tour.PropertyChanged += Tour_PropertyChanged;

                // Enable the play button.
                _playButton.Enabled = true;

                // Hide the activity indicator.
            catch (Exception e)
                new UIAlertView("Error", e.ToString(), (IUIAlertViewDelegate) null, "OK", null).Show();

        private void FindKmlTour(IEnumerable<KmlNode> rootNodes)
            // Hold a list of nodes to explore.
            Queue<KmlNode> nodesToExplore = new Queue<KmlNode>();

            // Add each root node to the list.
            foreach (KmlNode rootNode in rootNodes)

            // Keep exploring until a tour is found or there are no more nodes.
            while (nodesToExplore.Any())
                // Remove a node from the queue.
                KmlNode currentNode = nodesToExplore.Dequeue();

                // If the node is a tour, use it.
                if (currentNode is KmlTour tourNode)
                    _tourController.Tour = tourNode;

                // If the node is a container, add all of its children to the list of nodes to explore.
                if (currentNode is KmlContainer container)
                    foreach (KmlNode node in container.ChildNodes)

                // Otherwise, continue.

        private void Tour_PropertyChanged(object sender, PropertyChangedEventArgs e)
            // Skip for everything except tour status property changes.
            if (e.PropertyName != nameof(KmlTour.TourStatus))

            // Set the UI based on the current state of the tour.
            switch (_tourController.Tour.TourStatus)
                case KmlTourStatus.Completed:
                case KmlTourStatus.Initialized:
                    _playButton.Enabled = true;
                    _pauseButton.Enabled = false;
                case KmlTourStatus.Paused:
                    _playButton.Enabled = true;
                    _pauseButton.Enabled = false;
                    _resetButton.Enabled = true;
                case KmlTourStatus.Playing:
                    _resetButton.Enabled = true;
                    _playButton.Enabled = false;
                    _pauseButton.Enabled = true;

        // Play the tour when the button is pressed.
        private void Play_Clicked(object sender, EventArgs e) => _tourController?.Play();

        // Pause the tour when the button is pressed.
        private void Pause_Clicked(object sender, EventArgs e) => _tourController?.Pause();

        // Reset the tour when the button is pressed.
        private void Reset_Clicked(object sender, EventArgs e) => _tourController?.Reset();

        public override void ViewWillDisappear(bool animated)

            // Reset the tour controller when the sample closes - avoids a crash.

        public override void LoadView()
            // Create the views.
            View = new UIView {BackgroundColor = UIColor.White};

            _mySceneView = new SceneView();
            _mySceneView.TranslatesAutoresizingMaskIntoConstraints = false;

            UIToolbar toolbar = new UIToolbar();
            toolbar.TranslatesAutoresizingMaskIntoConstraints = false;

            _playButton = new UIBarButtonItem(UIBarButtonSystemItem.Play, Play_Clicked) {Enabled = false};
            _pauseButton = new UIBarButtonItem(UIBarButtonSystemItem.Pause, Pause_Clicked) {Enabled = false};
            _resetButton = new UIBarButtonItem(UIBarButtonSystemItem.Refresh, Reset_Clicked) {Enabled = false};

            toolbar.Items = new UIBarButtonItem[]
                new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace),

            UILabel helpLabel = new UILabel
                Text = "Use the buttons to play the tour. Contains audio. 🎧",
                AdjustsFontSizeToFitWidth = true,
                TextAlignment = UITextAlignment.Center,
                BackgroundColor = UIColor.FromWhiteAlpha(0, .6f),
                TextColor = UIColor.White,
                Lines = 1,
                TranslatesAutoresizingMaskIntoConstraints = false

            _loadingIndicator = new UIActivityIndicatorView(UIActivityIndicatorViewStyle.WhiteLarge)
                TranslatesAutoresizingMaskIntoConstraints = false,
                HidesWhenStopped = true,
                BackgroundColor = UIColor.FromWhiteAlpha(0, .6f)

            // Add the views.
            View.AddSubviews(_mySceneView, toolbar, helpLabel, _loadingIndicator);

            // Lay out the views.

        public override void ViewDidLoad()

In this topic
  1. Code