Implementación de Indicadores de Carga Personalizados y Nativos en MUI

En el desarrollo de aplicaciones móviles híbridas, proporcionar retroalimentación visual durante las operaciones asíncronas es fundamental para la experiencia del usuario. El framework MUI permite extender sus funcionalidades para crear un componente de carga unificado. Este componente detecta automáticamente el entorno de ejecución: si se ejecuta en un entorno nativo (5+ App), utilizará la interfaz nativa del sistema; de lo contrario, generará un componente DOM personalizado con una capa de superposición.

A continuación, se presenta la extensión del módulo MUI para gestionar la visualización y ocultación de estos indicadores. La lógica ha sido refactorizada para mejorar la manipulación del DOM, optimizar la selección de elementos y gestionar correctamente los eventos táctiles, evitando el desplazamiento del fondo cuando el modal está activo.

(function(api, win) {
    const isNativeEnv = api.os.plus;

    api.showLoading = function(text = 'Cargando...', renderType = 'div') {
        // Utilizar UI nativa si el entorno lo permite y no se fuerza el modo DOM
        if (isNativeEnv && renderType !== 'div') {
            api.plusReady(function() {
                plus.nativeUI.showWaiting(text);
            });
            return;
        }

        const overlaySelector = '.app-loader-overlay';
        const modalSelector = '.app-loader-modal';

        // Gestión de la capa de superposición (Overlay)
        let overlay = document.querySelector(overlaySelector);
        if (!overlay) {
            overlay = document.createElement('div');
            overlay.className = 'app-loader-overlay';
            overlay.addEventListener('touchmove', blockTouchEvents, false);
            document.body.appendChild(overlay);
        }
        overlay.classList.remove('hidden-overlay');

        // Gestión del modal de carga
        let modal = document.querySelector(modalSelector);
        if (!modal) {
            modal = document.createElement('div');
            modal.className = 'app-loader-modal active-modal';
            modal.addEventListener('touchmove', blockTouchEvents, false);
            document.body.appendChild(modal);
        } else {
            modal.classList.add('active-modal');
        }

        // Inyectar contenido dinámico
        modal.innerHTML = `
            <i class="mui-spinner mui-spinner-white"></i>
            <p class="loader-text">${text}</p>
        `;
    };

    api.hideLoading = function(onComplete) {
        if (isNativeEnv) {
            api.plusReady(function() {
                plus.nativeUI.closeWaiting();
            });
        }

        const overlay = document.querySelector('.app-loader-overlay');
        const modal = document.querySelector('.app-loader-modal');

        if (overlay) {
            overlay.classList.add('hidden-overlay');
        }
        
        if (modal) {
            modal.classList.remove('active-modal');
            if (typeof onComplete === 'function') {
                onComplete();
            }
        }
    };

    // Función auxiliar para bloquear el scroll de fondo
    function blockTouchEvents(e) {
        e.stopPropagation();
        e.preventDefault();
    }
})(mui, window);

Para que el indicador personalizado en entorno web sea visualmente consistente, es necesario aplicar estilos CSS específicos. Estos estilos controlan el posicionamiento fijo, la animación de escala, la transición de opacidad y la integración con el spinner nativo de MUI.

.app-loader-modal {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 130px;
    min-height: 130px;
    margin-left: -65px;
    margin-top: -65px;
    background-color: rgba(15, 15, 15, 0.75);
    border-radius: 8px;
    text-align: center;
    color: #ffffff;
    z-index: 9999;
    opacity: 0;
    visibility: hidden;
    transform: scale(0.85);
    transition: all 0.25s ease-in-out;
}

.app-loader-modal.active-modal {
    opacity: 1;
    visibility: visible;
    transform: scale(1);
}

.app-loader-modal .mui-spinner {
    margin: 25px auto 10px;
    width: 38px;
    height: 38px;
}

.app-loader-modal .loader-text {
    font-size: 14px;
    font-family: system-ui, -apple-system, sans-serif;
    margin: 0;
    padding: 0 10px;
    line-height: 1.5;
    color: #fff;
}

.app-loader-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 9998;
    background: transparent;
}

.hidden-overlay {
    display: none !important;
}

El uso de esta extensión es directo. Puedes invocar el indicador de carga especificando el mensaje y forzando el tipo de renderizaod si es necesario, así como definir una función de retorno al ocultarlo.

// Mostrar el indicador de carga (forzar renderizado DOM en entorno nativo)
mui.showLoading('Procesando datos...', 'div');

// Ocultar el indicador y ejecutar una función al terminar
mui.hideLoading(function() {
    console.log('El indicador de carga ha sido cerrado correctamente.');
});

Etiquetas: mui mobile-ui JavaScript css hybrid-apps

Publicado el 6-13 05:45