CardButtonStyle
For tvOS-style buttons, use the new
CardButtonStyleraises when focused
directional effects when dragging on the Siri remote
Button(albumLabel, action: playAlbum)
.buttonStyle(CardButtonStyle())Context Menus
invoked on long press gesture
AlbumView()
.contextMenu {
Button("Add to Favorites", action: addAlbumToFavorites)
Button("View Artist", action: viewArtistPage)
Button("Discover Similar Albums", action: viewSimilarAlbums)
}Focus
primary way to interact with a TV app
incredibly important to be able to focus on views and determine if a view is focused
use the
focusable(_:onFocusChange:)modifier to make a view focusablenot meant for intrinsically focusable views (buttons, lists, ..)
use the modifier
onFocusChangeparameter to configure your statenew
isFocusedEnvironment variablelets you check whether or not a view is in focus, even if the view itself is not focusable
trueif the nearest focusable ancestor of your view is focused
Default focus
tvOS will geometrically compute the view that should be focused on load
this is typically the topmost or leading focusable view on the screen
use
prefersDefaultFocus(_:in:)to change the default behavioruse
focusScope(_:)to limit your focus preferences to a specific view instead of globally
@Namespace private var namespace
@State private var areCredentialsFilled: Bool
var body: some View {
VStack {
TextField("Username", text: $username)
.prefersDefaultFocus(!areCredentialsFilled, in: namespace)
SecureField("Password", text: $password)
Button("Log In", action: logIn)
.prefersDefaultFocus(areCredentialsFilled, in: namespace)
}
.focusScope(namespace)
}use
resetFocusenvironment action to reset the focus back to its default (limited to the current scope)
@Namespace var mainNamespace
@Environment(\.resetFocus) var resetFocus
var body: some View {
// ...
resetFocus(in: mainNamespace)
// ...
}