Adjust letter spacing in iOS 7
Asked Answered
D

3

40

In iOS 7, when navigating back using the new swipe-from-edge-of-screen gesture, the title of the Back button ("Artists") fades from being pink (in the example below) and having regular font weight to being black and having bold font weight.

enter image description here

It seems to me that the animation uses two different labels in order to achieve this effect; one fading out as the other fades in. However, Apple has somehow adjusted the font so that the regular label perfectly overlays the bold one, thus creating the illusion of a single label morphing between two different weights and colors.

Have they simply adjusted the letter spacing on the regular font so that it matches onto the bold one? In that case, how would that be achieved in iOS 7? Does Text Kit have any awesome features for doing this or how should I go about it?

Doyledoyley answered 15/1, 2014 at 14:54 Comment(0)
G
95

You can adjust letter spacing like this, using NSAttributedString.

In Objective-C:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"The Clash"];
[attributedString addAttribute:NSKernAttributeName
                         value:@(1.4)
                         range:NSMakeRange(0, 9)];
    
self.label.attributedText = attributedString;

In Swift 3:

let attributedString = NSMutableAttributedString(string: "The Clash")
attributedString.addAttribute(NSKernAttributeName, value: CGFloat(1.4), range: NSRange(location: 0, length: 9))

label.attributedText = attributedString

In Swift 4 and later:

label.attributedText = NSAttributedString(string: "The Clash", attributes: [.kern: 1.4])

More info on kerning is available in Typographical Concepts from the Text Programming Guide.

I don't think there's a TextKit feature that will automatically match font spacing between bold and regular text.

Gaskins answered 15/1, 2014 at 15:15 Comment(5)
Anyone knows about the differences for letter spacing vs. kerning? As I see, NSKernAttributeName is about kerning but not about letter spacing.Metaphosphate
@Metaphosphate There's no tracking attribute - see devsign.co/notes/tracking-and-character-spacingGaskins
What about using tracking and kerning in same string. For example tracking = 10, kerning = default. ?Vouchsafe
This answer is correct but if you want to do it from storyboard check this: https://mcmap.net/q/282264/-how-to-set-kerning-in-iphone-uilabelReface
For later versions key has been renamed to NSAttributedString.Key.kernSchoolboy
A
5

For Swift 4+ the syntax is as simple as:

let text = NSAttributedString(string: "text", attributes: [.kern: 1.4])
Audit answered 13/3, 2018 at 9:1 Comment(0)
A
2

With Swift 5.3 and iOS 14, NSAttributedString.Key has a static property called kern. kern has the following declaration:

static let kern: NSAttributedString.Key

The value of this attribute is an NSNumber object containing a floating-point value. This value specifies the number of points by which to adjust kern-pair characters. Kerning prevents unwanted space from occurring between specific characters and depends on the font. The value 0 means kerning is disabled. The default value for this attribute is 0.

The following Playground code shows a possible implementation of kern in order to have some letter spacing in your NSAttributedString:

import PlaygroundSupport
import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let string = "Some text"
        let paragraph = NSMutableParagraphStyle()
        paragraph.alignment = .center
        let attributes: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.kern: 10,
            NSAttributedString.Key.paragraphStyle: paragraph
        ]
        let attributedString = NSMutableAttributedString(
            string: string,
            attributes: attributes
        )

        let label = UILabel()
        label.attributedText = attributedString

        view.backgroundColor = .white
        view.addSubview(label)

        label.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            label.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        ])
    }
}

PlaygroundPage.current.liveView = ViewController()
Allomerism answered 27/1, 2018 at 0:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.