This is the 27th day of my participation in the More Text Challenge. For more details, see more text Challenge

This article translated from: www.hackingwithswift.com/articles/23…

SF Symbols is available during WWDC 2019. Since then, Apple has given us free Symbols to use in our apps, and it’s easy to use them. Recently, WWDC 2020 introduced SF Symbols 2.0, which makes it easier to use elegant Symbols in apps; And iOS 14 added the ability to render multi-color ICONS, and iOS 15 added the ability to have full control over a single layer. In this article, I’ll guide you on how to use SF symbols in your projects, and provide sample code for SwiftUI and UIKit;

Tip: The best way to view the Symbols icon is through the official, free SF Symbols app.

How to load SF Symbol

It’s very simple to load a symbol and just write “Star”, but if you’re using the SF Symbol application, you can right-click on any symbol and select the copy name.

In SwiftUI, loading an Image is done by placing the Image into the view hierarchy, using systemName.

Image(systemName: "star")
Copy the code

In UIKit, you need to use UIImage, and then place it in UIImageView, as follows:

let image = UIImage(systemName: "star")

let imageView = UIImageView(image: image)
Copy the code

How to insert SF Symbol into text

In SwiftUI, putting an image next to text does this:

Label("Please try again", systemImage: "xmark.circle")
Copy the code

If you want to put it in a text string, it’s best to interpolate the string with Image, like this:

Text("Please press the \(Image(systemName: "calendar")) button")
Copy the code

For UIKit, the code is a little more complicated because you need to use NSAttributedString and NSTextAttachment to render into a UILabel, but the same code allows you to place the image anywhere you want:

let attachment = NSTextAttachment()
attachment.image = UIImage(systemName: "xmark.circle")

let imageString = NSMutableAttributedString(attachment: attachment)
let textString = NSAttributedString(string: "Please try again")
imageString.append(textString)

let label = UILabel()
label.attributedText = imageString
label.sizeToFit()
Copy the code

How do I change the SF Symbol size

SF Symbols are completely vector graphics, so you can resize them freely without losing mass. This also applies to the built-in dynamic type size, where the SF Symbol adjusts itself to match other text in the user interface.

In SwiftUI, resizing SF Symbol is done using the built-in text style’s font() modifier, as shown below:

Image(systemName: "airplane")
    .font(.largeTitle)
Copy the code

Or use a custom font size like this:

Image(systemName: "house")
    .font(.system(size: 72))
Copy the code

In UIKit, adjust the size of the symbol is the use of UIImage. SymbolConfiguration, like this:

let config = UIImage.SymbolConfiguration(textStyle: .largeTitle)
let image = UIImage(systemName: "airplane", withConfiguration: config)
Copy the code

Or use a custom font size like this:

let config = UIImage.SymbolConfiguration(pointSize: 72)
let image = UIImage(systemName: "airplane", withConfiguration: config)
Copy the code

How to adjust the proportion of SF Symbol

You just saw how the SF Symbol attaches custom font sizes, allowing them to flow neatly through the text. However, we can also scale SF Symbols independently of their font size, which allows you to have more granular control over how they look in the user interface.

In SwiftUI, the proportions of SF symbols can be adjusted as follows:

Image(systemName: "house")
    .imageScale(.large)
Copy the code

As I said, this happens with any custom font, so you can use both fonts if you want:

Image(systemName: "house")
    .font(.largeTitle)
    .imageScale(.large)
Copy the code

In UIKit, this is done with another notation configuration, this time using the Scale constructor:

let config = UIImage.SymbolConfiguration(scale: .large)
let image = UIImage(systemName: "house", withConfiguration: config)
Copy the code

Again, you can provide custom fonts and proportions:

let config = UIImage.SymbolConfiguration(textStyle: .largeTitle, scale: .large)
let image = UIImage(systemName: "house", withConfiguration: config)
Copy the code

How to make SF Symbol bold by adjusting its weight

All SF Symbols come in a variety of font weights, from ultra light to black, which means you can make them stand out with very little work. In SwiftUI, you can adjust the SF Symbol weight like this:

Image(systemName: "keyboard")
    .font(.largeTitle.weight(.black))
Copy the code

In UIKit, you adjust the weights by creating two instances of UIImage. UIImage. SymbolConfiguration then combine them together:

let largeTitle = UIImage.SymbolConfiguration(textStyle: .largeTitle)
let black = UIImage.SymbolConfiguration(weight: .black)
let combined = largeTitle.applying(black)
let image = UIImage(systemName: "keyboard", withConfiguration: combined)
Copy the code

How do I change the color of SF Symbol

Depending on the layout system you use, SF Symbol is rendered in default colors — SwiftUI uses default font colors and UIKit uses default colors. Either way, you can customize the color of the icon in a number of ways.

To use SwiftUI to complete the recolor of the SF Symbol, changing all of its parts to one color, decorate with a foreground foregroundColor() like this:

Image(systemName: "doc")
    .foregroundColor(.red)
Copy the code

In UIKit, you have two choices: either change the tone of the image view where you place the symbol:

let image = UIImage(systemName: "doc")
let imageView = UIImageView(image: image)
imageView.tintColor = .systemRed
Copy the code

Or, adjust the UIImage itself so that it recolor everywhere:

let image = UIImage(systemName: "doc")?.withTintColor(.systemRed, renderingMode: .alwaysOriginal)
let imageView = UIImageView(image: image)
Copy the code

How to render layered SF Symbol

In iOS15 and later, many SF Symbol ICONS contain several layers that represent the depth of the icon, and these layers can be rendered with a little transparency to help highlight the meaning of the icon. This works even when recolouring an image – because of transparency, you only change the shade of the color.

In SwiftUI, you can render layered SF Symbols like this:

Image(systemName: "square.stack.3d.down.right.fill")
    .symbolRenderingMode(.hierarchical)
    .foregroundColor(.indigo)
Copy the code

In UIKit, this is done by specifying the hierarchy color as part of the configuration, as shown below:

let config = UIImage.SymbolConfiguration(hierarchicalColor: .systemIndigo)
let image = UIImage(systemName: "square.stack.3d.down.right.fill", withConfiguration: config)
Copy the code

How to render multi-color SF Symbol

In iOS14 and later, many SF symbols have built-in colors with specific meanings, such as “externaldrive.badge.plus”. Badges. The external drive uses the default color, but the external badge is green. This multicolor drawing mode is not enabled by default, so your symbols will be rendered in the colors discussed above, but you can enable the default multicolor mode if you wish.

In SwiftUI, you can enable a multi-color SF Symbol like this:

Image(systemName: "externaldrive.badge.plus")
    .symbolRenderingMode(.multicolor)
Copy the code

In UIKit, this is done using configurationPreferringMulticolor, like this:

let config =  UIImage.SymbolConfiguration.configurationPreferringMulticolor()
let image = UIImage(systemName: "externaldrive.badge.plus", withConfiguration: config)
Copy the code

** Tip: ** Images without polychromatic variants will automatically render in monochrome, just as if you hadn’t changed the Settings.

How to create a custom SF Symbol palette

After iOS15, many SF symbols were split into segments that supported two or even three colors. How they render depends on how many fragments they contain and how many colors you provide:

  • If they have 1 paragraph, it will always use the first color you specified; Other colors will be ignored.

  • If they have 2 segments and you specify 1 color, this will be used for both segments. If you specify two colors, one will be used for each segment. If you specify three colors, the third is ignored.

  • If they have three segments and you specify a color, this will be used for all three segments. If you specify 2 colors, one color will be used for the first paragraph and the other for the remaining two paragraphs. If you specify three colors, one color is used for each segment.

In SwiftUI, you can render a palette image using the. Palette render mode, and then use a foreground style that contains one, two, or three colors:

Image(systemName: "person.3.sequence.fill")
    .symbolRenderingMode(.palette)
    .foregroundStyle(.red, .green, .blue)
Copy the code

You can actually use any shape, not just color, which means you can use three different materials:

Image(systemName: "person.3.sequence.fill")
    .symbolRenderingMode(.palette)
    .foregroundStyle(
        .ultraThickMaterial,
        .regularMaterial,
        .ultraThinMaterial
    )
Copy the code

Or even three linear gradients:

Image(systemName: "person.3.sequence.fill")
    .symbolRenderingMode(.palette)
    .foregroundStyle(
        .linearGradient(colors: [.red, .black], startPoint: .top, endPoint: .bottomTrailing),
        .linearGradient(colors: [.green, .black], startPoint: .top, endPoint: .bottomTrailing),
        .linearGradient(colors: [.blue, .black], startPoint: .top, endPoint: .bottomTrailing)
    )
    .font(.largeTitle)
Copy the code

In UIKit, this is done using another symbol configuration, this time passing the array of colors to the paletteColors initialization constructor:

let config = UIImage.SymbolConfiguration(paletteColors: [.systemRed, .systemGreen, .systemBlue])
let image = UIImage(systemName: "person.3.sequence.fill", withConfiguration: config)

Copy the code

UIKit cannot use materials or gradients in its palette, only colors.

How to adjust SF Symbol variants

In iOS15 and later, some SF symbols offer variations of one or more circles, fills, rectangles, slashes, or squares. In UIKit, you need to activate these symbols by name — such as “bell.slash” — but there is a symbolVariant () modifier in SwiftUI to make this easier.

For example, this renders a bell icon with a slash:

Image(systemName: "bell")
    .symbolVariant(.slash)
Copy the code

The clock has a square around it:

Image(systemName: "bell")
    .symbolVariant(.square)
Copy the code

If you want, these can be combined like this:

Image(systemName: "bell").SymbolVariant (.fill.slash) also has one that presents the original image.This is helpful if you need to move between two states of the icon.For example, this will switch between two statesstruct ContentView: View {
    @State private var showingAlerts = true
    var body: some View {
        Toggle(isOn: $showingAlerts) {
            Label("Show Alerts", systemImage: "bell")
                .symbolVariant(showingAlerts ? .none : .slash)
        }
        .toggleStyle(.button)

    }

}
Copy the code

How to describe the SF Symbol for voiceover

By default, many SF symbols have a useful Voiceover tag, for example “Heart” is pronounced “love” and “Calendar.Badge. Plus” is pronounced “Add to Calendar”. However, many other ICONS do not have such a built-in name. Including complex icon, such as “arrowshape. Turn. Up. Backward. Circle”. In this case, you should set a custom accessibility tag that describes the contents of The VoiceVER.

In SwiftUI, you can attach a custom accessibility label to a SF Symbol as follows:

Image(systemName: "arrowshape.turn.up.backward.circle")
    .accessibilityLabel("Go back")
Copy the code

If you are using a tag, Voiceover will use the tag’s text, even if it is not currently displayed.

** Tip: ** You can also put your accessibility label in your Localizable using the same name as the SF Symbol. String file, SwiftUI will use it.

In UIKit, the accessibility label is set on the control that displays the symbol, as follows:

let image = UIImage(systemName: "arrowshape.turn.up.backward.circle")
let imageView = UIImageView(image: image)
imageView.accessibilityLabel = "Go back"
Copy the code

How do SF symbols fit into their context

In iOS15 and beyond, many SF symbols are automatically adapted to their usage, including the way the “signature” Symbol changes to match various locales, such as Japanese or Hebrew.

However, SwiftUI does have one powerful feature that UIKit lacks, and that is the ability to render SF Symbols in context. In TabView, the correct variant of symbol depends on the system: The iOS And Apple HMI guides recommend filling ICONS, while in macOS they recommend using strokes.

SwiftUI does something smart here: If you’re using SF Symbol for a tag item, you shouldn’t specify whether it’s filled or not — it will automatically adapt according to the system.

So, this will create a TAB item that uses the filler person symbol on iOS, but uses the stroke person on macOS:

TabView {
    Text("Your View Here")
        .tabItem {
            Label("Home", systemImage: "person")
                .symbolVariant(.none)
        }
}
Copy the code

reference

www.hackingwithswift.com/articles/23…