Simplifying User Interface Design
Designing a user interface can be challenging. Not only do you need to design a user interface that’s easy to use, but you also need to design an adaptive user interface that can respond to any changes the user might make to a window’s size. If the user shrinks a window, your user interface must shrink accordingly without cutting any items off. If the user enlarges a window, your user interface must expand accordingly to maintain a consistent appearance.
To help create adaptive user interfaces, Xcode provides constraints that fix the edges of various user interface items to a window’s edge or the edge of other user interface items. In this chapter, you’ll learn more about constraints and storyboards to help make user interface design easier than ever before.
If your user interface contains a handful of items such as a text field, a button, and a label, it’s fairly straightforward to place constraints on these items so they stay in the correct place. However, if your user interface contains multiple items, then it can get messy to place so many constraints on each item. Change one constraint and your entire user interface can fail to adapt properly, which often means wasting time trying to get your multiple constraints working. Figure 22-1 shows how messy multiple constraints can look on a crowded user interface.
Figure 22-1. Multiple constraints make it hard to correctly lay out a user interface
To solve this problem, Xcode offers a feature called Stack View. The idea behind stack view is that groups of user interface items often need to stay together. Rather than set constraints for each item individually, you group them together in a stack view, then set constraints for that single stack view.
To see how to create and use a stack view, follow these steps:
Figure 22-2. Dragging is a fast way to select multiple items
By using a stack view, you can keep grouped items together and only use one set of constraints for the entire group rather than exhaustively place constraints on each item individually.
Ideally, constraints should keep items a specific distance from the edge of the window or the edge of another user interface item. However if you shrink or expand a window, it’s possible for constraints to create unexpected problems.
Let’s see how setting two constraints on a user interface item can create a problem:
Right now we have two constraints that keep the text field a fixed distance from the two window edges, but they do nothing to keep the text field from disappearing if the window shrinks too much. One way to fix this is to create a compression constraint.
A compression constraint keeps a user interface item from shrinking or expanding too much. To create a compression constraint, you hold down the Control key and drag the mouse within the boundaries of that user interface element.
Figure 22-3. Defining a compression constraint
Figure 22-4. A compression constraint appears underneath a user interface item
The compression constraint tells Xcode to keep the text field a fixed width, and the left and right constraints tell Xcode to keep the text field a fixed distance from the left and right edges of the window. To satisfy all of these constraints, the window can no longer be resized in width.
What if we want to keep the text field width no smaller than its current width, but allow the window to resize? One solution is to use constraint priorities.
Priorities define which constraints must be satisfied first. Each time you create a constraint, Xcode gives it a priority of 1000, which is the highest priority possible. If you give a constraint a lower priority, then that constraint will allow constraints with higher priorities to take precedence. Let’s see how changing priorities on constraints works:
Figure 22-5. Editing a constraint
Figure 22-6. Changing the priority of a constraint
Figure 22-7. A constraint with a lower priority appears as a dotted line
Changing constraint priorities may not always give you the result you want so you may need to change how the constraint works. Most constraints define a fixed value that the constraint must satisfy. For more flexibility, you can also change this equal constraint to a greater than or equal or a less than or equal constraint.
Figure 22-8. Changing an equal sign to a greater than or equal to or less than or equal to sign
When your user interface doesn’t adapt correctly, try one or more of the following options:
Each user interface problem with adapting to window resizing can be different, so solving that problem could be as simple as modifying one constraint or as complicated as modifying multiple constraints. If groups of user interface items move together, group them in a stack view for simplicity.
Often times you may need to experiment with modifying different constraints to see how they work in various combinations. Just be aware of your options for modifying constraints, and you’ll eventually find the best solution for your particular user interface.
Working with Storyboard References
The two ways to design user interfaces involve .xib files and .storyboard files. Storyboard files represent scenes (windows) connected by segues. For a simple program that consists of a handful of windows, a storyboard may be fine, but if your program’s user interface consists of many windows, then a storyboard can get clumsy and cluttered with multiple segues linking scenes.
The more scenes your user interface needs, the more complicated your storyboard can be to understand as shown in Figure 22-9.
Figure 22-9. Large storyboards can look cluttered and hard to understand
To avoid storing your entire user interface in a single, cluttered storyboard, Xcode lets you divide a storyboard into parts using storyboard references. A storyboard reference lets you store scenes and segues in a separate storyboard file.
A storyboard reference replaces one or more scenes and segues with a storyboard reference box as shown in Figure 22-10. You can have multiple storyboard reference boxes where each one represents a separate storyboard file.
Figure 22-10. Storyboard references represent multiple scenes and segues stored in another storyboard file
You can create a storyboard reference in two ways:
To see how to use storyboard references, follow these steps:
Note If you fail to select the Use Storyboards check box, Xcode will store your user interface in a .xib file instead of a .storyboard file.
Figure 22-11. Control-dragging creates a segue between view controllers
Figure 22-12. Control-dragging creates a segue between view controllers
Summary
Every program’s user interface is crucial to letting users control a program. It doesn’t matter how powerful your program may be if the user interface frustrates users and discourages them from using the program.
Since every user interface needs to respond to changes the user might make to the size of a window, stack views let you group related items together and apply constraints on that entire stack view. Without grouping related items together, you would have to apply constraints to each item individually, which could get messy and be difficult to fix if they don’t respond the way you expect.
If you have constraint conflicts, you can modify priorities of each constraint and/or modify how a constraint works. When you create a constraint initially, Xcode makes the constraint equal to a fixed value. To provide flexibility, you can change this equal sign to a greater than or equal, or less than or equal sign.
To keep your user interface items visible, you can also apply compression constraints. Unlike ordinary constraints that link an item to another item or the edge of a window, a compression constraint defines the width and/or height of a user interface item. Compression constraints keep user interface items from disappearing if the user resizes a window.
For designing user interfaces that display windows or views in a specific order, you might find storyboard files easier to use than multiple .xib files. Rather than store your entire user interface in a single storyboard file (which can get cluttered and hard to understand), you can create storyboard references.
A storyboard reference divides a user interface into multiple storyboard files. By separating a user interface into multiple storyboard files, you can design and understand the structure of your user interface much easier.