Tutoriales de SwiftUI y Swift para iOS Developers - PROGRAMACIONSWIFT.COM

Como cambiar el tamaño de ProgressView en SwiftUI

Si eres un iOS Developer que busca perfeccionar la interfaz de usuario de sus aplicaciones, seguramente te has encontrado con el desafío de adaptar los componentes nativos a los requisitos específicos de diseño. Uno de los elementos más utilizados para indicar que una tarea está en proceso es el ProgressView. Sin embargo, durante los primeros días de SwiftUI, modificar sus dimensiones no era tan intuitivo.

Hoy en día, cambiar el tamaño de ProgressView en SwiftUI es un proceso elegante y semántico gracias al modificador controlSize(). En este tutorial, exploraremos a fondo cómo utilizar esta herramienta en programación Swift para crear interfaces adaptables y consistentes en iOS, macOS y watchOS, todo desde Xcode.


¿Qué es ProgressView en SwiftUI?

Antes de profundizar en los tamaños, es fundamental entender qué representa este componente. En Swift, un ProgressView es una vista que muestra el progreso de una tarea. Puede presentarse de dos formas principales:

  1. Indeterminada (Spinner): Muestra una animación circular (comúnmente conocida como “activity indicator”) cuando no se sabe cuánto tiempo tomará una tarea.
  2. Determinada (Barra de progreso): Muestra una barra lineal que se llena de 0.0 a 1.0 (o cualquier otro rango) cuando el progreso de la tarea es calculable.

Independientemente del tipo de vista de progreso que utilices, mantener una jerarquía visual clara es vital. Un indicador demasiado pequeño puede pasar desapercibido, mientras que uno demasiado grande puede parecer tosco y arruinar el diseño.


El Problema: scaleEffect() vs frame()

Históricamente, los desarrolladores intentaban cambiar el tamaño de ProgressView en SwiftUI usando modificadores genéricos como .frame(width:height:) o .scaleEffect().

  • El problema con .frame(): Si aplicas un marco más grande a un ProgressView circular indeterminado, el contenedor crece, pero el spinner en sí mismo mantiene su tamaño nativo en el centro.
  • El problema con .scaleEffect(): Aunque hace que el componente se vea más grande o más pequeño mediante una transformación matricial, puede causar que los píxeles se vean borrosos, alterar los márgenes de los componentes adyacentes de forma impredecible y no respeta las guías de accesibilidad del sistema operativo.

Aquí es donde brilla el modificador semántico nativo.


La Solución Elegante: controlSize()

Introducido para unificar la forma en que dimensionamos los controles, controlSize() es un modificador que le indica a SwiftUI cuál debe ser el tamaño semántico de un control. En lugar de pasar píxeles exactos, le das al sistema una intención, y SwiftUI se encarga de renderizar el tamaño perfecto dependiendo de si estás en iOS, macOS o watchOS.

Tamaños Disponibles

El modificador acepta un valor del enumerador ControlSize. Aquí tienes los valores disponibles y su propósito general:

ValorDescripción
.miniEl tamaño más pequeño. Útil para listas densas o barras de herramientas muy saturadas (principalmente en macOS).
.smallPequeño, ideal para acompañar texto secundario o celdas compactas.
.regularEl tamaño por defecto. Es el estándar que ves si no aplicas ningún modificador.
.largeGrande. Perfecto para estados de carga a pantalla completa (Full Screen Loading).
.extraLargeEl tamaño máximo (disponible desde iOS 17/macOS 14). Útil para pantallas vacías, interfaces de watchOS o modales de carga principales.

Implementación Práctica en Xcode

A continuación, vamos a escribir algo de programación Swift real para ver cómo se comporta este modificador. Abre Xcode, crea un nuevo proyecto multiplataforma (o simplemente un proyecto de iOS) y copia el siguiente código.

1. ProgressView Indeterminado (Spinner)

El caso de uso más común es un spinner de carga que aparece mientras hacemos una petición a una API o cargamos datos de una base de datos.

import SwiftUI

struct IndeterminateProgressViewExample: View {
    var body: some View {
        VStack(spacing: 40) {
            Text("Tamaños de ProgressView Indeterminado")
                .font(.headline)
            
            HStack(spacing: 30) {
                VStack {
                    ProgressView()
                        .controlSize(.mini)
                    Text("Mini").font(.caption)
                }
                
                VStack {
                    ProgressView()
                        .controlSize(.small)
                    Text("Small").font(.caption)
                }
                
                VStack {
                    ProgressView()
                        .controlSize(.regular)
                    Text("Regular").font(.caption)
                }
                
                VStack {
                    ProgressView()
                        .controlSize(.large)
                    Text("Large").font(.caption)
                }
                
                if #available(iOS 17.0, macOS 14.0, watchOS 10.0, *) {
                    VStack {
                        ProgressView()
                            .controlSize(.extraLarge)
                        Text("Extra Large").font(.caption)
                    }
                }
            }
        }
        .padding()
    }
}

Al ejecutar esto en tu simulador de Xcode, notarás cómo el sistema renderiza spinners perfectamente nítidos y proporcionados para cada tamaño, sin sufrir la distorsión que causaría un .scaleEffect().

2. ProgressView Determinado (Barra de progreso)

¿Qué sucede cuando queremos cambiar el tamaño de ProgressView en SwiftUI para una barra de progreso? El modificador controlSize() también afecta el grosor (altura) de la barra, haciendo que se adapte visualmente a su entorno.

import SwiftUI

struct DeterminateProgressViewExample: View {
    @State private var progressAmount = 0.6
    
    var body: some View {
        VStack(spacing: 30) {
            Text("Tamaños de ProgressView Determinado")
                .font(.headline)
            
            VStack(alignment: .leading) {
                Text("Small")
                    .font(.caption)
                ProgressView(value: progressAmount)
                    .controlSize(.small)
            }
            
            VStack(alignment: .leading) {
                Text("Regular")
                    .font(.caption)
                ProgressView(value: progressAmount)
                    .controlSize(.regular)
            }
            
            VStack(alignment: .leading) {
                Text("Large")
                    .font(.caption)
                ProgressView(value: progressAmount)
                    .controlSize(.large)
                    .tint(.blue) // Puedes cambiar el color fácilmente
            }
        }
        .padding()
    }
}

En el caso de las barras de progreso, el .controlSize() cambia el grosor de la línea. Si combinas esto con un modificador .tint(), puedes integrar la barra perfectamente en el sistema de diseño (Design System) de tu aplicación.


Desarrollo Multiplataforma: iOS, macOS y watchOS

Una de las grandes ventajas de ser un iOS Developer en el ecosistema actual de Apple es que SwiftUI es inherentemente multiplataforma. Al utilizar un modificador semántico como controlSize(), estás delegando al sistema operativo la decisión de qué significa exactamente “grande” o “pequeño” en términos de píxeles.

Comportamiento en iOS

En el iPhone y el iPad, los tamaños responden muy bien a los paradigmas táctiles. Un .large es excelente para el centro de la pantalla cuando una vista está cargando por primera vez. Un .regular o .small es ideal para colocar dentro de un botón (por ejemplo, un botón de “Guardando…” donde el spinner reemplaza al icono temporalmente).

Comportamiento en macOS

Las aplicaciones de Mac tienen una densidad de información diferente. Los usuarios navegan con un cursor, por lo que los elementos pueden ser más pequeños. En macOS, el .mini y .small son vitales para barras de herramientas laterales (Sidebars) o para listas de elementos (por ejemplo, indicadores de sincronización en una aplicación de correo). SwiftUI ajustará automáticamente los milímetros en la pantalla de la Mac para que el indicador de progreso se vea como un control nativo de AppKit, no como una app de iOS estirada.

Comportamiento en watchOS

En el Apple Watch, el espacio es el recurso más valioso. Un ProgressView circular con un .large o .extraLarge puede llenar casi toda la pantalla y funcionar como el foco visual central de tu aplicación (por ejemplo, midiendo el progreso de un entrenamiento de fitness). Además, en watchOS, Swift optimiza la animación de los ProgressView para conservar la batería de la pantalla OLED.


Casos de Uso Avanzados y Mejores Prácticas

Saber escribir el código es solo una parte del trabajo de un iOS Developer. Saber cuándo utilizarlo es lo que separa a los juniors de los seniors. Aquí tienes algunas mejores prácticas para dominar el uso de ProgressView.

1. Botones con Estado de Carga

Un patrón de interfaz muy común es mostrar un spinner dentro de un botón cuando el usuario lo toca, indicando que la acción se está procesando. Para esto, .regular suele ser muy grande, rompiendo el diseño del botón. El tamaño .small es tu mejor aliado.

Button(action: {
    // Iniciar petición de red
}) {
    HStack {
        Text("Guardar Perfil")
        ProgressView()
            .progressViewStyle(CircularProgressViewStyle(tint: .white))
            .controlSize(.small)
    }
    .padding()
    .background(Color.blue)
    .foregroundColor(.white)
    .cornerRadius(8)
}

2. Modificadores Combinados

No olvides que controlSize() se lleva perfectamente con otros modificadores de vista de SwiftUI. Puedes aplicar sombras, opacidad, o envolver el spinner en un material translúcido para crear un HUD (Heads-Up Display) moderno.

ProgressView("Sincronizando datos...")
    .controlSize(.large)
    .padding(24)
    .background(.regularMaterial) // Efecto cristal translúcido
    .cornerRadius(16)
    .shadow(color: .black.opacity(0.1), radius: 10, x: 0, y: 5)

3. Consideraciones de Accesibilidad

Al usar programación Swift y SwiftUI, gran parte de la accesibilidad (VoiceOver, Dynamic Type) viene configurada de fábrica. Sin embargo, al cambiar el tamaño de ProgressView en SwiftUI, debes asegurarte de que si adjuntas una etiqueta (Label) al ProgressView, la fuente de esa etiqueta escale correctamente con las preferencias de texto del usuario. Usar controlSize() asegura que el icono en sí mantenga proporciones legibles sin importar la configuración de Dynamic Type del usuario.


Conclusión

La evolución de SwiftUI ha estado marcada por la introducción de APIs cada vez más declarativas y semánticas. En versiones anteriores, intentar ajustar el tamaño de un spinner o una barra de progreso podía resultar en “hacks” de diseño que requerían .scaleEffect y rompían la nitidez de la interfaz.

Hoy, gracias a controlSize(), cualquier iOS Developer puede crear interfaces coherentes, accesibles y visualmente atractivas con una sola línea de código en Xcode. Ya sea que estés programando para la pantalla compacta de un Apple Watch, adaptando una vista compleja en un iPad, o desarrollando una potente herramienta para macOS, confiar en las intenciones semánticas de Swift asegura que tus componentes nativos siempre se vean exactamente como Apple los diseñó.

Visited 1 times, 1 visit(s) today
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Article

¿Vale la pena aprender SwiftUI?

Related Posts