internal static FrameworkElement UpdateMask(UIView owner, UIView superView = null) { superView = superView ?? owner.Superview; var layer = owner.Layer; var clippingParentResult = GetClippingParent(owner); if ( clippingParentResult.clippingParent != null && owner is FrameworkElement tfe #if DEBUG && (CanClipSelector?.Invoke(owner) ?? true) #endif ) { var clippingParent = clippingParentResult.clippingParent; if (clippingParentResult.child is FrameworkElement cfe && !cfe.ClipChildrenToBounds) { // If the immediate child of the clipping parent is not clipping its children, then the // clipping parent is its parent (Ellipse -> Canvas -> Grid -> StackPanel) clippingParent = clippingParentResult.clippingParent.Superview; } var absolutePosition = ConvertOriginPointToView(owner, clippingParent); var clippingBounds = clippingParent.Bounds; if (clippingBounds != CGRect.Empty) { var maskLayer = new CoreAnimation.CAShapeLayer(); var maskRect = new CGRect(-absolutePosition.X, -absolutePosition.Y, clippingBounds.Width, clippingBounds.Height); maskLayer.Path = UIBezierPath.FromRect(maskRect).CGPath; layer.Mask = maskLayer; if (typeof(UIElement).Log().IsEnabled(LogLevel.Debug)) { typeof(UIElement).Log().LogDebug($"UpdateMask o:{owner.GetType()} p:{clippingParent.GetType()} f:{owner.Frame} b:{owner.Bounds} m:{maskRect} t:{owner.Transform}"); } CreateDebugLayer(owner, layer, absolutePosition, clippingBounds); return(clippingParent as FrameworkElement); } else { CreateDebugLayer(owner, layer, absolutePosition, clippingBounds); if (typeof(UIElement).Log().IsEnabled(LogLevel.Debug)) { typeof(UIElement).Log().LogDebug($"Mask disabled for CGRect.Empty parent o:{owner.GetType()}/{owner.GetHashCode():X8} p:{clippingParent.GetType()}/{clippingParent.GetHashCode():X8} f:{owner.Frame} b:{owner.Bounds} t:{owner.Transform}"); } } } layer.Mask = null; return(null); }
private static void CreateDebugLayer(UIView owner, CALayer layer, CGPoint absolutePosition, CGRect clippingBounds) { if (FeatureConfiguration.UIElement.ShowClippingBounds) { if (_debugLayers == null) { _debugLayers = new Dictionary <UIView, CALayer>(); } if (_debugLayers.TryGetValue(owner, out var previousLayer)) { previousLayer.RemoveFromSuperLayer(); _debugLayers.Remove(owner); } var debugLayer = new CoreAnimation.CAShapeLayer(); var debugMaskRect = new CGRect( -absolutePosition.X, -absolutePosition.Y, clippingBounds.Width < 1 ? 5 : clippingBounds.Width, clippingBounds.Height < 1 ? 5 : clippingBounds.Height ); debugLayer.Path = UIBezierPath.FromRect(debugMaskRect).CGPath; debugLayer.Frame = debugMaskRect; debugLayer.LineWidth = 2; if (clippingBounds.Width == 0 && clippingBounds.Height == 0) { debugLayer.StrokeColor = Colors.Red; } else if (clippingBounds.Width < 1 || clippingBounds.Height < 1) { debugLayer.StrokeColor = Colors.Purple; } else { debugLayer.StrokeColor = Colors.Blue; } debugLayer.Opaque = false; debugLayer.BackgroundColor = UIColor.Clear.CGColor; debugLayer.FillColor = UIColor.Clear.CGColor; debugLayer.MasksToBounds = false; _debugLayers.Add(owner, debugLayer); if (layer.Sublayers != null) { layer.InsertSublayer(debugLayer, layer.Sublayers.Length); } else { layer.AddSublayer(debugLayer); } } }