Instruction 2
AnyLayout works great. It handles the changes for you and arranges the views in the correct way. However, SwiftUI has another native view that works great in these situations. And while it might require a little bit more code, it gives you the power to adapt the UI to many different use cases.
Using ViewThatFits
ViewThatFits is a SwiftUI view that allows you to pass many different views, of different sizes, that can be used in different contexts, and it will take all those views and decide which one fits best with the available space.
It will evaluate the subviews in order of you provide them in the closure, so if you have a preferred view, you have to pass them first. Usually, you would pass the bigger view first and the smaller view last.
You can pass as many views as you need, and it will evaluate them, in order, to find the one that fits best.
ViewThatFits {
ReallyBigView()
RegularSizeView()
SmallView()
TinyView()
}
By default, ViewThatFits will check its child views in the horizontal and vertical axis. You can, however, tell it to evaluate in only one of them by passing the axis parameter in the initializer.
ViewThatFits(in: .vertical) {
LargeHorizontalView()
LargeVerticalView()
}
Passing .vertical tells ViewThatFits to evaluate the views only in the vertical axis. So, even if LargeHorizontalView is too large to fit in the width of the screen, ViewThatFits might choose it if it still fits in the height of the screen. The same thing happens with .horizontal, but instead of it evaluating the vertical axis, it will evaluate the horizontal axis.
Limitations
While AnyLayout seems simpler and with less code compared to ViewThatFits, it also requires you to write more code if you need to alternate over multiple different layouts. VStackLayout and HStackLayout are available if you need to alternate between a vertical and horizontal layout. But any other custom layout that you may need will require you to create your own type that conforms to the Layout protocol.
Also, unlike AnyLayout, you can’t tell ViewThatFits to use a specific layout depending on some conditional. It’ll evaluate the available views in order and choose the one that fits best. That’s why it’s important to provide the views in order of preference.
Using ViewThatFits for Accessibility
In the previous lesson, you learned about the importance of accessible UI and its importance to build apps that are inclusive. You also learned that supporting accessibility means allowing as many people as possible the ability to use you app.
You also learned how UI can break when some accessibility features are turned on, like large accessibility fonts.
SwiftUI has a lot of APIs that you can use to support this, like dynamicTypeSize. This is an environment value that allows you to read the user’s choice of dynamic type size.
Use this value to adapt the UI accordingly:
@Environment(\.dynamicTypeSize) var dynamicTypeSize
var body: some View {
switch dynamicTypeSize {
case .accessibility1,
.accessibility2,
.accessibility3,
.accessibility4,
.accessibility5:
AdaptedView()
case .medium,
.small,
.xSmall:
ViewWithMoreContent()
default:
ViewAdaptedForLargeFonts()
}
}
When the user opts of a larger accessibility font, you use a view that’s adapted to this context. You can also use different views if the device’s font size is large or medium.
You can also use ViewThatFits to do this work for you.
var body: some View {
ViewThatFits {
ViewWithMoreContent()
ViewAdaptedForLargeFonts()
AdaptedView()
}
}
Given the tools SwiftUI gives you, you have the power to build UI that works for everyone.
You’re going to use ViewThatFits to let SwiftUI choose which layout to apply when changing orientation.