The SwiftUI cookbook for focus - WWDC23 - Videos - Apple Developer
<aside> ⚠️ El focus es el sistema con el que podemos configurar el comportamiento para el teclado en mac, la corona en el apple watch o el swipe en el Apple TV. Es como un cursor para la atención del usuario
</aside>
Los textField son focusable views por defecto, cuando pulsamos Tab se desplaza al siguiente elemento
Los botones funcionan diferente, a no ser que esté activo el sistema de navegación por teclado en settings, sino ignoran el tab.
Se puede activar así en el panel de settings
struct RecipeGrid: View {
var body: some View {
LazyVGrid(columns: [GridItem(), GridItem()]) {
ForEach(0..<4) { _ in Capsule() }
}
.focusable(interactions: .edit)
}
}
struct RatingPicker: View {
var body: some View {
HStack { Capsule() ; Capsule() }
.focusable(interactions: .activate)
}
}
El focusable on activate recibirá el foco si el keyboard navigation está activado.Con el contentShape capsule podemos definir que su forma sea la de una cápsula para que el foco tome esa forma.
struct GroceryListView: View {
@FocusState private var isItemFocused
@State private var itemName = ""
var body: some View {
TextField("Item Name", text: $itemName)
.focused($isItemFocused)
Button("Done") { isItemFocused = false }
.disabled(!isItemFocused)
}
}
struct SelectedRecipeKey: FocusedValueKey {
typealias Value = Binding<Recipe>
}
extension FocusedValues {
var selectedRecipe: Binding<Recipe>? {
get { self[SelectedRecipeKey.self] }
set { self[SelectedRecipeKey.self] = newValue }
}
}
struct RecipeView: View {
@Binding var recipe: Recipe
var body: some View {
VStack {
Text(recipe.title)
}
.focusedSceneValue(\\.selectedRecipe, $recipe)
}
}
struct RecipeCommands: Commands {
@FocusedBinding(\\.selectedRecipe) private var selectedRecipe: Recipe?
var body: some Commands {
CommandMenu("Recipe") {
Button("Add to Grocery List") {
if let selectedRecipe {
addRecipe(selectedRecipe)
}
}
.disabled(selectedRecipe == nil)
}
}
private func addRecipe(_ recipe: Recipe) { /* ... */ }
}
struct Recipe: Hashable, Identifiable {
let id = UUID()
var title = ""
var isFavorite = false
}
Aquí un ejemplo del focused value en un LazyVGrid que nos permite gestionar con el teclado el
Este nuevo método nos permite capturar las teclas que se han pulsado con el foco encima
Los focus section permiten mover el foco hacia secciones enteras nuevas, similar a como funciona en apple tv.
struct ContentView: View {
@State private var favorites = Recipe.examples
@State private var selection = Recipe.examples.first!
var body: some View {
VStack {
HStack {
ForEach(favorites) { recipe in
Button(recipe.name) { selection = recipe }
}
}
Image(selection.imageName)
HStack {
Spacer()
Button("Add to Grocery List") { addIngredients(selection) }
Spacer()
}
.focusSection()
}
}
private func addIngredients(_ recipe: Recipe) { /* ... */ }
}
struct Recipe: Hashable, Identifiable {
static let examples: [Recipe] = [
Recipe(name: "Apple Pie"),
Recipe(name: "Baklava"),
Recipe(name: "Crème Brûlée")
]
let id = UUID()
var name = ""
var imageName = ""
}