fraggjkee fraggjkee - 3 months ago 18
iOS Question

Complex image (bubble / pin) and [UIImage resizableImageWithCapInsets:]

I am trying to create a resizable version of the following image (40x28, the small triangle at the bottom should be centered horizontally):

enter image description here

UIEdgeInsets imageInsets = UIEdgeInsetsMake(4.0f, 4.0f, 8.0f, 4.0f);
UIImage *pinImage = [[UIImage imageNamed:@"map_pin"] resizableImageWithCapInsets:imageInsets];


As per the documentation, this simple approach won't work since my triangle falls into resizable area (fixed height but scalable width):

enter image description here

This will cause the same problem as described in this very similar SO post - duplicated (tiled) triangles. But unfortunately their solution doesn't work for my particular case since excluding the triangle from scalable area causes its misplacement and it won't be centered horizontally due to obvious reasons.

So I wonder... is it possible to achieve my goal using the
[UIImage resizableImageWithCapInsets:]
method at all? Or may be I should try something else like drawing everything in the code instead?

Basically, I would like to implement something like Info Windows from Google Maps SDK:

enter image description here

Answer

You can achieve that by using UIBezierPath.The following code in swift but you should be able to achieve the same thing in Objective-C

Instead of starting the code with a straight line :

path.moveToPoint(CGPoint(x: 300, y: 0))

I instead start with an arc (upper right):

path.addArcWithCenter(CGPoint(x: 300-10, y: 50), radius: 10 , startAngle: 0 , endAngle: CGFloat(M_PI/2)  , clockwise: true) //1st rounded corner

and by doing this, I have four rounded corners and I just need to add a straight line at the end of the code right before:

path.closePath()  

Here is the code and a screenshot:

let path = UIBezierPath()
path.addArcWithCenter(CGPoint(x: 300-10, y: 50), radius: 10 , startAngle: 0 , endAngle: CGFloat(M_PI/2)  , clockwise: true) //1st rounded corner
path.addArcWithCenter(CGPoint(x: 200, y: 50), radius:10, startAngle: CGFloat(2 * M_PI / 3), endAngle:CGFloat(M_PI) , clockwise: true)// 2rd rounded corner
path.addArcWithCenter(CGPoint(x: 200, y: 10), radius:10, startAngle: CGFloat(M_PI), endAngle:CGFloat(3 * M_PI / 2), clockwise: true)// 3rd rounded corner
// little triangle
path.addLineToPoint(CGPoint(x:240 , y:0))
path.addLineToPoint(CGPoint(x: 245, y: -10))
path.addLineToPoint(CGPoint(x:250, y: 0))
path.addArcWithCenter(CGPoint(x: 290, y: 10), radius: 10, startAngle: CGFloat(3 * M_PI / 2), endAngle: CGFloat(2 * M_PI ), clockwise: true)
path.addLineToPoint(CGPoint(x:300 , y:50))
path.closePath()

enter image description here