I deep into the Core Animation and have some problem with layer masking
I try to make a complex UI layer with transparent things for study reasons
This view a have and put into the ViewController
public class TestView : UIView
{
public TestView()
{
Layer.Delegate = this;
Frame = new CGRect(100f,200f, 100f, 100f);
}
public override void LayoutSublayersOfLayer(CALayer layer)
{
base.LayoutSublayersOfLayer(layer);
var bounds = Bounds;
var circleFrame = new CGRect(20, 20, 60, 60);
var imageFrame = new CGRect(30, 30, 40, 40);
Layer.BorderWidth = 5;
Layer.BorderColor = UIColor.Red.CGColor;
Layer.CornerRadius = 4;
var gradientLayer = new CAGradientLayer();
gradientLayer.Colors = new[] { UIColor.Green.CGColor, UIColor.Red.CGColor };
gradientLayer.Frame = bounds;
Layer.AddSublayer(gradientLayer);
var maskOfGradientLayer = new CAShapeLayer();
var path = UIBezierPath.FromRoundedRect(circleFrame, 30);
path.UsesEvenOddFillRule = true;
maskOfGradientLayer.Path = path.CGPath;
maskOfGradientLayer.FillRule = CAShapeLayer.FillRuleEvenOdd;
maskOfGradientLayer.FillColor = UIColor.Black.CGColor;
maskOfGradientLayer.Frame = bounds;
gradientLayer.Mask = maskOfGradientLayer;
var maskOfMaskLayer = new CAShapeLayer();
maskOfMaskLayer.Frame = imageFrame;
maskOfMaskLayer.FillColor = UIColor.Black.CGColor;
maskOfMaskLayer.Contents = Bundles.ImageOff.CGImage;
Layer.AddSublayer(maskOfMaskLayer);
}
}
And that I have and this is exactly what I wanted.
But I also want can to make transparent in circle instead black color.
I tried to make like this maskOfGradientLayer.Mask = maskOfMaskLayer.
But this way maskOfMaskLayer
do nothing! It's not working like mask must do.
What I should to do?
All needed to do it is reverse image colors via Core Graphics, any color to transparent, transparent to any color. In this case, black color is enough
public static UIImage GetRevertImage(UIImage image, CGRect rect, CGRect cropFrame)
{
UIGraphics.BeginImageContextWithOptions(rect.Size, false, 1);
UIColor.Black.SetColor();
UIGraphics.RectFill(rect);
image.Draw(cropFrame, CGBlendMode.DestinationOut, 1);
var newImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return newImage;
}
And set mask of mask layer to parent layer
Layer.Mask = maskOfMaskLayer;
And final version of code:
public class TestView : UIView
{
public TestView()
{
Layer.Delegate = this;
Frame = new CGRect(50f, 50f, 100f, 100f);
}
public override void LayoutSublayersOfLayer(CALayer layer)
{
base.LayoutSublayersOfLayer(layer);
var bounds = Bounds;
var circleFrame = new CGRect(20, 20, 60, 60);
var imageFrame = new CGRect(30, 30, 40, 40);
Layer.BorderWidth = 5;
Layer.BorderColor = UIColor.Red.CGColor;
Layer.CornerRadius = 4;
Layer.MasksToBounds = true;
var gradientLayer = new CAGradientLayer();
gradientLayer.Colors = new[] {UIColor.Green.CGColor, UIColor.Red.CGColor};
gradientLayer.Frame = bounds;
Layer.AddSublayer(gradientLayer);
var maskOfGradientLayer = new CAShapeLayer();
var path = UIBezierPath.FromRoundedRect(circleFrame, 30);
path.UsesEvenOddFillRule = true;
maskOfGradientLayer.Path = path.CGPath;
maskOfGradientLayer.FillRule = CAShapeLayer.FillRuleEvenOdd;
maskOfGradientLayer.FillColor = UIColor.Black.CGColor;
maskOfGradientLayer.Frame = bounds;
gradientLayer.Mask = maskOfGradientLayer;
var maskOfMaskLayer = new CALayer();
maskOfMaskLayer.Frame = bounds;
var image = UIImage.FromBundle("Turn");
var reversedImage = GetReverseImage(image, bounds, imageFrame);
maskOfMaskLayer.Contents = reversedImage.CGImage;
Layer.Mask = maskOfMaskLayer;
}
private static UIImage GetReverseImage(UIImage image, CGRect rect, CGRect cropFrame)
{
UIGraphics.BeginImageContextWithOptions(rect.Size, false, 1);
UIColor.Black.SetColor();
UIGraphics.RectFill(rect);
image.Draw(cropFrame, CGBlendMode.DestinationOut, 1);
var newImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return newImage;
}
}