SetNeedsDisplay导致应用程序在TouchesMoved事件中崩溃
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SetNeedsDisplay导致应用程序在TouchesMoved事件中崩溃相关的知识,希望对你有一定的参考价值。
在视觉工作室2017中使用xamarin for windows。我有UIScrollView with zoom和UIView作为缩放视图:
public class PlanMarkingPageRenderer : PageRenderer
{
private UIScrollView scrollView;
private PlanMarkingView planView;
private ToolbarItem markItem;
private bool _markEnabled = false;
private nfloat _minScale;
private nfloat _zoomScale;
public bool MarkEnabled
{
get
{
return _markEnabled;
}
set
{
_markEnabled = value;
scrollView.ScrollEnabled = _markEnabled;
if (_markEnabled)
{
markItem.Text = "Zoom";
scrollView.MinimumZoomScale = _zoomScale;
scrollView.MaximumZoomScale = _zoomScale;
planView.MarkEnabled = true;
scrollView.MultipleTouchEnabled = false;
scrollView.ScrollEnabled = false;
scrollView.DelaysContentTouches = false;
}
else
{
markItem.Text = "Mark";
scrollView.MinimumZoomScale = _minScale;
scrollView.MaximumZoomScale = 1;
planView.MarkEnabled = false;
scrollView.MultipleTouchEnabled = true;
scrollView.ScrollEnabled = true;
scrollView.DelaysContentTouches = true;
}
}
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
var page = e.NewElement as PlanMarkingPage;
markItem = new ToolbarItem("Mark", null, () =>
{
MarkEnabled = !MarkEnabled;
});
page.ToolbarItems.Add(markItem);
var view = NativeView;
scrollView = new UIScrollView() { Frame = UIScreen.MainScreen.Bounds };
var img1 = FromUrl(@"");
var img = img1.CGImage;
scrollView.ContentSize = img1.Size;
var scrollViewFrame = scrollView.Frame;
var scaleWidth = scrollViewFrame.Size.Width / img.Width;
var scaleHeight = scrollViewFrame.Size.Height / img.Height;
_minScale = (nfloat)Math.Min(scaleHeight, scaleWidth);
scrollView.MinimumZoomScale = _minScale;
scrollView.MaximumZoomScale = 1;
scrollView.ZoomScale = _minScale;
planView = new PlanMarkingView() { Frame = new CGRect(0, 0, img.Width, img.Height) };
planView.ContentMode = UIViewContentMode.Redraw;
planView.Image = img;
scrollView.AddSubview(planView);
scrollView.ViewForZoomingInScrollView += (UIScrollView sv) => { return planView; };
view.AddSubview(scrollView);
scrollView.ZoomScale = _minScale;
_zoomScale = _minScale;
}
static UIImage FromUrl(string uri)
{
using (var url = new NSUrl(uri))
using (var data = NSData.FromUrl(url))
return UIImage.LoadFromData(data);
}
}
添加图像,在planView
上绘制..缩放和滚动工作正常。现在,我想用触摸画一些东西。
与SetNeedsDisplay()
一致后,我的应用程序在一次或几次移动后崩溃
public class PlanMarkingView : UIView
{
public bool MarkEnabled { get; set; }
public CGImage Image;
CGPoint initialPoint;
CGPoint latestPoint;
public PlanMarkingView()
{
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
}
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);
if (!MarkEnabled) return;
if (touches.AnyObject is UITouch touch)
{
initialPoint = touch.LocationInView(this);
}
}
public override void TouchesMoved(NSSet touches, UIEvent evt)
{
base.TouchesMoved(touches, evt);
if (!MarkEnabled) return;
if (touches.AnyObject is UITouch touch)
{
latestPoint = touch.LocationInView(this);
SetNeedsDisplay();
}
}
public override void TouchesEnded(NSSet touches, UIEvent evt)
{
base.TouchesEnded(touches, evt);
MarkEnabled = false;
}
public override void TouchesCancelled(NSSet touches, UIEvent evt)
{
base.TouchesCancelled(touches, evt);
MarkEnabled = false;
}
}
答案
[Export("layerClass")]
public static Class LayerClass()
{
return new Class(typeof(CATiledLayer));
}
public PlanMarkingView(nfloat scale)
{
tiledLayer = Layer as CATiledLayer;
tiledLayer.LevelsOfDetail = 8;
tiledLayer.LevelsOfDetailBias = 3;
tiledLayer.TileSize = new CGSize(1024f, 1024f);
tiledLayer.BackgroundColor = UIColor.Red.CGColor;
tiledLayer.BorderWidth = 0;
}
[Export("drawLayer:inContext:")]
public override void DrawLayer(CALayer layer, CGContext context)
{
context.SetFillColor(1f, 1f, 1f, 1f);
context.FillRect(Bounds);
context.SaveState();
context.TranslateCTM(0f, Bounds.Height);
context.ScaleCTM(1f, -1f);
context.DrawImage(new CGRect(0, 0, Image.Width, Image.Height), Image);
if (MarkEnabled && initialPoint != null && latestPoint != null)
{
}
context.RestoreState();
}
使用CATiledLayer绘制大图像
以上是关于SetNeedsDisplay导致应用程序在TouchesMoved事件中崩溃的主要内容,如果未能解决你的问题,请参考以下文章
setNeedsDisplay 是立即生效还是只是排队等候?
setNeedsLayout 和 setNeedsDisplay
setNeedsDisplay 未按预期在子视图中触发 drawRect
setNeedsDisplay() 和 redraw() 函数调用之间的延迟