Tenho trabalhado em um projeto de bate-papo H5 recentemente e encontrei uma das maiores armadilhas: a caixa de entrada fica em foco, o teclado virtual aparece e a caixa de entrada precisa ser adsorvida (ou coberta) no método de entrada caixa. Os requisitos são muito claros e parecem simples, mas na verdade não são. Depois de experimentar alguns modelos, descobrimos que existem principalmente os seguintes problemas:
Vamos explorar as soluções para os problemas mencionados acima, uma por uma.
Obtenha o status de pop-up e retração do teclado virtualÉ importante saber se o teclado virtual está ativo ou inativo, e o processamento de compatibilidade subsequente deve ser baseado nisso. No entanto, o H5 não monitora diretamente os eventos nativos do teclado virtual. Ele só pode monitorar indiretamente o desempenho de outros aspectos da página abrindo ou retraindo o teclado virtual, salvando o país. Além disso, o desempenho no IOS e no Android é diferente.
Desempenho pop-up do teclado virtual do IOSNo iOS, quando a caixa de entrada (input, textarea ou rich text) recebe o foco, o teclado aparece, a página (webview) não é compactada ou a altura (height) não muda, mas a página (webview) como um todo rola para cima e a altura máxima de rolagem (scrollTop) é a altura do teclado virtual.
Desempenho do pop-up do teclado virtual do AndroidDa mesma forma, no Android, a caixa de entrada fica em foco e o teclado aparece, mas a altura da página (visualização na web) muda. De modo geral, a altura é a altura da área visual (altura original menos a altura do teclado virtual). ), exceto porque o conteúdo da página está em expansão, pode produzir rolagem, mas a visualização da web em si não pode rolar.
Desempenho de colapso do teclado virtual IOSQuando o botão de retração no teclado virtual ou na área da página fora da caixa de entrada é acionado, a caixa de entrada perde o foco e o teclado virtual é retraído.
Desempenho de colapso do teclado virtual do AndroidQuando uma área fora da caixa de entrada é acionada, a caixa de entrada perde o foco e o teclado virtual é retraído. No entanto, quando o botão de retração do teclado é acionado, a caixa de entrada não perderá o foco e o teclado virtual também será retraído.
Monitore o pop-up e o colapso do teclado virtualCom base nos diferentes desempenhos acima de pop-up e recolhimento do teclado no IOS e Android, podemos realizar o seguinte processamento separadamente para monitorar o pop-up e recolhimento do teclado virtual:
// Julgue o tipo de dispositivo var juizDeviceType = function () { var ua = window.navigator.userAgent.toLocaleLowerCase(); ( ua); return { isIOS: isIOS, isAndroid: isAndroid }}() // Ouça o pop-up do teclado virtual e a função de eventos de recolhimento da caixa de entrada listenKeybord($input) { if (judgeDeviceType.isIOS) { // O teclado IOS aparece: as caixas de entrada IOS e Android ganham foco e o teclado aparece $input.addEventListener('focus', function () { console.log(' Teclado IOS Aparece! '); // Operação após o teclado IOS aparecer}, false) // Teclado IOS retrai: IOS Se você clicar fora da caixa de entrada ou clicar no botão retrair, a caixa de entrada perderá o foco e o teclado será retraído $input.addEventListener('blur', () => { console.log('IOS keyboard retracted!') ; // Operação após o teclado IOS ser dobrado }) } // O teclado Andriod é dobrado: Quando o teclado Andriod aparece ou dobra, a altura da página muda e, com base nisso, o teclado é dobrado 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('O teclado Android foi guardado!'); // Operação após o teclado Android ser guardado} else { console.log('Teclado Android aparece! '); // Operação após o teclado Android aparecer} originHeight = resizeHeight }, false) }}var $inputs = document.querySelectorAll('.input');for (var i = 0; i < $inputs.length; i++) { ouvirKeybord($inputs[i]);}Ao abrir o teclado virtual, a caixa de entrada sempre rola para a área visível.
Às vezes faremos um formulário de entrada com muitos itens de entrada. A caixa de entrada ganha o foco e o teclado virtual aparece. Quando a caixa de entrada está localizada na parte inferior da página, no IOS, todo o webview será enrolado a uma certa distância para que a caixa de entrada em foco fique automaticamente na área visível. Porém, este não será o caso no Android. . Isso apenas alterará a altura da página, sem rolar para o elemento atualmente em foco na área visível.
Como o acima foi implementado para monitorar o pop-up e retração dos teclados IOS e Android, aqui você só precisa rolar (scrollIntoView()) o elemento de foco para a área visual depois que o teclado Android aparecer. Para ver o efeito, você pode clicar aqui.
// Obtenha o elemento de foco e role até a área visível function activeElementScrollIntoView(activeElement, delay) { var editable = activeElement.getAttribute('contenteditable') // A caixa de entrada, textarea ou rich text não rola para a área visível após obter a área de foco if (activeElement.tagName == 'INPUT' || activeElement.tagName == 'TEXTAREA' || editable === '' || editable) { setTimeout(function () { activeElement.scrollIntoView(); }, delay) }}// ...// Operate activeElementScrollIntoView($input, 1000);// ... depois que o teclado Android aparecerEvoque um teclado virtual numérico puro
A caixa de entrada do formulário acima exige que você insira um número de telefone, um teclado virtual numérico aparecerá. Como falamos sobre compatibilidade de teclado virtual, vamos inseri-lo aqui. Uma solução melhor é a seguinte:
<p>Insira o número do seu celular</p><input type=tel novalidate=novalidate pattern=[0-9]* class=input>
Se você usar a versão IOS12 e V6.7.4+ do navegador WeChat para abrir a demonstração de entrada do formulário acima, ficará surpreso ao descobrir que depois que o teclado é retraído, a página que foi originalmente rolada para cima não retorna à posição inferior, causando o teclado original para saltar. A posição inicial está vazia.
Na verdade, este é um bug da Apple no iOS e aparecerá em todos os dispositivos IOS12 empacotados com Xcode10. O WeChat deu oficialmente uma solução. Basta rolar a página (webview) de volta para a posição inferior da janela (posição clientHeight) depois que o teclado virtual for fechado. A demonstração de entrada do formulário reparada acima pode ser clicada aqui
console.log('IOS keyboard is guarded!'); // O navegador WeChat versão 6.7.4+IOS12 mostrará que depois que o teclado for guardado, a visualização será empurrada para cima, mas não para baixo var wechatInfo = window.navigator.userAgent .match( /MicroMessenger//([/d/.]+)/i);if (!wechatInfo) return;var wechatVersion = wechatInfo[1];var versão = (navigator.appVersion).match(/OS (/d+)_(/d+)_?(/d+)?/);if (+wechatVersion.replace(//./g, '') >= 674 && +versão[1] >= 12) { window.scrollTo(0, Math.max(document.body.clientHeight, document.documentElement.clientHeight));}Compatível com métodos de entrada de terceiros
Tendo dito tudo acima, na verdade, mais da metade das armadilhas da caixa de entrada do chat H5 foram preenchidas. A seguir, vamos dar uma olhada na estrutura HTML básica da caixa de entrada do chat.
<div class=chat__content> <div> <p>Algum conteúdo de bate-papo 1</p> </div> <!--Omitir milhares de linhas de conteúdo de bate-papo--></div><div class=input__content> <div class =input contenteditable=true></div> <button>Enviar</button></div>
estilo
/* Omitir alguns estilos */.chat__content { height: calc(100% - 40px); margin-bottom: 40px; posição: absoluta esquerda: 0; direita: 0; inferior: 0; alinhar-itens: centro;}/* Omitir alguns estilos*/
É muito simples, basta dividir a área de conteúdo e a área de entrada. A área de entrada está absolutamente posicionada. De acordo com o método de demonstração de entrada do formulário acima, é verdade que a maioria dos navegadores Android estão bem, mas o teste foi no UC Browser. o método de entrada nativo e Para métodos de entrada de terceiros (como o método de entrada Sogou), a caixa de entrada será completamente bloqueada para o navegador QQ ou navegador WeChat, com um método de entrada de terceiros, a caixa de entrada será parcialmente bloqueada; com o navegador Baidu, com um método de entrada de terceiros, a caixa de entrada será bloqueada. Também será completamente coberta. Para visualizar o efeito, você pode visitar aqui no navegador correspondente.
No UC Browser, depois que o teclado virtual aparece, a altura da barra de título acima do navegador tem um efeito dinâmico de atraso de diminuição da altura, o que faz com que o webview role um pouco para baixo e a caixa de entrada inferior role para o não- área visível.
Quanto ao método de entrada de terceiros, especula-se que o posicionamento inicial de rolagem do webview está incorreto devido a um cálculo de altura incorreto após o painel do método de entrada aparecer. Na verdade, esses dois pontos são causados pelo fato de o webview não rolar no lugar. Depois que o teclado virtual aparece, o elemento de foco pode ser rolado para a área visível novamente, forçando o webview a se posicionar no lugar.
console.log('Teclado Android aparece!');activeElementScrollIntoView($input, 1000);Solução de hack compatível com navegador Android Xiaomi
No navegador Xiaomi do Android, depois de aplicar a solução acima, descobri que a caixa de entrada do bate-papo ainda estava totalmente bloqueada e scrollIntoView() ainda permanecia imóvel. Então, acho que é porque o teclado virtual foi rolado para baixo e a altura da página é maior que a altura da área visual quando o teclado virtual aparece. Dessa forma, a altura da página só pode ser aumentada à força depois. o teclado virtual aparece para que a caixa de entrada possa ser exibida. Com base no exposto, é compatível com métodos de entrada de terceiros. Para visualizar o efeito, você pode clicar aqui.
// Teclado Andriod retrai: A altura da página mudará quando o teclado Andriod aparecer ou retrair Com base nisso, a retração do teclado é conhecida 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('O teclado Android está fechado!'); // Corrige o problema de que a caixa de entrada ainda está bloqueada pelo método de entrada no navegador Xiaomi if (judgeDeviceType.isMiuiBrowser). ) { document.body.style.marginBottom = '0px'; } else { console.log('O teclado Android aparece!'); Corrija o problema de que a caixa de entrada ainda está bloqueada pelo método de entrada no navegador Xiaomi if (judgeDeviceType.isMiuiBrowser) { document.body.style.marginBottom = '40px' } activeElementScrollIntoView($input, 1000 } originHeight = resizeHeight; }, falso)}Resumir
O final do H5 tem um longo caminho pela frente e muitas armadilhas, então você precisa continuar tentando. Compreender a diferença de desempenho entre a página pop-up do teclado virtual no IOS e no Android é um pré-requisito. A segunda etapa é rolar o elemento de foco para a área visível. deve ser levado em conta.
O texto acima é todo o conteúdo deste artigo. Espero que seja útil para o estudo de todos. Também espero que todos apoiem a Rede VeVb Wulin.