Stack Views and the Focus Engine
In iOS 9 Apple introduced Stack Views, and these are also available in tvOS. The UIStackView class provides an interface for laying out collections of views in either a column or a row. A Stack View lets you utilize Auto Layout, creating user interfaces that can dynamically adapt to any changes in the available space within your views. In iOS 9 Stack Views automatically adjust for autorotation and screen size.
In this chapter we will expand our WeatherStation app to use Stack Views and also explore how the tvOS Focus Engine works.
Auto Layout and Stack Views
Stack View uses Auto Layout to position and size its views. The Stack View will pin the first and last arranged view flush with its edge along the stack’s axis. When working with a horizontal stack, this means the first arranged view’s leading edge is pinned to the stack’s leading edge, and the last arranged view’s trailing edge is pinned to the stack’s trailing edge. When working with vertical stacks, the top and bottom edges are pinned, respectively. You will see this in action in our example below.
You can then specify how you want the spacing to appear between the views in a stack, all without having to specify the constraints in a stack.
Implementing Stacks
Implementing stacks is pretty easy. The steps below will show how to embed five labels into a single stack.
Figure 3-1. Placing the City Name label in a Vertical Stack View
Figure 3-2. Placing the Temp labels in a horizontal Stack View
You will notice that Interface Builder is smart about choosing the correct Axis settings when selecting multiple controls.
Figure 3-3. Placing the Weather labels in a horizontal Stack View
You should see all five labels in three different Stack Views, as shown in Figure 3-4.
Figure 3-4. Three Stack Views have been created
Figure 3-5. One Vertical Stack View created from the three Stack Views
Note Xcode 7.1.1 Issue: When completing Step 11 above, the labels may not look as they do in Figure 3-5 and Figure 3-6. Simply select another file and then select the Main.storyboard file. This will cause Xcode to reset the view correctly.
Ensure the Stack View is a Vertical Axis Stack View. This makes all the views in the Stack View alignment based vertically to one another.
It appears that all the labels are crunched together. Let’s improve the spacing in the one Stack View.
Figure 3-6. Increasing the Vertical Spacing of the Stack Views
Figure 3-7. Increasing the Horizontal Spacing of the Stack Views
Now that you have the one parent Stack View, you can unset the “Extend Edges Under Top Bars” and Add Missing Constraints in 2 steps. This will enable the First View to shift automatically scroll up and down when the Tab Bar is visible.
Figure 3-8. Uncheck Extend Edges – Under Top Bars
Now we can apply the “Add Missing Constraints” tool to our View Controller and all our controls will be positioned, as we want in our view.
Figure 3-9. Adding Missing Constraints to our First Scene
Congratulations! You did it. Run the app now so you can see how the two constraints for the Stack View place all five labels where you want them. More importantly, if you add other controls to the view, you only need to update the constraints for the parent stack, not all five labels (see Figure 3-10).
Figure 3-10. The Weather App with Stack Views
With tvOS there are no tap or touch gestures, instead Apple provides the Focus Engine.
According to Apple, “the process within the UIKit that controls focus and focus movement is called the focus engine. The user controls focus through the remote and game controllers. The focus engine listens for incoming focus-movement events from all these input devices. When an event comes in, it automatically determines where focus should update and notifies the app. This system helps to create a consistent user experience across apps, provides automatic support for all current and future input methods in every app, and helps developers concentrate on implementing their app’s unique behavior rather than defining or reinventing basic navigation. Only the focus engine can update focus. There is no API for directly setting the focused view or moving focus in a certain direction. The focus engine only updates focus if the user sends a movement event, if the system requests an update, or if the application requests an update.”
The great thing about the focus engine is that it looks at the interface layout and handles all the work when moving the focus from one item to another.
There are many new functions and properties available to control the way focus is handled within tvOS apps. Many of these are defined by the UIFocusEnvironment protocol, which the UIViewController, UIView, UIWindow, and UIPresentationController classes automatically conform to. There are also several methods contained in the UITableViewDelegate and UICollectionViewDelegate protocols that can be used to control the focus within your app.
A Focus Engine Example
Let’s say you wanted to skip focus for one of the cities in our weather app as the user scrolls through the city list with their remote. You could add some code to do this. Let’s add the code to skip the focus of the second city in the Table View, Dallas. Add the code as shown in Listing 3-1 starting at line 58 in the FirstViewController.swift.
Here you implemented the UItableView(_:canFocusRowAtIndexPath:) method to return false when the indexPath.row is equal to 1. Otherwise you would return true. The UItableView(_:canFocusRowAtIndexPath:) delegate method determines whether specific rows can be can obtain focus.
When you run the app now, you’ll notice that when you try to navigate the rows in the Table View, the Dallas row is skipped because you implemented the UItableView(_:canFocusRowAtIndexPath:) method.
Summary
In this chapter you learned how Stack Views and the focus engine work. Stack Views are available in iOS and tvOS, but the focus engine is only available in tvOS. The Focus Engine is available only for tvOS because we can’t tap on our TVs.
Stack Views can save lots of time during the development lifecycle of an app. Understanding the focus engine will enable you to add to the user’s interface experience as you create your tvOS applications.
In the next few chapters, we will be exploring some of the more common Apple TV user interface elements while building a Photo Gallery application.
Exercises