Technical Support
🟢 Online now
Hello 👋

How can we help you today?
Contact on WhatsApp
B4X Store
jdashboardUI / Núcleo y utilidades / ResponsiveUtils
Núcleo y utilidades

ResponsiveUtils

Layouts responsive por porcentaje, tamaño de Forms, escala HiDPI y posicionamiento multi-monitor

Buscar en toda jdashboardUI
Fuente
jdashboardUI.b4xlib · Solo API pública
Idioma de la tienda: es

Núcleo y utilidades · jdashboardUI 24 · B4J / JavaFX

ResponsiveUtils es una clase de apoyo para crear interfaces que se adapten al tamaño de un B4XView, al tamaño de un Form y a la pantalla donde se encuentra el usuario.

En B4J añade además utilidades para:

  • calcular anchos y altos porcentuales;
  • centrar un Form;
  • dimensionar un Form como porcentaje de la pantalla;
  • obtener dimensiones, coordenadas y escala de la pantalla;
  • trabajar correctamente en configuraciones multi-monitor;
  • adaptar Views durante Base_Resize.

La clase no modifica automáticamente el layout. Proporciona cálculos y helpers para que el desarrollador los aplique donde corresponda.

Plataforma

El archivo fuente ResponsiveUtils.bas contiene ramas condicionales para B4J y B4A.

Sin embargo, el paquete analizado jdashboardUI 24 declara en su manifest.txt:

Supported Platforms=B4j

Por tanto, la documentación principal de esta versión corresponde a B4J. La API B4A existente en el fuente se documenta más adelante como referencia del código condicional.

Dependencias

ResponsiveUtils utiliza:

  • B4XView / jXUI;
  • JFX en B4J;
  • JavaObject para consultar la escala real de salida de JavaFX;
  • Screen y Form de B4J.

No necesita AdditionalJar propio.

Initialize

La clase se vincula a un View base:

Private Responsive As ResponsiveUtils

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Main")

    Responsive.Initialize(Root)
    MainForm.Show
End Sub

Firma:

Responsive.Initialize(v As B4XView)

El View recibido se guarda internamente como mBase.

Normalmente se usa el Root, un Pane principal o cualquier View cuyo tamaño quieras tomar como referencia.

GetPercentX

Calcula un porcentaje del ancho actual del View vinculado.

Dim W As Double = Responsive.GetPercentX(80)

Equivale a:

mBase.Width * (Percent / 100)

Ejemplos:

Dim HalfWidth As Double = Responsive.GetPercentX(50)
Dim CardWidth As Double = Responsive.GetPercentX(30)
Dim Margin As Double = Responsive.GetPercentX(3)

No existe clamp interno: valores mayores de 100 o negativos también se calculan matemáticamente.

GetPercentY

Calcula un porcentaje de la altura actual del View vinculado.

Dim HeaderHeight As Double = Responsive.GetPercentY(12)
Dim ContentHeight As Double = Responsive.GetPercentY(80)

Equivale a:

mBase.Height * (Percent / 100)

GetBaseView

Devuelve exactamente el View usado en Initialize.

Dim Base As B4XView = Responsive.GetBaseView
Log(Base.Width)
Log(Base.Height)

Es útil cuando una clase recibe ResponsiveUtils y necesita recuperar el recurso visual original.

Uso con Base_Resize

ResponsiveUtils no escucha automáticamente los cambios de tamaño. En B4J, un patrón práctico es recalcular el layout dentro de Base_Resize.

Private Responsive As ResponsiveUtils

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("Dashboard")

    Responsive.Initialize(Root)
End Sub

Private Sub B4XPage_Resize (Width As Int, Height As Int)
    Dim Margin As Double = Responsive.GetPercentX(2)
    Dim HeaderH As Double = Responsive.GetPercentY(12)

    pnlHeader.SetLayoutAnimated(0, _
        Margin, _
        Margin, _
        Responsive.GetPercentX(96), _
        HeaderH)

    pnlContent.SetLayoutAnimated(0, _
        Margin, _
        HeaderH + Margin * 2, _
        Responsive.GetPercentX(96), _
        Responsive.GetPercentY(82))
End Sub

Los porcentajes siempre se calculan usando el tamaño actual de mBase.

Layout de tarjetas proporcional

Ejemplo con tres tarjetas:

Private Sub B4XPage_Resize (Width As Int, Height As Int)
    Dim Gap As Double = Responsive.GetPercentX(2)
    Dim CardW As Double = Responsive.GetPercentX(30.66)
    Dim CardH As Double = Responsive.GetPercentY(22)

    Card1.SetLayoutAnimated(0, Gap, 20dip, CardW, CardH)
    Card2.SetLayoutAnimated(0, Gap * 2 + CardW, 20dip, CardW, CardH)
    Card3.SetLayoutAnimated(0, Gap * 3 + CardW * 2, 20dip, CardW, CardH)
End Sub

Este enfoque mantiene las proporciones cuando cambia el tamaño de la ventana.

Detección de pantalla activa

Los métodos de Form usan internamente GetScreenForForm, que es privado.

La selección de pantalla sigue este orden:

  1. intenta localizar la pantalla donde está actualmente el cursor del mouse;
  2. si no puede, intenta localizar la pantalla usando el centro horizontal del Form cuando tiene coordenadas y tamaño válidos;
  3. como fallback devuelve fx.PrimaryScreen.

Esto permite que CenterForm y SetFormSizeByPercentage funcionen en sistemas con varios monitores.

Si el mouse está sobre otra pantalla al llamar estos métodos, esa pantalla puede ser elegida como destino aunque el Form todavía esté en otro monitor.

CenterForm

Centra el Form en la pantalla seleccionada.

Responsive.CenterForm(MainForm)

La implementación usa:

WindowLeft = MinX + (ScreenWidth / 2 - Form.Width / 2)
WindowTop  = MinY + (ScreenHeight / 2 - Form.Height / 2)

Ejemplo:

MainForm.SetFormStyle("DECORATED")
MainForm.WindowWidth = 1100
MainForm.WindowHeight = 700

Responsive.CenterForm(MainForm)
MainForm.Show

GetScreenDimensions

Devuelve un Map con los datos de la pantalla seleccionada.

Dim Info As Map = Responsive.GetScreenDimensions(MainForm)

Log("Width: " & Info.Get("Width"))
Log("Height: " & Info.Get("Height"))
Log("Scale: " & Info.Get("Scale"))

Llaves devueltas:

Llave Tipo esperado Descripción
Width Double Ancho de la pantalla
Height Double Alto de la pantalla
MinX Double Coordenada X mínima
MinY Double Coordenada Y mínima
MaxX Double Coordenada X máxima
MaxY Double Coordenada Y máxima
Scale Double Escala de salida JavaFX

La escala se obtiene mediante:

Screen.getOutputScaleX()

Si esa llamada no está disponible o falla, Scale queda en 1.0.

Detectar HiDPI

Dim Info As Map = Responsive.GetScreenDimensions(MainForm)
Dim Scale As Double = Info.Get("Scale")

If Scale > 1 Then
    Log("HiDPI / scaling detected: " & Scale)
End If

La clase devuelve la escala; no reescala automáticamente las fuentes ni los Views.

SetFormSizeByPercentage

Ajusta el tamaño del Form usando porcentajes de la pantalla y después lo centra.

Responsive.SetFormSizeByPercentage(MainForm, 80, 70)

En este ejemplo:

  • ancho = 80% de la pantalla;
  • alto = 70% de la pantalla;
  • el Form queda centrado.

Ejemplo de inicio:

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Main")

    Responsive.Initialize(MainForm.RootPane)
    Responsive.SetFormSizeByPercentage(MainForm, 85, 82)

    MainForm.Show
End Sub

Los comentarios del fuente indican que WidthPercent y HeightPercent deben estar entre 0 y 100.

La implementación actual no aplica clamp, así que es responsabilidad del desarrollador respetar ese rango.

GetFormRelativeWidth

Devuelve un porcentaje del ancho actual del Form.

Dim SidebarW As Double = Responsive.GetFormRelativeWidth(MainForm, 20)
Dim ContentW As Double = Responsive.GetFormRelativeWidth(MainForm, 80)

Implementación:

f.Width * (Percent / 100)

GetFormRelativeHeight

Devuelve un porcentaje de la altura actual del Form.

Dim ToolbarH As Double = Responsive.GetFormRelativeHeight(MainForm, 8)

Implementación:

f.Height * (Percent / 100)

Ejemplo completo B4J

Este ejemplo combina tamaño inicial relativo a la pantalla y layout proporcional al Root.

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI

    Private Responsive As ResponsiveUtils

    Private pnlSidebar As B4XView
    Private pnlContent As B4XView
    Private pnlHeader As B4XView
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Main")

    Responsive.Initialize(MainForm.RootPane)

    '85% del ancho y 80% del alto de la pantalla activa.
    Responsive.SetFormSizeByPercentage(MainForm, 85, 80)

    MainForm.Show
End Sub

Private Sub MainForm_Resize (Width As Double, Height As Double)
    Dim Margin As Double = Responsive.GetPercentX(2)
    Dim HeaderH As Double = Responsive.GetPercentY(10)
    Dim SidebarW As Double = Responsive.GetPercentX(22)

    pnlHeader.SetLayoutAnimated(0, _
        Margin, _
        Margin, _
        Responsive.GetPercentX(96), _
        HeaderH)

    pnlSidebar.SetLayoutAnimated(0, _
        Margin, _
        HeaderH + Margin * 2, _
        SidebarW, _
        Responsive.GetPercentY(84))

    pnlContent.SetLayoutAnimated(0, _
        SidebarW + Margin * 2, _
        HeaderH + Margin * 2, _
        Responsive.GetPercentX(96) - SidebarW - Margin, _
        Responsive.GetPercentY(84))
End Sub

Multi-monitor

Para obtener información de la pantalla que ResponsiveUtils considera activa:

Dim ScreenInfo As Map = Responsive.GetScreenDimensions(MainForm)

Log("Monitor origin: " & _
    ScreenInfo.Get("MinX") & ", " & _
    ScreenInfo.Get("MinY"))

Log("Monitor size: " & _
    ScreenInfo.Get("Width") & " x " & _
    ScreenInfo.Get("Height"))

En monitores situados a la izquierda o encima del monitor principal, MinX o MinY pueden ser negativos. Esto es normal.

Rama B4A presente en el fuente

Aunque el paquete actual de jdashboardUI 24 está marcado como B4J, ResponsiveUtils.bas contiene código B4A condicional.

En B4A se encuentran:

GetScreenDimensions As Map
GetFormRelativeWidth(Percent As Double) As Double
GetFormRelativeHeight(Percent As Double) As Double

GetScreenDimensions — B4A

Usa GetDeviceLayoutValues y devuelve las mismas llaves:

Width
Height
MinX
MinY
MaxX
MaxY
Scale

GetFormRelativeWidth — B4A

100%x * (Percent / 100)

GetFormRelativeHeight — B4A

100%y * (Percent / 100)

Estos métodos se documentan porque existen en el fuente, pero no convierten el paquete actual en una librería B4A: el manifest de la versión analizada declara únicamente B4J.

API pública completa

API común

Método Retorno Descripción
Initialize(v As B4XView) - Vincula el View base
GetPercentX(Percent As Double) Double Porcentaje del ancho de mBase
GetPercentY(Percent As Double) Double Porcentaje del alto de mBase
GetBaseView B4XView Devuelve mBase

API B4J

Método Retorno Descripción
CenterForm(f As Form) - Centra el Form en la pantalla seleccionada
GetScreenDimensions(f As Form) Map Dimensiones, coordenadas y escala
SetFormSizeByPercentage(f, WidthPercent, HeightPercent) - Redimensiona y centra el Form
GetFormRelativeWidth(f, Percent) Double Porcentaje del ancho del Form
GetFormRelativeHeight(f, Percent) Double Porcentaje del alto del Form

API B4A existente en el fuente

Método Retorno Descripción
GetScreenDimensions Map Dimensiones y escala del dispositivo
GetFormRelativeWidth(Percent) Double Porcentaje de 100%x
GetFormRelativeHeight(Percent) Double Porcentaje de 100%y

Designer, eventos y AddToParent

ResponsiveUtils es una clase auxiliar:

  • no tiene Designer Properties;
  • no expone eventos;
  • no implementa AddToParent;
  • no crea Views;
  • no cambia automáticamente el layout;
  • requiere Initialize con un B4XView.

Buenas prácticas

  • Inicializa la clase con el contenedor que realmente representa el área responsive.
  • Usa GetPercentX y GetPercentY dentro de eventos Resize cuando quieras adaptación dinámica.
  • Usa SetFormSizeByPercentage para el tamaño inicial del Form, no en cada frame de resize.
  • Mantén WidthPercent y HeightPercent entre 0 y 100.
  • Recuerda que la detección B4J da prioridad a la pantalla donde está el cursor.
  • No asumas que MinX y MinY son siempre 0 en configuraciones multi-monitor.
  • Usa Scale como información; ResponsiveUtils no cambia fuentes ni escala de UI automáticamente.
  • Si necesitas considerar barra de tareas o dock, comprueba si las dimensiones completas de Screen son apropiadas para tu caso.