Happy WWDC 2017! Today we're beginning our look at the incredibly large list of updates and improvements announced this week with UIFontMetrics. Let's jump in.
We'll start with the problem we're trying to solve. It's all about Dynamic Type.
Our users can adjust their preferred Dynamic Type value in Settings.app to display the text in our apps larger and more prominently.
This works great when we want to use the system default font, since we can simply write some code like this:
There's always one more fun trick tucked away in UIFontMetrics, and that is scaling arbitrary values. This is great for helping us size our UI elements (for example buttons or headers) to accomodate dynamically sized fonts that live inside:
Text is a huge part of iOS apps. Today we'll look at one way we can polish up the text in our apps, by allowing it to naturally "flow" around objects. Let's begin.
We'll start with a "before" picture. Here we've got a basic setup with some text and an image in the top right corner. Nothing too fancy here, just a regular UITextView and UIImageView:
letimageView=UIImageView(image:UIImage(named:"steve"))lettextView=UITextView(frame:.zero)textView.text="Here's to the crazy ones..."
This looks fine. But our text is needlessly narrow. It'd be great if we could make the textexpand to the full width of the device. We'll change our Text View's layout so it does:
Well, we're getting closer. Now we just need a way to make the text"flow" or "wrap" around our image. We'll start by getting the frame of the image view, then we'll create a path from it:
letimagePath=UIBezierPath(rect:imageView.frame)
Finally, we'll set our new path as one of the exclusionPaths of our Text View'stextContainer:
textView.textContainer.exclusionPaths=[imagePath]
Success! Since exclusionPaths is an Array, we can flow text around as many shapes as we want!
UITextField is one of the sort of "low key" hidden gems of UIKit. Today we'll look at some of the lesser-known things it can do and how to configure them. Let's dive in.
We'll begin by creating a text field and customizing its look and feel. First, instead of boring plain placeholder, let's spice things up a bit:
Nice, now let's customize how our text field works.
Suppose we wanted to clear out its contents when a user tapped it. We simply set clearsOnBeginEditing to true.
Similarly, if we wanted to clear the contents not when the user tapped the field, but rather when the user began typing content, we can set clearsOnInsertion to true.
Let's add some more "padding" to our text field. This turns out to be a tricker than expected.
UITextField allows for customization of the rects it uses to draw text via subclassing:
Let's draw some strings! There's plenty of text-drawing capabilities in iOS and OS X, with full frameworks like Text Kit (or the lower-level Core Text) dedicated to the task. Today, we'll start looking at these capabilities by using Core Graphics and UIKit to draw a multiline string.
Sometimes we need to draw text ourselves, “manually”. This can be helpful when optimizing for scrolling performance, or when complete customization is necessary.
First we'll need a view to draw into, we'll make a new UIView, and override drawRect.
Next, we'll start implementing our drawRectfunction with a few variables. We'll choose a font, then setup a paragraph style to make our text multiline, with some tall lines.
We'll also setup some drawing options to tell the system we want multiline text:
Dynamic Type is a system introduced back in iOS 7 with the intention of unifying and simplifying how users change their preference for how big text should be on the screen. While the user choice is simple, under the hood Dynamic Type earns its name by dynamically adjusting things such as spacing between characters and character weights to make text as readable as possible.
Let’s take a look at how to add simple Dynamic Type support.
Text Styles
The main way you interact with Dynamic Type is through the built-in set of text styles. As of iOS 9, 9 styles are available to choose from:
Lastly, you'll want to update your UI when the user changes their preferences in Settings.app. Observe this notification and trigger a re-layout when it occurs: