Una de las mejores formas de aplicar un tema en tus apps de iOS es coloreando la Barra de Navegación (NavigationBar) de la pantalla (Screen); y si bien es posible hacerlo ahora mismo mediante el uso de un ContainerControl o un Rectangle, en combinación con los Constraint adecuados… existe una mejor forma de lograrlo mediante el uso de los Declare. Continúa leyendo y te mostraré como.
Los Declares son la vía proporcionada por el lenguaje de programación Xojo para acceder a las funciones en las librerías o Frameworks ya compilados, ya sean los proporcionados por el sistema operativo propiamente dicho o bien los procedentes de terceros. En este caso utilizaremos varias de las funciones y sub-rutinas facilitadas por el propio Framework de iOS para definir el color utilizado por la NavigationBar de una instancia MobileScreen.
Comenzaremos añadiendo un nuevo Módulo llamado, por ejemplo, “DeclaresForiOS” a un proyecto de iOS nuevo… o bien a un proyecto de iOS ya existente.
A continuación, añade un nuevo método a dicho módulo utilizando los siguientes valores:
- Method Name: NavigationBarColor
- Parameters: Extends Screen As MobileScreen, Assigns Value As ColorGroup
- Scope: Global
Y pega el siguiente fragmento de código en el Editor de Código asociado con el nuevo método:
// Obtenemos el ViewController correspondiente a la pantalla recibida var controller as ptr = Screen.ViewControllerHandle // https://developer.apple.com/documentation/uikit/uiviewcontroller/navigationcontroller?language=objc Declare Function navigationController Lib "UIKit" Selector "navigationController" (controller as ptr) as ptr // https://developer.apple.com/documentation/uikit/uinavigationcontroller/navigationbar?language=objc Declare Function navigationBar Lib "UIKit" Selector "navigationBar" (controller as ptr) as ptr // Obtenemos el objeto NavigationBarController asociado con el ViewController var nc as ptr = navigationController(controller) // …y el objeto NavigationBar propiamente dicho del NavigationBarController var nv as ptr = navigationBar(nc) Var colPtr As ptr If value<>Nil Then colptr = ColorGroupToUIColor(value) End If // https://developer.apple.com/documentation/uikit/uinavigationbar/standardappearance?language=objc Declare Function standardAppearance Lib "UIKit" Selector "standardAppearance" (obj As ptr) As ptr Declare Sub setStandardAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj as ptr, value as ptr) // https://developer.apple.com/documentation/uikit/uinavigationbar/scrolledgeappearance?language=objc Declare Sub setScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj as ptr, value as ptr) // https://developer.apple.com/documentation/uikit/uibarappearance/backgroundcolor?language=objc Declare Sub setBackgroundColor Lib "UIKit" Selector "setBackgroundColor:" (obj as ptr, value as ptr) // Obtenemos el objeto StandardAppearance del NavigationBar var appear as ptr = standardAppearance(nv) // Definimos la propiedad BackgrounColor en el objeto standardappearance… setBackgroundColor(appear, colptr) // …Y asignamos nuevamente el objeto standardappearance a la NavigationBar setStandardAppearance(nv, appear) // Si nuestra app está ejecutándose en una versión de iOS superior a la versión 15.0 // entonces hemos de asignar el mismo objeto de apariencia al atributo // scrolledgeappearance de la NavigationBar if (System.Version.MajorVersion >= 15.0) then setScrollEdgeAppearance(nv, appear) end if
Como puedes ver en el anterior fragmento de código, hacemos una llamada al método ColorGroupToUIColor para obtener un puntero a una instancia de UIColor a partir del ColorGroup recibido; de modo que hemos de añadir un método auxiliar a nuestro Módulo “DeclaresForiOS” utilizando los siguientes valores:
- Method Name: ColorGroupToUIColor
- Parameters: value As ColorGroup
Return Type: Ptr - Scope: Global
Y escribe (o pega) el siguiente fragmento de código:
Var colorptr As ptr Var c As Color Select Case value.Mode Case ColorGroup.modes.dual Var valueColors() As Color = value.values If Color.IsDarkMode And valueColors.LastIndex > 0 Then c = valueColors(1) Else c = valueColors(0) End If Case ColorGroup.modes.Single Var valueColors() As Color = value.values c = valueColors(0) End Select If colorptr = Nil Then // https://developer.apple.com/documentation/foundation/nsclassfromstring(_:)?language=objc Declare Function NSClassFromString Lib "Foundation" (name As CFStringRef) As Ptr // https://developer.apple.com/documentation/uikit/uicolor/1621930-colorwithred Declare Function rgba Lib "UIKit" selector "colorWithRed:green:blue:alpha:" (cls As ptr, r As Double, g As Double, b As Double, a As Double) As ptr colorptr = rgba(NSClassFromString("UIColor"), c.Red/255, c.Green/255, c.Blue/255, 1-(c.Alpha/255)) End If return colorptr
¡Hora de Colorear!
Y ese es todo el código que necesitamos. Selecciona ahora el ítem Screen1 en el Navegador de tu proyecto, y añádele la siguiente propiedad:
- Name: mNavigationBarColor
- Type: ColorGroup
- Scope: Protected
Con el ítem Scren1 aun seleccionado en el Navegador, añádele el evento Opening y escribe la siguiente línea de código:
mNavigationBarColor = new ColorGroup( color.red, color.Yellow)
Como último paso, añade el evento AppearanceChanged al ítem Screen1, y añádele la siguiente línea de código:
me.NavigationBarColor = mNavigationBarColor
Asegúrate de que esté seleccionada la propiedad “Has Navigation Bar” en el Panel Inspector asociado con Screen1… y ejecuta el proyecto. Verás que la barra de navegación asociada con Screen1 aparecerá de color Rojo, siempre y cuando el dispositivo o el Simulador esté funcionando en Modo Claro; o de color Amarillo si el dispositivo o Simulador está ajustado en Modo Oscuro. También verás la transición entre ambos colores del ColorGroup asignado a medida que cambies el dispositivo o el Simulador entre los modos Claro / Oscuro.
¡Feliz programación!