I am masking an image within a stack view and for some odd reason, my mask is not aligning/resizing correctly with the image.
Here is a demonstration of what's occurring as I'm dynamically adding instances of this image in a stack view while each subview is resized within its boundaries and spacing.
As you can see, the mask retains the original size of the image and not the resized version. I've tried many different width & height variations including the bounds.width, layer.frame.width, frame.width, frame.origin.x, etc, and had no luck.
Current code in Swift 2:
let testPicture:UIImageView = UIImageView(image: UIImage(named: "myPicture"))
testPicture.contentMode = .ScaleAspectFit
testPicture.layer.borderWidth = 1
testPicture.clipsToBounds = true
testPicture.layer.masksToBounds = true
view.layer.addSublayer(shapeLayer)
var width = testPicture.layer.frame.width
var height = testPicture.layer.frame.height
let center = CGPointMake(width/2, height/2)
let radius = CGFloat(CGFloat(width) / 2)
// Mask
let yourCarefullyDrawnPath = UIBezierPath()
yourCarefullyDrawnPath.moveToPoint(center)
yourCarefullyDrawnPath.addArcWithCenter(center,
radius: radius,
startAngle: 0,
endAngle: CGFloat( (0.80*360.0) * M_PI / 180.0),
clockwise: true)
yourCarefullyDrawnPath.closePath()
let maskPie = CAShapeLayer()
maskPie.frame = testPicture.layer.bounds
testPicture.clipsToBounds = true
testPicture.layer.masksToBounds = true
maskPie.path = yourCarefullyDrawnPath.CGPath
testPicture.layer.mask = maskPie
// Add Into Stackview
self.myStackView.addArrangedSubview(testPicture)
self.myStackView.layoutIfNeeded()
I suspect that I'm fetching the wrong width and height in order to generate the center and radius variables although after trying all the different widths and heights I can find, I still cannot achieve the correct sizes. :-(
You'll want to get the frame the image occupies within the image view.
Unfortunately,
UIImageView
provides no native support for doing this, however you can calculate this fairly simply. I have already created a function that will take a given outer rect, and a given inner rect and return the inner rect after it's been aspect fitted to sit within the outer rect.A Swift version of the function would look something like this:
The other thing you need to do is subclass
UIImageView
and override thelayoutSubviews
method. This is because as you're adding your image views to aUIStackView
- you're no longer in control of the frames of your image views. Therefore by overridinglayoutSubviews
, you'll be able to update your mask whenever the stack view alters the frame of the view.Something like this should achieve the desired result:
You can then create your image views from your view controller and add them to your stack view as normal.
Gives me the following result:
Unrelated Ramblings...
Just noticed in your code that you're doing this:
These both do the same thing.
A
UIView
is no more than a wrapper for an underlyingCALayer
. However for convenience, someCALayer
properties also have aUIView
equivalent. All theUIView
equivalent does is forward to message down to theCALayer
when it is set, and retrieve a value from theCALayer
when it is 'get'ed.clipsToBounds
andmasksToBounds
are one of these pairs (although annoyingly they don't share the same name).Try doing the following:
Seeing as you're working with a
UIView
,clipToBounds
is generally the preferred property to update.