- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
在 iOS 上使用自定义 map /渲染器时遇到两个问题。
我有一个自定义 map 类,它带有一个放置在 map 上的圆圈。 slider 控件根据可绑定(bind)属性调整圆圈的大小。
当 slider 值发生变化时,圆的半径属性会更新为所选值。但如您所见,它并没有更新 map 上的半径,而是将圆移动到曲线内的新位置。
当圆移出 x 像素时,它会在可见边界外消失或被截断。
这些是正在使用的类:
页面.xaml:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:CompanyName.Data.ViewModels.MapWithCircleSlider;assembly=CompanyName"
xmlns:local="clr-namespace:CompanyName.UI;assembly=CompanyName"
x:Class="CompanyName.UI.Pages.MapWithCircleSlider"
Title="{Binding Title}">
<ContentPage.BindingContext>
<vm:MapWithCircleSliderViewModel></vm:MapWithCircleSliderViewModel>
</ContentPage.BindingContext>
<ContentPage.Content>
<ScrollView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<local:CircleMap Grid.Row="0" CircleRadius="{Binding CircleRadius}" Latitude="{Binding Latitude}" Longitude="{Binding Longitude}" MapRadius="{Binding MapRadius}" IsShowingUser="true" HasZoomEnabled="true" />
<!--<Image Grid.Row="0" HorizontalOptions="Center" VerticalOptions="Center" Source="ic_place_green_48dp.png" />-->
<StackLayout Grid.Row="1" Padding="32,16">
<Entry VerticalOptions="Start" Placeholder="navn *" Text="{Binding Name}">
<Entry.Style>
<OnPlatform x:TypeArguments="Style">
<On Platform="iOS" Value="{x:Static local:Styling.IosEntryStyle}" />
</OnPlatform>
</Entry.Style>
</Entry>
<Label VerticalOptions="Center" HorizontalOptions="Center" Text="{Binding CircleRadius, StringFormat='{0}m'}" />
<Slider VerticalOptions="End" Maximum="{Binding Maximum}" Minimum="{Binding Minimum}" Value="{Binding CircleRadius}" />
<!-- NB: Maximum must be set before Minimum, ref: https://bugzilla.xamarin.com/show_bug.cgi?id=23665 -->
</StackLayout>
</Grid>
</ScrollView>
</ContentPage.Content>
</ContentPage>
页面 View 模型:
using System;
using CompanyName.ViewModels;
namespace CompanyName.Data.ViewModels.MapWithCircleSlider
{
public class MapWithCircleSliderViewModel : ViewModelBase
{
private string name;
private int circleRadius;
private float latitude;
private float longitude;
private int mapRadius;
public MapWithCircleSliderViewModel()
{
Name = "Labs";
CircleRadius = 200;
MapRadius = 200;
Latitude = 58.9698634f;
Longitude = 5.7331874f;
}
public int Maximum => 1000;
public int Minimum => 100;
public string Id { get; set; }
public bool IsEditMode { get; set; }
public string Title { get; set; }
public string Name
{
get => name;
set
{
if (name == value) return;
name = value;
OnPropertyChanged("Name");
}
}
public int CircleRadius
{
get => circleRadius;
set
{
if (circleRadius == value) return;
circleRadius = value;
OnPropertyChanged("CircleRadius");
}
}
public float Latitude
{
get => latitude;
set
{
if (Math.Abs(latitude - value) < float.Epsilon) return;
latitude = value;
OnPropertyChanged("Latitude");
}
}
public float Longitude
{
get => longitude;
set
{
if (Math.Abs(longitude - value) < float.Epsilon) return;
longitude = value;
OnPropertyChanged("Longitude");
}
}
public int MapRadius
{
get => mapRadius;
set
{
if (mapRadius == value) return;
mapRadius = value;
OnPropertyChanged("MapRadius");
}
}
}
}
圆图.cs
using System.Diagnostics;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
namespace CompanyName.UI
{
public class CircleMap : Map
{
private const int DefaultCircleRadius = 100;
private const float DefaultLatitude = 58.8523208f;
private const float DefaultLongitude = 5.7326743f;
private const int DefaultMapRadius = 150;
public static readonly BindableProperty CircleRadiusProperty = BindableProperty.Create("CircleRadius", typeof(int), typeof(CircleMap), DefaultCircleRadius, BindingMode.TwoWay, propertyChanged: OnCircleRadiusPropertyChanged);
public static readonly BindableProperty LatitudeProperty = BindableProperty.Create("Latitude", typeof(float), typeof(CircleMap), DefaultLatitude, BindingMode.TwoWay, propertyChanged: OnLatitudePropertyChanged);
public static readonly BindableProperty LongitudeProperty = BindableProperty.Create("Longitude", typeof(float), typeof(CircleMap), DefaultLongitude, BindingMode.TwoWay, propertyChanged: OnLongitudePropertyChanged);
public static readonly BindableProperty MapRadiusProperty = BindableProperty.Create("MapRadius", typeof(int), typeof(CircleMap), DefaultMapRadius, BindingMode.TwoWay, propertyChanged: OnMapRadiusPropertyChanged);
public CircleMap() : base(MapSpan.FromCenterAndRadius(new Position(DefaultLatitude, DefaultLongitude), Distance.FromMeters(DefaultMapRadius))) { }
public int CircleRadius
{
get => (int)GetValue(CircleRadiusProperty);
set => SetValue(CircleRadiusProperty, value);
}
public float Latitude
{
get => (float)GetValue(LatitudeProperty);
set => SetValue(LatitudeProperty, value);
}
public float Longitude
{
get => (float)GetValue(LongitudeProperty);
set => SetValue(LongitudeProperty, value);
}
public int MapRadius
{
get => (int)GetValue(MapRadiusProperty);
set => SetValue(MapRadiusProperty, value);
}
private static void OnCircleRadiusPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var circleMap = (CircleMap)bindable;
circleMap.CircleRadius = (int)newValue;
}
private static void OnLatitudePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var circleMap = (CircleMap)bindable;
circleMap.Latitude = (float)newValue;
MoveToRegion(circleMap);
}
private static void OnLongitudePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var circleMap = (CircleMap)bindable;
circleMap.Longitude = (float)newValue;
MoveToRegion(circleMap);
}
private static void OnMapRadiusPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var circleMap = (CircleMap)bindable;
circleMap.MapRadius = (int)newValue;
MoveToRegion(circleMap);
}
private static void MoveToRegion(CircleMap circleMap)
{
circleMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(circleMap.Latitude, circleMap.Longitude), Distance.FromMeters(circleMap.MapRadius)));
}
}
}
CustomMapRenderer.cs(iOS):
using CompanyName.UI;
using MapKit;
using ObjCRuntime;
using System;
using System.ComponentModel;
using System.Linq;
using Xamarin.Forms;
using Xamarin.Forms.Maps.iOS;
using Xamarin.Forms.Platform.iOS;
using CompanyName.iOS.Renderers.CustomRenderer;
using CompanyName.Utilities;
[assembly: ExportRenderer(typeof(CircleMap), typeof(CustomMapRenderer))]
namespace CompanyName.iOS.Renderers.CustomRenderer
{
/// <remarks>
/// https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/custom-renderer/map/circle-map-overlay/#Creating_the_Custom_Renderer_on_iOS
/// </remarks>
public class CustomMapRenderer : MapRenderer
{
private CircleMap circleMap;
private MKCircleRenderer circleRenderer;
private MKMapView NativeMap => Control as MKMapView;
protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
try
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
if (Control is MKMapView nativeMap)
{
nativeMap.RemoveOverlays(nativeMap.Overlays);
nativeMap.OverlayRenderer = null;
circleRenderer = null;
}
}
if (e.NewElement != null)
{
circleMap = (CircleMap)e.NewElement;
NativeMap.OverlayRenderer = GetOverlayRenderer;
AddOverlay();
}
}
catch (Exception ex)
{
//Logger.LogException(ex, GetType().Name);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (sender == null) return;
circleMap = (CircleMap)sender;
if (e.PropertyName == "VisibleRegion") OnVisibleRegionChanged();
if (e.PropertyName == CircleMap.CircleRadiusProperty.PropertyName) RedrawOverlay();
}
private MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
{
if (circleRenderer == null && !Equals(overlayWrapper, null))
{
var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay;
circleRenderer = new MKCircleRenderer(overlay as MKCircle)
{
Alpha = 0.15f,
FillColor = CompanyName.Constants.Colors.Skobeloff500.ToUIColor(),
LineWidth = 1,
StrokeColor = CompanyName.Constants.Colors.Skobeloff500.ToUIColor()
};
}
return circleRenderer;
}
private void OnVisibleRegionChanged()
{
SetNewCoordinates();
RedrawOverlay();
}
private void SetNewCoordinates()
{
circleMap.Latitude = (float)circleMap.VisibleRegion.Center.Latitude;
circleMap.Longitude = (float)circleMap.VisibleRegion.Center.Longitude;
circleMap.MapRadius = (int)circleMap.VisibleRegion.Radius.Meters;
}
private void RedrawOverlay()
{
RemoveOverlays();
AddOverlay();
}
private void RemoveOverlays()
{
if (NativeMap?.Overlays == null) return;
if (NativeMap.Overlays.Any()) NativeMap.RemoveOverlays(NativeMap.Overlays);
}
private void AddOverlay()
{
var circleOverlay = MKCircle.Circle(new CoreLocation.CLLocationCoordinate2D(circleMap.Latitude, circleMap.Longitude), circleMap.CircleRadius);
NativeMap.AddOverlay(circleOverlay);
}
}
}
非常感谢任何反馈/建议!
最佳答案
您可以尝试刷新 circleRenderer
来实现您的效果,例如:
private void RemoveOverlays()
{
if (NativeMap?.Overlays == null) return;
if (NativeMap.Overlays.Any())
{
NativeMap.RemoveOverlays(NativeMap.Overlays);
circleRenderer = null;
NativeMap.OverlayRenderer = GetOverlayRenderer;
}
}
关于ios - Xamarin Forms Maps Circle 自定义渲染器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48868681/
我之前让 dll 注入(inject)器变得简单,但我有 Windows 7,我用 C# 和 C++ 做了它,它工作得很好!但是现在当我在 Windows 8 中尝试相同的代码时,它似乎没有以正确的方
我正在尝试制作一个名为 core-splitter 的元素,该元素在 1.0 中已弃用,因为它在我们的项目中起着关键作用。 如果您不知道 core-splitter 的作用,我可以提供一个简短的描述。
我有几个不同的蜘蛛,想一次运行所有它们。基于 this和 this ,我可以在同一个进程中运行多个蜘蛛。但是,我不知道如何设计一个信号系统来在所有蜘蛛都完成后停止 react 器。 我试过了: cra
有没有办法在达到特定条件时停止扭曲 react 器。例如,如果一个变量被设置为某个值,那么 react 器应该停止吗? 最佳答案 理想情况下,您不会将变量设置为一个值并停止 react 器,而是调用
https://code.angularjs.org/1.0.0rc9/angular-1.0.0rc9.js 上面的链接定义了外部js文件,我不知道Angular-1.0.0rc9.js的注入(in
我正在尝试运行一个函数并将服务注入(inject)其中。我认为这可以使用 $injector 轻松完成.所以我尝试了以下(简化示例): angular.injector().invoke( [ "$q
在 google Guice 中,我可以使用函数 createInjector 创建基于多个模块的注入(inject)器。 因为我使用 GWT.create 在 GoogleGin 中实例化注入(in
我在 ASP.NET Core 1.1 解决方案中使用配置绑定(bind)。基本上,我在“ConfigureServices Startup”部分中有一些用于绑定(bind)的简单代码,如下所示: s
我在 Spring MVC 中设置 initBinder 时遇到一些问题。我有一个 ModelAttribute,它有一个有时会显示的字段。 public class Model { privat
我正在尝试通过jquery post发布knockoutjs View 模型 var $form = $('#barcodeTemplate form'); var data = ko.toJS(vm
如何为包含多态对象集合的复杂模型编写自定义模型绑定(bind)程序? 我有下一个模型结构: public class CustomAttributeValueViewModel { publi
您好,我正在尝试实现我在 this article 中找到的扩展方法对于简单的注入(inject)器,因为它不支持开箱即用的特定构造函数的注册。 根据这篇文章,我需要用一个假的委托(delegate)
你好,我想自动注册我的依赖项。 我现在拥有的是: public interface IRepository where T : class public interface IFolderReposi
我正在使用 Jasmine 测试一些 Angular.js 代码。为此,我需要一个 Angular 注入(inject)器: var injector = angular.injector(['ng'
我正在使用 Matlab 代码生成器。不可能包含代码风格指南。这就是为什么我正在寻找一个工具来“ reshape ”、重命名和重新格式化生成的代码,根据我的: 功能横幅约定 文件横幅约定 命名约定 等
这个问题在这里已经有了答案: Where and why do I have to put the "template" and "typename" keywords? (8 个答案) 关闭 8
我开发了一种工具,可以更改某些程序的外观。为此,我需要在某些进程中注入(inject)一个 dll。 现在我基本上使用这个 approach .问题通常是人们无法注入(inject) dll,因为他们
我想使用 swing、spring 和 hibernate 编写一个 java 应用程序。 我想使用数据绑定(bind)器用 bean 的值填充 gui,并且我还希望它反射(reflect) gui
我有这段代码,当两个蜘蛛完成后,程序仍在运行。 #!C:\Python27\python.exe from twisted.internet import reactor from scrapy.cr
要点是 Spring Batch (v2) 测试框架具有带有 @Autowired 注释的 JobLauncherTestUtils.setJob。我们的测试套件有多个 Job 类提供者。因为这个类不
我是一名优秀的程序员,十分优秀!