本文介绍如何在 Xamarin.iOS 项目中使用使用 ArcGIS Server 云端专题数据, 假设你已经准备好了 ArcGIS Client Runtime SDK for iOS 和 MonoTouch.ArcGIS 绑定项目。
ArcGIS API 提供的专题图层 (AGSFeatureLayer) 可以用来访问并编辑矢量地图数据, 它依赖于 ArcGIS 服务器专题服务 (Feature Service) , 专题服务不仅可以浏览和编辑数据, 还可以使用类似 SQL 的语法对数据进行过滤, 专题服务可以托管在 ESRI 的 ArcGIS Online 云中, 也可以部署在自己的服务器上。 本文中使用的是 ArcGIS Online 的专题服务。
添加专题服务图层是非常简单的, 只要初始化一个 AGSFeatureLayer 图层实例并把它添加到地图上就可以了, 要初始化一个图层 , 你需要知道专题服务的 URL 和访问服务所需的用户凭据, 而本文中使用专题服务是公开的, 因此不需要任何凭据。 将图层添加到地图上之后, 你需要使用自定义符号将图层的数据在地图上显示成蓝色的小圆点。
public override void ViewDidLoad() {
base.ViewDidLoad();
// 添加地图底图
var url = NSUrl.FromString("https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer");
var tiledLayer = AGSTiledMapServiceLayer.TiledMapServiceLayerWithURL(url);
this.MapView.AddMapLayer(tiledLayer, "Basemap Tiled Layer");
// 专题图层
var featureLayerUrl = NSUrl.FromString("https://services.arcgis.com/oKgs2tbjK6zwTdvi/arcgis/rest/services/Major_World_Cities/FeatureServer/0");
var featureLayer = AGSFeatureLayer.FeatureServiceLayerWithURL(featureLayerUrl, AGSFeatureLayerMode.OnDemand);
featureLayer.OutFields = new string[] { "*" };
this.MapView.AddMapLayer(featureLayer, "CloudData");
// 自定义符号
AGSSimpleMarkerSymbol featureSymbol = AGSSimpleMarkerSymbol.SimpleMarkerSymbolWithColor(UIColor.FromRGBA(0f, 0.46f, 0.68f, 1f));
featureSymbol.Size = new SizeF(7, 7);
featureSymbol.Style = AGSSimpleMarkerSymbolStyle.Circle;
//featureSymbol.Outline
featureLayer.Renderer = AGSSimpleRenderer.SimpleRendererWithSymbol(featureSymbol);
}
在这一节中, 允许用户从列表中选择一个国家。 要完成这个功能, 需要在界面上添加一个按钮, 并将按钮的 Touch Up Inside
事件连接到方法 ShowCountryPicker
:
当用户点击按钮时, 会调用 View Controller 的 ShowCountryPicker
方法, 在这个方法中, 我们初始化一个 UIPickerView
并把它显示在屏幕上, 要显示国家列表, 则需要指定数据源并实现 UIPickerViewDataSource
协议中定义的方法, 为了能收到用户选择的选项, 还需要实现 UIPickerViewDelegate
协议中定义的 pickerView:didSelectRow:inComponent:
方法。
partial void ShowCountryPicker(UIButton sender) {
if (this.Countries == null) {
this.Countries = new string[] { @"None",@"US",@"Canada",@"France",@"Australia",@"Brazil" };
}
var pickerSheet = new UIActionSheet(new RectangleF(0, 0, 320, 410));
pickerSheet.ShowInView(this.View);
pickerSheet.Bounds = new RectangleF(0, 0, 320, 410);
var countryPicker = new UIPickerView(pickerSheet.Bounds);
countryPicker.WeakDelegate = this;
countryPicker.DataSource = this;
countryPicker.ShowSelectionIndicator = true;
pickerSheet.AddSubview(countryPicker);
}
#region "UIPickerview DataSource Part"
[Export("numberOfComponentsInPickerView:")]
public int GetComponentCount(UIPickerView picker) {
return 1;
}
[Export("pickerView:numberOfRowsInComponent:")]
public virtual int GetRowsInComponent(UIPickerView picker, int component) {
return this.Countries.Length;
}
[Export("pickerView:titleForRow:forComponent:")]
public virtual string GetTitle(UIPickerView picker, int row, int component) {
return this.Countries[row];
}
#endregion
#region "UIPickerview Delegate Part"
[Export("pickerView:didSelectRow:inComponent:")]
public virtual void Selected(UIPickerView picker, int row, int component) {
// Dismiss action sheet
var pickerSheet = (UIActionSheet)picker.Superview;
pickerSheet.DismissWithClickedButtonIndex(0, true);
}
#endregion
我们现在来完成高亮显示属于用户选择的国家的数据。
首先得到的是用户选择的国家, 如果用户选择了 None
的话, 清空专题图层选中的数据; 否则, 使用类似于 SQL 的语法 COUNTRY = <selected_country>
来选中专题图层的数据。 不过在进行选中操作之前, 需要设置专题图层选中数据的符号, 比如设置选中的数据在地图上显示为红色的原点; 同时还需要设置图层的 queryDelegate
, 实现 AGSFeatureLayerQueryDelegate
协议定义的方法, 这样当选择操作完成时,才能收到通知。
#region "UIPickerview Delegate Part"
[Export("pickerView:didSelectRow:inComponent:")]
public virtual void Selected(UIPickerView picker, int row, int component) {
var countryName = this.Countries[row];
var featureLayer = (AGSFeatureLayer)this.MapView.MapLayerForName("CloudData");
if (featureLayer.SelectionSymbol == null) {
// SYMBOLOGY FOR WHERE CLAUSE SELECTION
var selectedFeatureSymbol = AGSSimpleMarkerSymbol.SimpleMarkerSymbolWithColor(UIColor.FromRGBA(0.78f, 0.3f, 0.19f, 1f));
selectedFeatureSymbol.Style = AGSSimpleMarkerSymbolStyle.Circle;
selectedFeatureSymbol.Size = new SizeF(10, 10);
featureLayer.SelectionSymbol = selectedFeatureSymbol;
}
if (featureLayer.WeakQueryDelegate == null) {
featureLayer.WeakQueryDelegate = this;
}
if (countryName == "None") {
// CLEAR SELECTION
featureLayer.ClearSelection();
}
else {
var selectQuery = AGSQuery.Query();
selectQuery.Where = string.Format("COUNTRY = '{0}'", countryName);
featureLayer.SelectFeaturesWithQuery(selectQuery, AGSFeatureLayerSelectionMethod.New);
}
// Dismiss action sheet
var pickerSheet = (UIActionSheet)picker.Superview;
pickerSheet.DismissWithClickedButtonIndex(0, true);
}
#endregion
#region "AGSFeature Query Delegate part"
[Export("featureLayer:operation:didSelectFeaturesWithFeatureSet:")]
public virtual void DidSelectFeaturesWithFeatureSet(AGSFeatureLayer featureLayer, NSOperation op, AGSFeatureSet featureSet) {
AGSMutableEnvelope env = null;
foreach (var selectedFature in featureSet.Features) {
if (env != null) {
env.UnionWithEnvelope(selectedFature.Geometry.Envelope);
}
else {
env = (AGSMutableEnvelope)selectedFature.Geometry.Envelope.MutableCopy();
}
}
this.MapView.ZoomToGeometry(env, 20, true);
}
#endregion
好了, 现在可以运行一下这个测试程序, 如果没有错误的话, 看到下面的程序截图:
点击按钮时, 屏幕截图如下:
选择 US 时, 截图如下: