Click or drag to resize

KmlIconStyle Class

A KML icon style object.
Inheritance Hierarchy

Namespace:  Esri.ArcGISRuntime.Ogc
Assembly:  Esri.ArcGISRuntime (in Esri.ArcGISRuntime.dll) Version: 100.9.0.0
Syntax
C#
public sealed class KmlIconStyle : KmlColorStyle

The KmlIconStyle type exposes the following members.

Constructors
  NameDescription
Public methodCode exampleKmlIconStyle
Initializes a new instance of the KmlIconStyle class.
Top
Properties
  NameDescription
Public propertyColor
Gets or sets the color.
(Inherited from KmlColorStyle.)
Public propertyColorMode
Gets or sets the color mode.
(Inherited from KmlColorStyle.)
Public propertyHeading
Gets or sets the direction, in decimal degrees.
Public propertyHotSpot
Gets or sets the position within the Icon that is anchored to the point specified in the placemark.
Public propertyIcon
Gets or sets the icon to be used by the placemark.
Public propertyScale
Gets or sets the scale factor that should be applied to the rendered icon.
Top
Events
  NameDescription
Public eventPropertyChanged (Inherited from KmlColorStyle.)
Top
Remarks
Specifies how icons for placemarks and photo overlays with a point geometry are drawn. Color is blended with the existing color of the icon.
Examples

Android

Example Name: CreateAndSaveKmlFile

Construct a KML document and save it as a KMZ file.

Code example screen shot.

C#
// 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: 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.

using Android;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Support.V4.App;
using Android.Support.V4.Content;
using Android.Views;
using Android.Widget;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Ogc;
using Esri.ArcGISRuntime.UI;
using Esri.ArcGISRuntime.UI.Controls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Resource = ArcGISRuntime.Resource;

namespace ArcGISRuntimeXamarin.Samples.CreateAndSaveKmlFile
{
    [Activity(ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
    [ArcGISRuntime.Samples.Shared.Attributes.Sample(
        name: "Create and save KML file",
        category: "Layers",
        description: "Construct a KML document and save it as a KMZ file.",
        instructions: "Tap on one of the buttons in the middle row to start adding a geometry. Tap on the map view to place vertices. Tap the \"Complete Sketch\" button to add the geometry to the KML document as a new KML placemark. Use the style interface to edit the style of the placemark. If you do not wish to set a style, tap the \"Don't Apply Style\" button. When you are finished adding KML nodes, tap on the \"Save KMZ file\" button to save the active KML document as a .kmz file on your system. Use the \"Reset\" button to clear the current KML document and start a new one.",
        tags: new[] { "KML", "KMZ", "Keyhole", "OGC", "Featured" })]
    [ArcGISRuntime.Samples.Shared.Attributes.AndroidLayout("CreateAndSaveKmlFile.axml")]
    [ArcGISRuntime.Samples.Shared.Attributes.OfflineData()]
    public class CreateAndSaveKmlFile : Activity
    {
        // Hold references to the UI controls.
        private MapView _myMapView;
        private Button _addButton;
        private Button _saveButton;
        private Button _resetButton;
        private Button _completeButton;
        private Button _noStyleButton;
        private LinearLayout _buttonLayout;
        private LinearLayout _pickerLayout;
        private TextView _status;
        private TextView _styleText;
        private ListView _listView;
        private BaseAdapter _iconAdapter;
        private BaseAdapter _colorAdapter;

        private KmlDocument _kmlDocument;
        private KmlDataset _kmlDataset;
        private KmlLayer _kmlLayer;
        private KmlPlacemark _currentPlacemark;

        private List<string> _iconLinks;
        private List<Color> _colorList;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            Title = "Create and save KML file";

            CreateLayout();
            Initialize();
        }

        private void Initialize()
        {
            // Create the map.
            _myMapView.Map = new Map(Basemap.CreateImagery());

            // Set up a new kml document and kml layer.
            ResetKml();

            // Set the colors for the color picker.
            _colorList = new List<Color>()
            {
               Color.Blue, Color.Brown, Color.Gray, Color.Green, Color.Yellow, Color.Pink, Color.Purple, Color.Red, Color.Black
            };
            _colorAdapter = new ColorAdapter(this, _colorList);

            // Set the images for the point icon picker.
            _iconLinks = new List<string>()
            {
                "https://static.arcgis.com/images/Symbols/Shapes/BlueCircleLargeB.png",
                "https://static.arcgis.com/images/Symbols/Shapes/BlueDiamondLargeB.png",
                "https://static.arcgis.com/images/Symbols/Shapes/BluePin1LargeB.png",
                "https://static.arcgis.com/images/Symbols/Shapes/BluePin2LargeB.png",
                "https://static.arcgis.com/images/Symbols/Shapes/BlueSquareLargeB.png",
                "https://static.arcgis.com/images/Symbols/Shapes/BlueStarLargeB.png"
            };

            // Request permission to save a file.
            if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != Android.Content.PM.Permission.Granted)
            {
                ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.WriteExternalStorage }, 1);
            }
        }

        private void ResetKml()
        {
            // Clear any existing layers from the map.
            _myMapView.Map.OperationalLayers.Clear();

            // Reset the most recently placed placemark.
            _currentPlacemark = null;

            // Create a new KML document.
            _kmlDocument = new KmlDocument() { Name = "KML Sample Document" };

            // Create a KML dataset using the KML document.
            _kmlDataset = new KmlDataset(_kmlDocument);

            // Create the KML layer using the KML dataset.
            _kmlLayer = new KmlLayer(_kmlDataset);

            // Add the KML layer to the map.
            _myMapView.Map.OperationalLayers.Add(_kmlLayer);
        }

        private void Add_Click(object sender, EventArgs e)
        {
            string[] options = new string[] { "Point", "Polyline", "Polygon" };

            // Create UI for terminal selection.
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.SetItems(options, Draw);
            builder.SetCancelable(false);
            builder.Show();
        }

        private async void Draw(object sender, DialogClickEventArgs e)
        {
            try
            {
                // Hide the base UI and enable the complete button.
                _buttonLayout.Visibility = ViewStates.Invisible;
                _completeButton.Visibility = ViewStates.Visible;

                // Create variables for the sketch creation mode and color.
                SketchCreationMode creationMode;

                // Set the creation mode and UI based on which button called this method.
                switch (e.Which)
                {
                    case 0:
                        creationMode = SketchCreationMode.Point;
                        _status.Text = "Tap to add a point.";
                        //StyleText.Text = "Select an icon for the placemark.";
                        break;

                    case 1:
                        creationMode = SketchCreationMode.Polyline;
                        _status.Text = "Tap to add a vertex.";
                        //StyleText.Text = "Select a color for the placemark.";
                        break;

                    case 2:
                        creationMode = SketchCreationMode.Polygon;
                        _status.Text = "Tap to add a vertex.";
                        //StyleText.Text = "Select a color for the placemark.";
                        break;

                    default:
                        return;
                }

                // Get the user-drawn geometry.
                Geometry geometry = await _myMapView.SketchEditor.StartAsync(creationMode, true);

                // Project the geometry to WGS84 (WGS84 is required by the KML standard).
                Geometry projectedGeometry = GeometryEngine.Project(geometry, SpatialReferences.Wgs84);

                // Create a KmlGeometry using the new geometry.
                KmlGeometry kmlGeometry = new KmlGeometry(projectedGeometry, KmlAltitudeMode.ClampToGround);

                // Create a new placemark.
                _currentPlacemark = new KmlPlacemark(kmlGeometry);

                // Add the placemark to the KmlDocument.
                _kmlDocument.ChildNodes.Add(_currentPlacemark);

                // Choose whether to open the icon picker or color picker.
                if (creationMode == SketchCreationMode.Point) { OpenIconDialog(); }
                else { OpenColorDialog(); }
            }
            catch (ArgumentException)
            {
                new AlertDialog.Builder(this).SetMessage("Unsupported Geometry").SetTitle("Error").Show();
            }
            finally
            {
                // Reset the UI.
                _buttonLayout.Visibility = ViewStates.Visible;
                _completeButton.Visibility = ViewStates.Invisible;
                _status.Text = "";
            }
        }

        private void Complete_Click(object sender, EventArgs e)
        {
            try
            {
                // Finish the sketch.
                _myMapView.SketchEditor.CompleteCommand.Execute(null);
            }
            catch (ArgumentException)
            {
            }
        }

        private void OpenIconDialog()
        {
            // Create the icon adapter if it has not been created yet.
            if (_iconAdapter == null) { _iconAdapter = new IconAdapter(this, _iconLinks); }

            // Display the picker view.
            _listView.Adapter = _iconAdapter;
            _styleText.Text = "Select an icon.";
            _pickerLayout.Visibility = ViewStates.Visible;
            _listView.ItemClick += IconSelected;
        }

        private void IconSelected(object sender, AdapterView.ItemClickEventArgs e)
        {
            // Set the style of the placemark.
            _currentPlacemark.Style = new KmlStyle();
            _currentPlacemark.Style.IconStyle = new KmlIconStyle(new KmlIcon(new Uri(_iconLinks[(int)e.Id])), 1.0);

            // Reset the UI.
            _pickerLayout.Visibility = ViewStates.Invisible;
            _listView.ItemClick -= IconSelected;
        }

        private void OpenColorDialog()
        {
            // Display the picker view.
            _listView.Adapter = _colorAdapter;
            _styleText.Text = "Select a color.";
            _pickerLayout.Visibility = ViewStates.Visible;
            _listView.ItemClick += ColorSelected;
        }

        private void ColorSelected(object sender, AdapterView.ItemClickEventArgs e)
        {
            // Convert the selected Android color into a System.Drawing.Color.
            Color androidColor = _colorList[e.Position];
            System.Drawing.Color systemColor = System.Drawing.Color.FromArgb(androidColor.R, androidColor.G, androidColor.B);

            // Create a new style for the placemark.
            _currentPlacemark.Style = new KmlStyle();

            // Check the graphic type of the placemark.
            if (_currentPlacemark.GraphicType == KmlGraphicType.Polyline)
            {
                // Set the line style.
                _currentPlacemark.Style.LineStyle = new KmlLineStyle(systemColor, 8);
            }
            else if (_currentPlacemark.GraphicType == KmlGraphicType.Polygon)
            {
                // Set the polygon style.
                _currentPlacemark.Style.PolygonStyle = new KmlPolygonStyle(systemColor);
                _currentPlacemark.Style.PolygonStyle.IsFilled = true;
                _currentPlacemark.Style.PolygonStyle.IsOutlined = false;
            }

            // Reset the UI.
            _pickerLayout.Visibility = ViewStates.Invisible;
            _listView.ItemClick -= ColorSelected;
        }

        private void No_Style_Click(object sender, EventArgs e)
        {
            // Reset the UI.
            _pickerLayout.Visibility = ViewStates.Invisible;
            _listView.ItemClick -= IconSelected;
            _listView.ItemClick -= ColorSelected;
        }

        private async void Save_Click(object sender, EventArgs e)
        {
            // Determine where to save your file
            string filePath = System.IO.Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads, "sampledata.kmz");

            // Check if the user can save their file.
            if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != Android.Content.PM.Permission.Granted)
            {
                ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.WriteExternalStorage }, 1);
            }
            else
            {
                using (Stream stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
                {
                    // Write the KML document to the stream of the file.
                    await _kmlDocument.WriteToAsync(stream);
                }
                new AlertDialog.Builder(this).SetMessage("File saved to " + filePath).SetTitle("Success!").Show();
            }
        }

        private void Reset_Click(object sender, EventArgs e)
        {
            ResetKml();
        }

        private void CreateLayout()
        {
            // Load the layout from the axml resource.
            SetContentView(Resource.Layout.CreateAndSaveKmlFile);

            _myMapView = FindViewById<MapView>(Resource.Id.MapView);
            _addButton = FindViewById<Button>(Resource.Id.addButton);
            _saveButton = FindViewById<Button>(Resource.Id.saveButton);
            _resetButton = FindViewById<Button>(Resource.Id.resetButton);
            _completeButton = FindViewById<Button>(Resource.Id.completeButton);
            _noStyleButton = FindViewById<Button>(Resource.Id.noStyleButton);
            _buttonLayout = FindViewById<LinearLayout>(Resource.Id.linearLayout);
            _pickerLayout = FindViewById<LinearLayout>(Resource.Id.PickerUI);
            _status = FindViewById<TextView>(Resource.Id.statusLabel);
            _styleText = FindViewById<TextView>(Resource.Id.styleText);
            _listView = FindViewById<ListView>(Resource.Id.listView);

            // Add listeners for all of the buttons.
            _addButton.Click += Add_Click;
            _saveButton.Click += Save_Click;
            _resetButton.Click += Reset_Click;
            _completeButton.Click += Complete_Click;
            _noStyleButton.Click += No_Style_Click;
        }
    }

    // Adapter to display icons in a ListView.
    public class IconAdapter : BaseAdapter<Bitmap>
    {
        public List<Bitmap> iconList;
        private Context context;

        public IconAdapter(Context context, List<string> list)
        {
            this.context = context;
            iconList = new List<Bitmap>();

            foreach (string link in list)
            {
                Bitmap imageBitmap;
                imageBitmap = BitmapFactory.DecodeStream(WebRequest.Create(link).GetResponse().GetResponseStream());
                iconList.Add(imageBitmap);
            }
        }

        public override Bitmap this[int position] => iconList[position];

        public override int Count => iconList.Count;

        public override long GetItemId(int position)
        {
            return position;
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            // Create the image.
            ImageView image = new ImageView(this.context);
            image.SetImageBitmap(iconList[position]);
            image.SetMinimumHeight(150);
            image.SetMinimumWidth(150);

            // Create the layout.
            LinearLayout layout = new LinearLayout(context) { Orientation = Orientation.Horizontal };
            layout.AddView(image);
            layout.SetMinimumHeight(150);
            return layout;
        }
    }

    // Adapter to display color options in a ListView.
    public class ColorAdapter : BaseAdapter<Color>
    {
        public List<Color> colorList;
        private Context context;

        public ColorAdapter(Context context, List<Color> list)
        {
            this.context = context;
            colorList = list;
        }

        public override Color this[int position] => throw new NotImplementedException();

        public override int Count => colorList.Count;

        public override long GetItemId(int position)
        {
            return position;
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            // Create a simple layout for the color.
            LinearLayout layout = new LinearLayout(context) { Orientation = Orientation.Horizontal };
            layout.SetMinimumHeight(150);
            layout.SetBackgroundColor(colorList[position]);
            return layout;
        }
    }
}
Examples

Xamarin Forms Android

Example Name: CreateAndSaveKmlFile

Construct a KML document and save it as a KMZ file.

Code example screen shot.

C#
// 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: 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.

using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Ogc;
using Esri.ArcGISRuntime.UI;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Xamarin.Forms;
using Color = System.Drawing.Color;
using Geometry = Esri.ArcGISRuntime.Geometry.Geometry;
#if __IOS__
using ArcGISRuntime.Samples.Managers;
#endif
#if __ANDROID__
using Android.Support.V4.Content;
using Android.Content.PM;
using Android;
#endif
#if WINDOWS_UWP
using Windows.Storage.Pickers;
#endif

namespace ArcGISRuntimeXamarin.Samples.CreateAndSaveKmlFile
{
    [ArcGISRuntime.Samples.Shared.Attributes.Sample(
        name: "Create and save KML file",
        category: "Layers",
        description: "Construct a KML document and save it as a KMZ file.",
        instructions: "Tap on one of the buttons in the middle row to start adding a geometry. Tap on the map view to place vertices. Tap the \"Complete Sketch\" button to add the geometry to the KML document as a new KML placemark. Use the style interface to edit the style of the placemark. If you do not wish to set a style, tap the \"Don't Apply Style\" button. When you are finished adding KML nodes, tap on the \"Save KMZ file\" button to save the active KML document as a .kmz file on your system. Use the \"Reset\" button to clear the current KML document and start a new one.",
        tags: new[] { "KML", "KMZ", "Keyhole", "OGC", "Featured" })]
    [ArcGISRuntime.Samples.Shared.Attributes.OfflineData()]
    public partial class CreateAndSaveKmlFile : ContentPage
    {
        private KmlDocument _kmlDocument;
        private KmlDataset _kmlDataset;
        private KmlLayer _kmlLayer;
        private KmlPlacemark _currentPlacemark;

        public CreateAndSaveKmlFile()
        {
            InitializeComponent();
            Initialize();
        }

        private void Initialize()
        {
            // Create the map.
            MyMapView.Map = new Map(Basemap.CreateImagery());

            List<String> colorHexes = new List<string>()
            {
                "#000000","#FFFFFF","#FF0000","#00FF00","#0000FF","#FFFF00", "#00FFFF","#FF00FF", "#C0C0C0", "#808080","#800000", "#808000","#008000", "#800080","#008080","#000080"
            };
            ColorPicker.ItemsSource = colorHexes;

            // Set the images for the point icon picker.
            List<string> iconLinks = new List<string>()
            {
                "https://static.arcgis.com/images/Symbols/Shapes/BlueCircleLargeB.png",
                "https://static.arcgis.com/images/Symbols/Shapes/BlueDiamondLargeB.png",
                "https://static.arcgis.com/images/Symbols/Shapes/BluePin1LargeB.png",
                "https://static.arcgis.com/images/Symbols/Shapes/BluePin2LargeB.png",
                "https://static.arcgis.com/images/Symbols/Shapes/BlueSquareLargeB.png",
                "https://static.arcgis.com/images/Symbols/Shapes/BlueStarLargeB.png"
            };
            List<Uri> iconList = iconLinks.Select(x => new Uri(x)).ToList();
            IconPicker.ItemsSource = iconLinks;

            // Set up a new kml document and kml layer.
            ResetKml();
        }
        private void ResetKml()
        {
            // Clear any existing layers from the map.
            MyMapView.Map.OperationalLayers.Clear();

            // Reset the most recently placed placemark.
            _currentPlacemark = null;

            // Create a new KML document.
            _kmlDocument = new KmlDocument() { Name = "KML Sample Document" };

            // Create a KML dataset using the KML document.
            _kmlDataset = new KmlDataset(_kmlDocument);

            // Create the KML layer using the KML dataset.
            _kmlLayer = new KmlLayer(_kmlDataset);

            // Add the KML layer to the map.
            MyMapView.Map.OperationalLayers.Add(_kmlLayer);
        }

        private async void Edit_Click(object sender, EventArgs e)
        {
            try
            {
                // Hide the base UI and enable the complete button.
                ShapeGrid.IsVisible = false;
                CompleteButton.IsVisible = true;
                SaveResetGrid.IsEnabled = false;

                // Create variables for the sketch creation mode and color.
                SketchCreationMode creationMode;

                // Set the creation mode and UI based on which button called this method.
                switch (((Button)sender).Text)
                {
                    case "Point":
                        creationMode = SketchCreationMode.Point;
                        Status.Text = "Tap to add a point.";
                        break;

                    case "Polyline":
                        creationMode = SketchCreationMode.Polyline;
                        Status.Text = "Tap to add a vertex.";
                        break;

                    case "Polygon":
                        creationMode = SketchCreationMode.Polygon;
                        Status.Text = "Tap to add a vertex.";
                        break;

                    default:
                        return;
                }

                // Get the user-drawn geometry.
                Geometry geometry = await MyMapView.SketchEditor.StartAsync(creationMode, true);

                // Project the geometry to WGS84 (WGS84 is required by the KML standard).
                Geometry projectedGeometry = GeometryEngine.Project(geometry, SpatialReferences.Wgs84);

                // Create a KmlGeometry using the new geometry.
                KmlGeometry kmlGeometry = new KmlGeometry(projectedGeometry, KmlAltitudeMode.ClampToGround);

                // Create a new placemark.
                _currentPlacemark = new KmlPlacemark(kmlGeometry);

                // Add the placemark to the KmlDocument.
                _kmlDocument.ChildNodes.Add(_currentPlacemark);

                // Choose whether to enable the icon picker or color picker.
                IconPicker.IsVisible = creationMode == SketchCreationMode.Point;
                ColorPicker.IsVisible = creationMode != SketchCreationMode.Point;

                // Enable the style editing UI.
                StyleUI.IsVisible = true;
                MainUI.IsVisible = false;
            }
            catch (ArgumentException)
            {
                await Application.Current.MainPage.DisplayAlert("Error", "Unsupported Geometry", "OK");
            }
            finally
            {
                // Reset the UI.
                ShapeGrid.IsVisible = true;
                CompleteButton.IsVisible = false;
                Status.Text = "Select the type of feature you would like to add.";

                // Enable the save and reset buttons.
                SaveResetGrid.IsEnabled = true;
            }
        }

        private void Apply_Style_Click(object sender, SelectedItemChangedEventArgs e)
        {
            // Get the color value if the selected item is a hexadecimal color.
            Color systemColor = Color.Transparent;
            if (((string)e.SelectedItem).StartsWith('#'))
            {
                Xamarin.Forms.Color platColor = Xamarin.Forms.Color.FromHex((string)e.SelectedItem);
                systemColor = Color.FromArgb((int)(platColor.A * 255), (int)(platColor.R * 255), (int)(platColor.G * 255), (int)(platColor.B * 255));
            }

            // Create a new style for the placemark.
            _currentPlacemark.Style = new KmlStyle();

            // Set the style for that Placemark.
            switch (_currentPlacemark.GraphicType)
            {
                // Create a KmlIconStyle using the selected icon.
                case KmlGraphicType.Point:
                    Uri iconLink = new Uri((string)e.SelectedItem);
                    _currentPlacemark.Style.IconStyle = new KmlIconStyle(new KmlIcon(iconLink), 1.0);
                    break;

                // Create a KmlLineStyle using the selected color value.
                case KmlGraphicType.Polyline:
                    _currentPlacemark.Style.LineStyle = new KmlLineStyle(systemColor, 8);
                    break;

                // Create a KmlPolygonStyle using the selected color value.
                case KmlGraphicType.Polygon:
                    _currentPlacemark.Style.PolygonStyle = new KmlPolygonStyle(systemColor);
                    _currentPlacemark.Style.PolygonStyle.IsFilled = true;
                    _currentPlacemark.Style.PolygonStyle.IsOutlined = false;
                    break;
            }

            // Reset the UI.
            MainUI.IsVisible = true;
            StyleUI.IsVisible = false;
        }

        private void No_Style_Click(object sender, EventArgs e)
        {
            // Reset the UI.
            StyleUI.IsVisible = false;
            MainUI.IsVisible = true;
        }

        private void Complete_Click(object sender, EventArgs e)
        {
            try
            {
                // Finish the sketch.
                MyMapView.SketchEditor.CompleteCommand.Execute(null);
            }
            catch (ArgumentException)
            {
            }
        }

        private async void Save_Click(object sender, EventArgs e)
        {
            try
            {
#if __IOS__
                // Determine the path for the file.
                string offlineDataFolder = Path.Combine(DataManager.GetDataFolder(), "CreateAndSaveKmlFile");

                // If temporary data folder doesn't exists, create it.
                if (!Directory.Exists(offlineDataFolder))
                {
                    Directory.CreateDirectory(offlineDataFolder);
                }

                string path = Path.Combine(offlineDataFolder, "sampledata.kmz");
                using (Stream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
                {
                    // Write the KML document to the stream of the file.
                    await _kmlDocument.WriteToAsync(stream);
                }
                await Application.Current.MainPage.DisplayAlert("Success", "KMZ file saved locally to ArcGISRuntimeSamples folder.", "OK");
#endif
#if __ANDROID__
                // Determine the path for the file.
                string filePath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads, "sampledata.kmz");

                // Check if permission has not been granted.
                if(ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.WriteExternalStorage) != Permission.Granted)
                {
                    ArcGISRuntime.Droid.MainActivity.Instance.RequestPermissions(new[] { Manifest.Permission.WriteExternalStorage }, 1);
                }
                else
                {
                    using (Stream stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
                    {
                        // Write the KML document to the stream of the file.
                        await _kmlDocument.WriteToAsync(stream);
                    }
                    await Application.Current.MainPage.DisplayAlert("Success", "File saved to " + filePath, "OK");
                }
#endif
#if WINDOWS_UWP
                // Open a save dialog for the user.
                FileSavePicker savePicker = new FileSavePicker();
                savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
                savePicker.FileTypeChoices.Add("KMZ file", new List<string>() { ".kmz" });
                Windows.Storage.StorageFile file = await savePicker.PickSaveFileAsync();

                if (file != null)
                {
                    using (Stream stream = await file.OpenStreamForWriteAsync())
                    {
                        // Write the KML document to the stream of the file.
                        await _kmlDocument.WriteToAsync(stream);
                    }
                }
#endif
            }
            catch (Exception)
            {
                await Application.Current.MainPage.DisplayAlert("Error", "File not saved.", "OK");
            }
        }

        private void Reset_Click(object sender, EventArgs e)
        {
            ResetKml();
        }
    }
    internal class ImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null || value.GetType() != typeof(string)) { return null; }
            return ImageSource.FromUri(new Uri((string)value));
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    internal class ColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null || value.GetType() != typeof(string)) { return null; }
            return Xamarin.Forms.Color.FromHex((string)value);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
XAML
<ContentPage
    x:Class="ArcGISRuntimeXamarin.Samples.CreateAndSaveKmlFile.CreateAndSaveKmlFile"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:controls="clr-namespace:Windows.UI.Xaml.Controls;assembly=Windows.Foundation.UniversalApiContract"
    xmlns:esriUI="clr-namespace:Esri.ArcGISRuntime.Xamarin.Forms;assembly=Esri.ArcGISRuntime.Xamarin.Forms"
    xmlns:local="clr-namespace:ArcGISRuntimeXamarin.Samples.CreateAndSaveKmlFile">
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:ImageConverter x:Key="imageConverter" />
            <local:ColorConverter x:Key="colorConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <Grid>
        <Grid x:Name="MainUI">
            <Grid.RowDefinitions>
                <RowDefinition Height="auto" />
                <RowDefinition Height="*" />
                <RowDefinition Height="auto" />
                <RowDefinition Height="auto" />
            </Grid.RowDefinitions>
            <esriUI:MapView
                x:Name="MyMapView"
                Grid.Row="0"
                Grid.RowSpan="2" />
            <Grid x:Name="StatusGrid" BackgroundColor="DimGray">
                <Label
                    x:Name="Status"
                    Grid.Row="0"
                    Margin="5"
                    HorizontalOptions="FillAndExpand"
                    Text="Select the type of feature you would like to add."
                    TextColor="White" />
            </Grid>
            <Grid Grid.Row="2">
                <Grid x:Name="ShapeGrid">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Button
                        Grid.Column="0"
                        Clicked="Edit_Click"
                        Text="Point" />
                    <Button
                        Grid.Column="1"
                        Clicked="Edit_Click"
                        Text="Polyline" />
                    <Button
                        Grid.Column="2"
                        Clicked="Edit_Click"
                        Text="Polygon" />
                </Grid>
                <Button
                    x:Name="CompleteButton"
                    Clicked="Complete_Click"
                    IsVisible="False"
                    Text="Complete Geometry" />
            </Grid>
            <Grid x:Name="SaveResetGrid" Grid.Row="3">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Button
                    Grid.Column="0"
                    Clicked="Save_Click"
                    Text="Save" />
                <Button
                    Grid.Column="1"
                    Clicked="Reset_Click"
                    Text="Reset" />
            </Grid>
        </Grid>
        <Grid x:Name="StyleUI" IsVisible="False">
            <Grid.RowDefinitions>
                <RowDefinition Height="auto" />
                <RowDefinition Height="*" />
                <RowDefinition Height="auto" />
                <RowDefinition Height="auto" />
            </Grid.RowDefinitions>
            <Label
                Grid.Row="0"
                Margin="5"
                HorizontalTextAlignment="Center"
                Text="Select a style for the placemark." />
            <ListView
                x:Name="IconPicker"
                Grid.Row="1"
                ItemSelected="Apply_Style_Click">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ImageCell ImageSource="{Binding Path=., Converter={StaticResource imageConverter}}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            <ListView
                x:Name="ColorPicker"
                Grid.Row="1"
                IsVisible="False"
                ItemSelected="Apply_Style_Click">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <BoxView Color="{Binding Path=., Converter={StaticResource colorConverter}}" />
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            <Button
                Grid.Row="3"
                Clicked="No_Style_Click"
                Text="Dont Apply Style" />
        </Grid>
    </Grid>
</ContentPage>
See Also
Additional Examples
Hyperlink to ExampleDescription
CreateAndSaveKmlFileConstruct a KML document and save it as a KMZ file.