Skip To Content ArcGIS for Developers Sign In Dashboard

Map reference scale

Set a map reference scale


// 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 CoreGraphics;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Portal;
using Esri.ArcGISRuntime.UI.Controls;
using Foundation;
using System;
using UIKit;

namespace ArcGISRuntimeXamarin.Samples.MapReferenceScale
        "Map reference scale",
        "Set a map's reference scale and control which feature layers honor that scale.",
    public class MapReferenceScale : UIViewController
        // Hold references to UI controls.
        private MapView _myMapView;
        private UILabel _scaleLabel;
        private UITableViewController _layerTableController;
        private UIBarButtonItem _layerSelectionButton;

        // List of reference scale options.
        private readonly double[] _referenceScales =

        public MapReferenceScale()
            Title = "Map reference scale";

        private async void Initialize()
            // Create a portal and an item; the map will be loaded from portal item.
            ArcGISPortal portal = await ArcGISPortal.CreateAsync(new Uri(""));
            PortalItem mapItem = await PortalItem.CreateAsync(portal, "3953413f3bd34e53a42bf70f2937a408");

            // Create the map from the item.
            Map webMap = new Map(mapItem);

            // Update the UI when the map navigates.
            _myMapView.ViewpointChanged += (o, e) => _scaleLabel.Text = $"Current map scale: 1:{_myMapView.MapScale:n0}";

            // Display the map.
            _myMapView.Map = webMap;

            // Wait for the map to load.
            await webMap.LoadAsync();

            // Configure the tableview controller to enable managing layers.
            _layerTableController = new UITableViewController();
            _layerTableController.TableView.Source = new LayerViewModel(webMap);

            // Enable the button now that the map is ready.
            _layerSelectionButton.Enabled = true;

        private void ShowLayerOptions_Click(object sender, EventArgs e)
            // Show the layer list popover. Note: most behavior is managed by the table view & its source. See LayerViewModel.
            var controller = new UINavigationController(_layerTableController);
            var closeButton = new UIBarButtonItem("Close", UIBarButtonItemStyle.Plain, (o, ea) => controller.DismissViewController(true, null));
            controller.NavigationBar.Items[0].SetRightBarButtonItem(closeButton, false);
            controller.ModalPresentationStyle = UIModalPresentationStyle.Popover;
            controller.PreferredContentSize = new CGSize(300, 250);
            UIPopoverPresentationController pc = controller.PopoverPresentationController;
            if (pc != null)
                pc.BarButtonItem = (UIBarButtonItem) sender;
                pc.PermittedArrowDirections = UIPopoverArrowDirection.Down;
                pc.Delegate = new ppDelegate();

            PresentViewController(controller, true, null);

        private void ShowScaleOptions_Click(object sender, EventArgs e)
            // Create the view controller that will present the list of scales.
            UIAlertController basemapSelectionAlert = UIAlertController.Create("Select a reference scale", "", UIAlertControllerStyle.ActionSheet);

            // Add an option for each basemap.
            foreach (double scale in _referenceScales)
                // Selecting a scale will call the lambda method, which will apply the chosen reference scale.
                basemapSelectionAlert.AddAction(UIAlertAction.Create($"1:{scale:n0}", UIAlertActionStyle.Default, action => _myMapView.Map.ReferenceScale = scale));

            // Fix to prevent crash on iPad.
            var popoverPresentationController = basemapSelectionAlert.PopoverPresentationController;
            if (popoverPresentationController != null)
                popoverPresentationController.BarButtonItem = (UIBarButtonItem) sender;

            // Show the alert.
            PresentViewController(basemapSelectionAlert, true, null);

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

            _myMapView = new MapView();
            _myMapView.TranslatesAutoresizingMaskIntoConstraints = false;

            UIToolbar toolbar = new UIToolbar();
            toolbar.TranslatesAutoresizingMaskIntoConstraints = false;
            _layerSelectionButton = new UIBarButtonItem("Configure layers", UIBarButtonItemStyle.Plain, ShowLayerOptions_Click) {Enabled = false};
            toolbar.Items = new[]
                new UIBarButtonItem("Set reference scale", UIBarButtonItemStyle.Plain, ShowScaleOptions_Click),
                new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace),

            _scaleLabel = new UILabel
                Text = "Current map scale:",
                AdjustsFontSizeToFitWidth = true,
                TextAlignment = UITextAlignment.Center,
                BackgroundColor = UIColor.FromWhiteAlpha(0, .6f),
                TextColor = UIColor.White,
                Lines = 1,
                TranslatesAutoresizingMaskIntoConstraints = false

            // Add the views.
            View.AddSubviews(_myMapView, toolbar, _scaleLabel);

            // Lay out the views.

        // Force popover to display on iPhone.
        private class ppDelegate : UIPopoverPresentationControllerDelegate
            public override UIModalPresentationStyle GetAdaptivePresentationStyle(
                UIPresentationController forPresentationController) => UIModalPresentationStyle.None;

            public override UIModalPresentationStyle GetAdaptivePresentationStyle(UIPresentationController controller,
                UITraitCollection traitCollection) => UIModalPresentationStyle.None;

        public override void ViewDidLoad()

    class LayerViewModel : UITableViewSource
        private Map _map;
        private const string CellIdentifier = "LayerTableCell";

        public LayerViewModel(Map map)
            _map = map;

        public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
            // Gets a cell for the specified section and row.
            var cell = new UITableViewCell(UITableViewCellStyle.Subtitle, CellIdentifier);
            Layer selectedLayer = _map.OperationalLayers[indexPath.Row];

            // Show the layer name.
            cell.TextLabel.Text = selectedLayer.Name;

            // Show a toggle if this is a feature layer whose visibility can be toggled.
            FeatureLayer fLayer = selectedLayer as FeatureLayer;
            if (fLayer != null)
                // Get the layer as a feature layer.

                // Create a switch.
                UISwitch scaleSwitch = new UISwitch();
                scaleSwitch.On = fLayer.ScaleSymbols;

                // Update the feature layer scaleSymbols setting when the switch is toggled.
                scaleSwitch.ValueChanged += (o, e) => { fLayer.ScaleSymbols = scaleSwitch.On; };

                // Add the switch to the cell.
                cell.AccessoryView = scaleSwitch;

            return cell;

        public override bool CanEditRow(UITableView tableView, NSIndexPath indexPath)
            return false;

        public override nint RowsInSection(UITableView tableview, nint section)
            return _map.OperationalLayers.Count;

        public override nint NumberOfSections(UITableView tableView)
            return 1;

In this topic
  1. Code