I am working on a CATextLayer that I want to use in both Mac and iOS. Can I control the vertical alignment of the text within the layer?
In this particular case, I want to center it vertically -- but information about other vertical alignments would also be of interest.
EDIT: I found this, but I can't make it work.
I slightly modified this answer by @iamkothed. The differences are:
NSString.size(with: Attributes)
. I don't know if it's an improvement over(height-fontSize)/2 - fontSize/10
, but I like to think that it is. Although, in my experience,NSString.size(with: Attributes)
doesn't always return the most appropriate size.invertedYAxis
property. It was useful for my purposes of exporting thisCATextLayer
subclass usingAVVideoCompositionCoreAnimationTool
. AVFoundation operates in "normal" y axis, and that's why I had to add this property.NSString
. You can use Swift'sString
class though, because it automatically casts toNSString
.It ignores
CATextLayer.fontSize
property and completely relies onCATextLayer.font
property which MUST be aUIFont
instance.The code for Swift 3, based on code @iamktothed
If you use an attributed string for setting font properties, than you can use function size() from NSAttributedString to calculate height of string. I think this code also resolve the problems described by @Enix
So there is no "direct" way of doing this but you can accomplish the same thing by using text metrics:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/NSString_UIKit_Additions/Reference/Reference.html
... for example, find the size of the text then use that information to place it where you want in the parent layer. Hope this helps.
thank @iamktothed, it works. following is swift 3 version:
It is an late answer, but I have the same question these days, and have solved the problem with following investigation.
Vertical align depends on the text you need to draw, and the font you are using, so there is no one way solution to make it vertical for all cases.
But we can still calculate the vertical mid point for different cases.
According to apple's About Text Handling in iOS, we need to know how the text is drawn.
For example, I am trying to make vertical align for weekdays strings: Sun, Mon, Tue, ....
For this case, the height of the text depends on cap Height, and there is no descent for these characters. So if we need to make these text align to the middle, we can calculate the offset of the top of cap character, e.g. The position of the top of character "S".
According to the the figure below:
The top space for the capital character "S" would be
And the bottom space for the capital character "S" would be
So we need to move "S" a little bit off the top by:
That equals to:
Then I can make the text vertical align middle.
Conclusion:
If your text does not include any character exceed the baseline, e.g. "p", "j", "g", and no character over the top of cap height, e.g. "f". The you can use the formula above to make the text align vertical.
If your text include character below the baseline, e.g. "p", "j", and no character exceed the top of cap height, e.g. "f". Then the vertical formula would be:
If your text include does not include character drawn below the baseline, e.g. "j", "p", and does include character drawn above the cap height line, e.g. "f". Then y would be:
If all characters would be occurred in your text, then y equals to:
You need to know where CATextLayer will put the baseline of your text. Once you know that, offset the coordinate system within the layer, i.e. adjust bounds.origin.y by the difference between where the baseline normally sits and where you want it to be, given the metrics of the font.
CATextLayer is a bit of a black box and finding where the baseline will sit is a bit tricky - see my answer here for iOS - I've no idea what the behaviour is on Mac.