He estado trabajando en un proyecto de chat H5 recientemente y me he encontrado con uno de los mayores obstáculos: el cuadro de entrada se enfoca, aparece el teclado en pantalla y es necesario adsorber (o empujar) el cuadro de entrada en el método de entrada. caja. Los requisitos son muy claros y parecen sencillos, pero en realidad no lo son. Después de experimentar con algunos modelos, encontramos que existen principalmente los siguientes problemas:
Exploremos las soluciones a los problemas mencionados anteriormente una por una.
Obtener el estado de ventana emergente y retracción del teclado virtualEs importante saber si el teclado virtual está arriba o abajo, y el procesamiento de compatibilidad posterior debe basarse en esto. Sin embargo, H5 no monitorea directamente los eventos nativos del teclado virtual. Solo puede monitorear indirectamente el rendimiento de otros aspectos de la página abriendo o retrayendo el teclado virtual, salvando el país. Además, el rendimiento en IOS y Android es diferente.
Rendimiento de la ventana emergente del teclado virtual de IOSEn iOS, cuando el cuadro de entrada (entrada, área de texto o texto enriquecido) recibe el foco, aparece el teclado, la página (vista web) no se comprime o la altura (altura) no cambia, pero la página (vista web) como un entero se desplaza hacia arriba y la altura máxima de desplazamiento (scrollTop) es la altura del teclado virtual.
Rendimiento de la ventana emergente del teclado virtual de AndroidDe manera similar, en Android, el cuadro de entrada recibe el foco y aparece el teclado, pero la altura de la página (vista web) cambiará. En términos generales, la altura es la altura del área visual (la altura original menos la altura del teclado virtual). ), excepto porque el contenido de la página se expande y puede producir desplazamiento, pero la vista web en sí no puede desplazarse.
Rendimiento del colapso del teclado virtual de IOSCuando se activa el botón de retracción en el teclado virtual o el área de página fuera del cuadro de entrada, el cuadro de entrada pierde el foco y el teclado virtual se retrae.
Rendimiento del colapso del teclado virtual de AndroidCuando se activa un área fuera del cuadro de entrada, el cuadro de entrada pierde el foco y el teclado virtual se retrae. Sin embargo, cuando se activa el botón de retracción del teclado, el cuadro de entrada no perderá el foco y el teclado virtual también se retraerá.
Supervise la ventana emergente y el colapso del teclado virtualCon base en las diferentes actuaciones anteriores de ventana emergente y colapso del teclado en IOS y Android, podemos realizar el siguiente procesamiento por separado para monitorear la ventana emergente y el colapso del teclado en pantalla:
// Juzga el tipo de dispositivo var JudgeDeviceType = function () { var ua = window.navigator.userAgent.toLocaleLowerCase(); var isIOS = /iphone|ipad|ipod/.test(ua var isAndroid = /android/.test); ( ua); return { isIOS: isIOS, isAndroid: isAndroid }}()// Escuche la ventana emergente del teclado en pantalla y la función de eventos de colapso del cuadro de entrada. listeningKeybord($input) { if (judgeDeviceType.isIOS) { // Aparece el teclado IOS: los cuadros de entrada de IOS y Android reciben el foco y aparece el teclado $input.addEventListener('focus', function () { console.log(' ¡Aparece el teclado IOS! '); // Operación después de que aparece el teclado IOS}, falso) // El teclado IOS se retrae: IOS Si hace clic fuera del cuadro de entrada o hace clic en el botón Retraer, el cuadro de entrada perderá el foco y el teclado se retraerá $input.addEventListener('blur', () => { console.log('¡Teclado IOS retraído!') ; // Operación después de plegar el teclado de IOS }) } // El teclado de Andriod está plegado: cuando el teclado de Andriod aparece o se pliega, la altura de la página cambiará y, en función de esto, el teclado se pliega if (judgeDeviceType.isAndroid) { var originHeight = document.documentElement.clientHeight || document.body.clientHeight; window.addEventListener('resize', function () { var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight; if (originHeight < resizeHeight) { console.log('¡El teclado de Android está guardado!'); // Operación después de guardar el teclado de Android} else { console.log('¡Aparece el teclado de Android! '); // Operación después de que aparece el teclado de Android} originHeight = resizeHeight; }, false) }}var $inputs = document.querySelectorAll('.input');for (var i = 0; i < $inputs.length; i++) { escuchaKeybord($entradas[i]);}Al abrir el teclado virtual, el cuadro de entrada siempre se desplaza al área visible.
A veces crearemos un formulario de entrada con muchos elementos de entrada. El cuadro de entrada recibe el foco y aparece el teclado virtual. Cuando el cuadro de entrada está ubicado en la parte inferior de la página, en IOS, toda la vista web se desplegará una cierta distancia para que el cuadro de entrada enfocado esté automáticamente en el área visible. Sin embargo, este no será el caso en Android. Solo cambiará la altura de la página, sin desplazarse al elemento actualmente enfocado en el área visible.
Dado que lo anterior se implementó para monitorear la ventana emergente y la retracción de los teclados de IOS y Android, aquí solo necesita desplazarse (scrollIntoView()) el elemento de enfoque al área visual después de que aparezca el teclado de Android. Para ver el efecto, puedes hacer clic aquí.
// Obtenga el elemento de enfoque y desplácese hasta el área visible function activeElementScrollIntoView(activeElement, delay) { var editable = activeElement.getAttribute('contenteditable') // El cuadro de entrada, el área de texto o el texto enriquecido no se desplaza al área visible después de obtener el área de enfoque if (activeElement.tagName == 'INPUT' || activeElement.tagName == 'TEXTAREA' || editable === '' || editable) { setTimeout(function () { activeElement.scrollIntoView(); }, delay) }}// ...// Operar activeElementScrollIntoView($input, 1000);// ... después de que aparezca el teclado de AndroidEvocar un teclado virtual numérico puro
El cuadro de entrada del formulario anterior requiere que ingrese un número de teléfono. De manera similar a esto, aparecerá un teclado numérico en pantalla. Ya que hablamos de compatibilidad con el teclado en pantalla, insertémoslo aquí. Una mejor solución es la siguiente:
<p>Ingrese su número de teléfono móvil</p><input type=tel novalidate=novalidate pattern=[0-9]* class=input>
Si utiliza la versión IOS12 y V6.7.4+ del navegador WeChat para abrir la demostración de entrada del formulario anterior, se sorprenderá al descubrir que después de retraer el teclado, la página que se desplazó originalmente hacia arriba no regresa a la posición inferior, lo que provoca el teclado original para rebotar. La posición inicial está vacía.
De hecho, este es un error de Apple en iOS y aparecerá en todos los dispositivos IOS12 empaquetados con Xcode10. WeChat ha dado oficialmente una solución. Simplemente desplace la página (vista web) hacia la posición inferior de la ventana (posición clientHeight) después de cerrar el teclado virtual. Puede hacer clic aquí para ver la demostración de entrada del formulario reparada arriba.
console.log('¡El teclado IOS está guardado!');// La versión 6.7.4+IOS12 del navegador WeChat mostrará que después de guardar el teclado, la vista se mueve hacia arriba pero no hacia abajo var wechatInfo = window.navigator.userAgent .match( /MicroMessenger//([/d/.]+)/i);if (!wechatInfo) return;var wechatVersion = wechatInfo[1];var versión = (navigator.appVersion).match(/OS (/d+)_(/d+)_?(/d+)?/);if (+wechatVersion.replace(//./g, '') >= 674 && +versión[1] >= 12) { ventana.scrollTo(0, Math.max(document.body.clientHeight, document.documentElement.clientHeight));}Compatible con métodos de entrada de terceros
Habiendo dicho todo lo anterior, de hecho, más de la mitad de los errores del cuadro de entrada del chat H5 se han solucionado. A continuación, echemos un vistazo a la estructura HTML básica del cuadro de entrada del chat.
<div class=chat__content> <div> <p>Algo de contenido de chat 1</p> </div> <!--Omitir miles de líneas de contenido de chat--></div><div class=input__content> <div clase = entrada contenteditable = true></div> <botón>Enviar</botón></div>
estilo
/* Omitir algunos estilos */.chat__content { height: calc(100% - 40px); margin-bottom: 40px; overflow-y: auto; overflow-x: oculto;}.input__content { display: flex height: 40px; posición: absoluta; izquierda: 0; derecha: 0; abajo: 0; align-items: center;}/* Omitir algunos estilos*/
Es muy simple, simplemente divida el área de contenido y el área de entrada. El área de entrada está absolutamente posicionada de acuerdo con el método de demostración de entrada del formulario anterior. Es cierto que la mayoría de los navegadores de Android están bien, pero la prueba fue en UC Browser. el método de entrada nativo y el método de entrada de terceros (como el método de entrada Sogou), el cuadro de entrada estará completamente bloqueado para el navegador QQ o el navegador WeChat; con un método de entrada de terceros, el cuadro de entrada estará medio bloqueado; con el navegador Baidu, con un método de entrada de terceros, el cuadro de entrada se bloqueará y quedará completamente cubierto. Para ver el efecto, puede visitar aquí en el navegador correspondiente.
En UC Browser, después de que aparece el teclado en pantalla, la altura de la barra de título sobre el navegador tiene un efecto dinámico de retardo al disminuir la altura, lo que hace que la vista web se desplace un poco hacia abajo y el cuadro de entrada inferior se desplace a la posición no deseada. zona visible.
En cuanto al método de entrada de terceros, se especula que la posición de desplazamiento inicial de la vista web es incorrecta debido a un cálculo de altura incorrecto después de que aparece el panel del método de entrada. De hecho, estos dos puntos se deben a que la vista web no se desplaza en su lugar. Después de que aparece el teclado en pantalla, el elemento de enfoque se puede desplazar nuevamente al área visible, lo que obliga a la vista web a desplazarse hacia su lugar.
console.log('¡Aparece el teclado de Android!');activeElementScrollIntoView($input, 1000);Solución de hackeo compatible con el navegador Xiaomi de Android
En el navegador Xiaomi de Android, después de aplicar la solución anterior, descubrí que el cuadro de entrada del chat todavía estaba firmemente bloqueado y scrollIntoView() aún permanecía inmóvil. Entonces, supongo que en realidad se debe a que el teclado virtual se ha desplazado hacia la parte inferior y la altura de la página es mayor que la altura del área visual cuando aparece el teclado virtual. De esta manera, la altura de la página solo se puede aumentar a la fuerza después del. Aparece un teclado en pantalla para que se pueda mostrar el cuadro de entrada. Según lo anterior, es compatible con métodos de entrada de terceros. Para ver el efecto, puede hacer clic aquí.
// El teclado de Andriod se retrae: la altura de la página cambiará cuando el teclado de Andriod aparezca o se retraiga. En base a esto, se conoce la retracción del teclado si (judgeDeviceType.isAndroid) { var originHeight = document.documentElement.clientHeight document. body.clientHeight; ventana.addEventListener('resize', function () { var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight; if (originHeight < resizeHeight) { console.log('¡El teclado de Android está cerrado!'); // Soluciona el problema de que el cuadro de entrada todavía está bloqueado por el método de entrada en el navegador Xiaomi if (judgeDeviceType.isMiuiBrowser). ) { document.body.style.marginBottom = '0px'; } } else { console.log('¡Aparece el teclado de Android!'); Solucione el problema de que el cuadro de entrada todavía está bloqueado por el método de entrada en el navegador Xiaomi if (judgeDeviceType.isMiuiBrowser) { document.body.style.marginBottom = '40px'; activeElementScrollIntoView($input, } originHeight = resizeHeight; }, FALSO )}Resumir
El final del H5 tiene un largo camino por delante con muchos escollos y requiere intentos constantes. Es un requisito previo comprender la diferencia de rendimiento entre la página emergente del teclado virtual en IOS y Android. El segundo paso es desplazar el elemento de enfoque al área visible. Al mismo tiempo, las diferencias en los métodos de entrada de terceros. Hay que tener en cuenta algunos navegadores.
Lo anterior es el contenido completo de este artículo. Espero que sea útil para el estudio de todos. También espero que todos apoyen VeVb Wulin Network.