SwiftUI: componente TabView
Qué es Tab View
El componente TabView
es un contenedor de vistas que permite intercambiar la vista hija que se muestra en cada momento. Es un componente equivalente a UITabBarController
de UIKit
. A partir de iOS 14 también se puede comportar como un UIPageViewController
de UIKit
.
Aquí podéis consultar la documentación oficial
Para crear el componente solo necesitaremos embeber en su ViewBuilder
las vistas que podrá mostrar y el propio componente nos proporcionará una barra inferior para poder intercambiar la vista que se muestra en cada momento.
TabView { Text("First Screen") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.yellow.opacity(0.3)) .tabItem { Image(systemName: "1.circle.fill") Text("First") } Text("Second Screen") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.red.opacity(0.3)) .tabItem { Image(systemName: "2.circle.fill") Text("Second") } }
La barra inferior contendrá tantos botones como vistas embebidas contenga y permitirá mostrar un texto e icono por cada una de las opciones a través del modificador tabItem
.
Cómo seleccionar una página ‘programáticamente’
El ‘inicializador’ de TabView
tiene un parámetro selection
que permite indicar la vista del TabView
debe presentarse. Este parámetro hace referencia al tag
de la vista a presentar, por lo que todas las vistas que se incluyan en el TabView
deberán tener definido el tag
. El tag
es un modificador del protocolo View
y lo asignaremos de la siguiente forma:
Text("Hello, world!") .tag(0)
El valor de tag
es de tipo Hashable
, que implementa String
o Int
, entre otros.
Por ejemplo, vamos a definir un TabView
con dos botones que al pulsarlos se naveguen entre las dos pantallas, sin necesidad de pulsar las opciones del TabView
. Para ello, definiremos los tag
de cada uno de los botones, declararemos una variable de estado y la asociaremos a la propiedad selection
del TabView
. De esta forma al pulsar cada botón se cambiará la variable de estado selection
para indicar el tag
que se debe mostrar.
struct ContentView: View { @State private var selection: Int = 0 var body: some View { TabView(selection: $selection) { Group { Button("Go to Second Screen") { selection = 1 } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.yellow.opacity(0.3)) .tabItem { Image(systemName: "1.circle.fill") Text("First") } .tag(0) Button("Go to First Screen") { selection = 0 } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.red.opacity(0.3)) .tabItem { Image(systemName: "2.circle.fill") Text("Second") } .tag(1) } } } }
Modificadores comunes para Tabview
El componente TabView
comparte los mismos métodos de personalización que el componente View
y pueden ser consultados en el siguiente enlace.
accentColor
Permite modificar el color del botón que indica que pantalla está seleccionada.
TabView { Group { Text("First Screen") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.yellow.opacity(0.3)) .tabItem { Image(systemName: "1.circle.fill") Text("First") } Text("Second Screen") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.red.opacity(0.3)) .tabItem { Image(systemName: "2.circle.fill") Text("Second") } } } .accentColor(.orange)
tabItem
Permite indicar a las vistas hijas la imagen y el texto que deberá mostrarse cuando se incluya en un componente TabView
.
TabView { Group { Text("First Screen") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.yellow.opacity(0.3)) .tabItem { Image(systemName: "cart.fill") Text("First") } Text("Second Screen") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.red.opacity(0.3)) .tabItem { Image(systemName: "creditcard") Text("Second") } } }
El modificador recibe como parámetro un ViewBuilder
que permite añadir una Image
y un Text
.
Para el ejemplo se han usados las imágenes SF Symbols pre-cargadas en el sistema.
tabViewStyle
(iOS14)
Permite alternar el estilo de presentación de la vistas del componente TabView
. Por defecto la SDK trae dos implementaciones para iOS que implementan el protocolo TabViewStyle
:
DefaultTabViewStyle
. Se corresponde al modo de presentación correspondiente a unUITabBarController
deUIKit
.PageTabViewStyle
. Se corresponde al modo de presentación correspondiente a unUIPageViewController
deUIKit
.
struct TabViewStyle4View: View { var body: some View { TabView { Group { Text("First Screen") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.blue.opacity(0.3)) .tabItem { Image(systemName: "cart.fill") Text("First") } Text("Second Screen") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.red.opacity(0.3)) .tabItem { Image(systemName: "creditcard") Text("Second") } } } .tabViewStyle(PageTabViewStyle()) } }
Cómo cambiar el color de la barra del TabView
Actualmente no hay forma de modificar el color de la barra inferior del TabView
con SwiftUI
, lo cual es necesario en algunas ocasiones por temas de diseño.
Existe una forma con las apis de UIKit
, pero es un cambio global y afectaría a todos los componentes TabView
del proyecto. Sería usando la api de appearence
de la siguiente forma:
UITabBar.appearance().barTintColor = UIColor(red: 180/255, green: 207/255, blue: 227/255, alpha: 1)
Este código lo podemos invocar en el método init
de nuestra vista o en el método onAppear
(y podemos restablecerlo en el método onDisappear
para minimizar los fallos).
struct ContentView: View { private var lastBarTintColor: UIColor? = UITabBar.appearance().barTintColor var body: some View { TabView { Group { Text("First Screen") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.yellow.opacity(0.3)) .tabItem { Image(systemName: "1.circle.fill") Text("First") } Text("Second Screen") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .background(Color.red.opacity(0.3)) .tabItem { Image(systemName: "2.circle.fill") Text("Second") } } } .onAppear { UITabBar.appearance().barTintColor = UIColor(red: 180/255, green: 207/255, blue: 227/255, alpha: 1) } .onDisappear { UITabBar.appearance().barTintColor = lastBarTintColor } } }
IMPORTANTE: recordad que esto es un cambio global y puede provocar fallos en otros puntos de la aplicación si no se controla correctamente.
Ejemplo
Puedes encontrar este ejemplo en https://github.com/SDOSLabs/SwiftUI-Test bajo el apartado TabView.
Rafael Fernández,
iOS Tech Lider