2010-04-07 8 views
127

Estoy escribiendo una aplicación web para el iPad (no es una aplicación de la tienda de aplicaciones normal - está escrito usando HTML, CSS y JavaScript). Dado que el teclado ocupa una gran parte de la pantalla, tendría sentido cambiar el diseño de la aplicación para que se ajuste al espacio restante cuando se muestra el teclado. Sin embargo, no he encontrado manera de detectar cuándo o si se muestra el teclado.iPad Web App: Detecta el teclado virtual con JavaScript en Safari?

Mi primera idea fue suponer que el teclado está visible cuando un campo de texto tiene foco. Sin embargo, cuando se conecta un teclado externo a un iPad, el teclado virtual no aparece cuando un campo de texto recibe el foco.

En mis experimentos, el teclado también no afectó a la altura o scrollheight de cualquiera de los elementos DOM, y no he encontrado eventos de propiedad o propiedades que indican si el teclado es visible.

+1

Hm, un problema interesante. Intenta iterar sobre los objetos de "ventana" en Safari del iPad para ver si hay algún objeto especial relacionado con el soporte del teclado. –

+0

@David que no funcionará, el teclado no es una "ventana" de Javascript. – kennytm

+2

@KennyTM. Duh. Pero puede haber un indicador relacionado con la visualización del teclado en pantalla en cualquiera de los objetos de la ventana. Vale la pena intentarlo. –

Respuesta

50

he encontrado una solución que funciona, aunque es un poco feo. Tampoco funcionará en todas las situaciones, pero funciona para mí. Como estoy adaptando el tamaño de la interfaz de usuario al tamaño de la ventana del iPad, el usuario normalmente no puede desplazarse. En otras palabras, si configuro la ventana scrollTop, permanecerá en 0.

Si, por otro lado, se muestra el teclado, el desplazamiento funciona de repente. Así que puedo configurar scrollTop, probar su valor inmediatamente y luego reiniciarlo. Así es como debería parecerse en el código, usando jQuery:

$(document).ready(function(){ 
    $('input').bind('focus',function() { 
     $(window).scrollTop(10); 
     var keyboard_shown = $(window).scrollTop() > 0; 
     $(window).scrollTop(0); 

     $('#test').append(keyboard_shown?'keyboard ':'nokeyboard '); 
    }); 
}); 

Normalmente, se esperaría que esto no sea visible para el usuario. Desafortunadamente, al menos cuando se ejecuta en el simulador, el iPad se desplaza visiblemente (aunque rápidamente) hacia arriba y hacia abajo.Aún así, funciona, al menos en algunas situaciones específicas.

He probado esto en un iPad, y parece funcionar bien.

+0

tengo un problema con mi aplicación web, cuando la entrada se enfoca, la pantalla se desplaza un poco. De lo contrario, he desactivado el desplazamiento, pero aún así se desplaza. ¿Algunas ideas? Gracias [http://stackoverflow.com/questions/6740253/disable-scrolling-when-changing-focus-form-elements-ipad-web-app] –

+0

No he intentado esto todavía, pero parece prometedor. ¿No funcionaría '.scrollTop (1)' tan bien y sería menos obvio? – ThinkingStiff

+0

Sí, scrollTop (1) debería funcionar también; cualquier valor por encima de 0 debería funcionar. – LKM

0

no he intentado esto mismo, por lo que su sólo una idea ... pero ¿ha intentado usar preguntas de los medios con CSS para ver cuando la altura de la ventana cambia y luego cambiar el diseño para que? Me imagino que el móvil de Safari no reconoce el teclado como parte de la ventana, así que con suerte funcionaría.

Ejemplo:

@media all and (height: 200px){ 
    #content {height: 100px; overflow: hidden;} 
} 
+1

idea muy inteligente. Desafortunadamente, en mis pruebas, mostrar el teclado no afectó los valores de altura utilizados para evaluar las consultas de medios. – LKM

+0

Puedo confirmar: altura: 250px funcionó para mí (en Android, al menos). – WoodrowShigeru

13

Si hay un teclado en pantalla, enfocando un campo de texto que está cerca de la parte inferior de la ventana gráfica hará que Safari para desplazarse por el campo de texto a la vista. Puede haber alguna forma de explotar este fenómeno para detectar la presencia del teclado (tener un pequeño campo de texto en la parte inferior de la página que gana foco momentáneamente, o algo así).

+0

Esa es una idea ingeniosa. Encontré una solución similar que también usa la posición de desplazamiento actual para detectar el teclado virtual. – LKM

+0

¡genial! ¡Me salvaste el día! – aztack

-1

Bueno, puede detectar cuándo sus cuadros de entrada tienen el foco, y usted sabe la altura del teclado. También hay CSS disponible para obtener la orientación de la pantalla, así que creo que puedes hackearla.

Sin embargo, querrá manejar el caso de un teclado físico.

0

Realicé algunas búsquedas, y no pude encontrar nada concreto para un "teclado mostrado" o "en el teclado descartado". Ver the official list of supported events. También vea Technical Note TN2262 para iPad. Como probablemente ya sepa, existe un evento de cuerpo onorientationchange que puede cablear para detectar paisaje/retrato.

De forma similar, pero supongo ... ¿has intentado detectar el cambio de tamaño? Los cambios en la ventana gráfica pueden desencadenar ese evento indirectamente desde el teclado que se muestra/oculta.

window.addEventListener('resize', function() { alert(window.innerHeight); }); 

cual sería simplemente alertar a la nueva altura en cualquier caso de cambio de tamaño ....

+6

Desafortunadamente, en mis pruebas, el teclado no activó el evento de cambio de tamaño. – LKM

+1

+1 para enlaces a la documentación – BastiBen

15

tal vez un poco mejor solución es unir (con jQuery en mi caso) el evento "desenfoque" en los diversos campos de entrada.

Esto porque cuando el teclado desaparece, todos los campos del formulario se vuelven borrosos. Así que, para mi situación, este recorte solucionó el problema.

$('input, textarea').bind('blur', function(e) { 

     // Keyboard disappeared 
     window.scrollTo(0, 1); 

}); 

Espero que ayude. Michele

+0

Gracias por esta respuesta. Me pareció útil resolver un problema donde el teclado iPad Safari causó que el cursor de la tabla de texto se desplazara (desplazamiento) fuera del área de texto. – kennbrodhagen

7

Editar: documentada por Apple, aunque en realidad no podía conseguir que funcione: Behavior with Keyboard Displays WKWebView: "En el IOS 10, WKWebView objetos comportamiento nativo partido de Safari mediante la actualización de su propiedad window.innerHeight cuando se muestra el teclado, y no llame eventos de cambio de tamaño "(tal vez puede usar el enfoque o el enfoque más el retraso para detectar el teclado en lugar de usar el tamaño).

Edición: el código presume el teclado en pantalla, no el teclado externo. Dejarlo porque la información puede ser útil para otros que solo se preocupan por los teclados en pantalla. Use http://jsbin.com/AbimiQup/4 para ver los parámetros de la página.

nos prueba para ver si el document.activeElement es un elemento que muestra el teclado (input type = text, textarea, etc). Probado funciona en iOS5, Chrome Mobile (Beta mayo de 2012) y Android (ICS) y Opera (no funciona porque Opera mantiene el foco en el elemento después del teclado cerrado).

creo que falla en algunas circunstancias (IOS dan enfoque a la entrada, van a la pantalla de inicio, y luego volver a la página?) Pero funciona bastante bien para lo que hacemos.

El siguiente código modifica las cosas para nuestros propósitos (aunque generalmente no es correcto).

function getViewport() { // Note viewport sizing broken in Android 2.x see http://stackoverflow.com/questions/6601881/problem-with-meta-viewport-and-android 
    var viewport = { 
      left: window.pageXOffset, // http://www.quirksmode.org/mobile/tableViewport.html 
      top: window.pageYOffset, 
      width: window.innerWidth || documentElement.clientWidth, 
      height: window.innerHeight || documentElement.clientHeight 
    }; 
    if (isTouchDevice && isInput(getActiveElement())) {  // iOS *lies* about viewport size when keyboard is visible. See http://stackoverflow.com/questions/2593139/ipad-web-app-detect-virtual-keyboard-using-javascript-in-safari Input focus/blur can indicate, also scrollTop: 
     return { 
      left: viewport.left, 
      top: viewport.top, 
      width: viewport.width, 
      height: viewport.height * (viewport.height > viewport.width ? 0.66 : 0.45) // Fudge factor to allow for keyboard on iPad 
     }; 
    } 
    return viewport; 
} 


function isInput(el) { 
    var tagName = el && el.tagName && el.tagName.toLowerCase(); 
    return (tagName == 'input' && el.type != 'button' && el.type != 'radio' && el.type != 'checkbox') || (tagName == 'textarea'); 
}; 

function getActiveElement() { 
    try { 
     return document.activeElement; // can get exeption in IE8 
    } catch(e) { 
    } 
}; 

El código de arriba es solo aproximado: es incorrecto para teclado dividido, teclado desacoplado, teclado físico. Según el comentario en la parte superior, es posible que pueda hacer un mejor trabajo que el código dado en Safari (desde iOS8?) O WKWebView (desde iOS10) usando la propiedad window.innerHeight.

Sin embargo la respuesta etiquetado (cambiando scrollTop para medir la altura) tiene efectos secundarios desagradables si IU visor con zoom (o fuerza-zoom habilitado en las preferencias). No utilizo la otra solución sugerida (cambio de desplazamiento) porque en iOS, cuando la vista es ampliable y se desplaza a la entrada enfocada, hay interacciones erróneas entre desplazamiento & zoom & foco (que puede dejar una entrada solo enfocada fuera de la ventana gráfica - no visible).

5

Sólo probado en Android 4.1.1:

caso desenfoque no es un evento fiable para probar el teclado arriba y abajo porque el usuario como la opción de ocultar el teclado de manera explícita, que no desencadena un evento de falta de definición en el campo eso hizo que el teclado se mostrara.

resize event, sin embargo, funciona como un amuleto si el teclado sube o baja por algún motivo.

café:

$(window).bind "resize", (event) -> alert "resize" 

incendios en cualquier momento el teclado se muestran u ocultan por cualquier motivo.

Sin embargo, tenga en cuenta que en el caso de un navegador Android (en lugar de una aplicación) hay una barra de URL retráctil que no cambia de tamaño cuando se retrae pero cambia el tamaño de ventana disponible.

+0

+1 para evento de desenfoque que no se activa al desconectar manualmente el teclado. Cambiar el tamaño es una buena idea y funcionaría bien para dispositivos Android. –

+2

no funciona en iphone5, ios6.1.3 – aztack

+0

Se puede confirmar que esto funciona tanto en un iPhone 5 (iOS 6.0.2) como en un iPad 3 (iOS 6.0). –

1

Esta solución recuerda la posición de desplazamiento

var currentscroll = 0; 

    $('input').bind('focus',function() { 
     currentscroll = $(window).scrollTop(); 
    }); 

    $('input').bind('blur',function() { 
     if(currentscroll != $(window).scrollTop()){ 

     $(window).scrollTop(currentscroll); 

     } 
    }); 
11

Durante el evento de foco puede desplazarse más allá de la altura del documento y mágicamente la window.innerHeight se reduce la altura del teclado virtual. Tenga en cuenta que el tamaño del teclado virtual es diferente para las orientaciones de paisaje y retrato, por lo que deberá volver a detectarlo cuando cambie. Aconsejaría no recordar estos valores ya que el usuario podría conectar/desconectar un teclado bluetooth en cualquier momento.

var element = document.getElementById("element"); // the input field 
var focused = false; 

var virtualKeyboardHeight = function() { 
    var sx = document.body.scrollLeft, sy = document.body.scrollTop; 
    var naturalHeight = window.innerHeight; 
    window.scrollTo(sx, document.body.scrollHeight); 
    var keyboardHeight = naturalHeight - window.innerHeight; 
    window.scrollTo(sx, sy); 
    return keyboardHeight; 
}; 

element.onfocus = function() { 
    focused = true; 
    setTimeout(function() { 
     element.value = "keyboardHeight = " + virtualKeyboardHeight() 
    }, 1); // to allow for orientation scrolling 
}; 

window.onresize = function() { 
    if (focused) { 
     element.value = "keyboardHeight = " + virtualKeyboardHeight(); 
    } 
}; 

element.onblur = function() { 
    focused = false; 
}; 

Tenga en cuenta que cuando el usuario está utilizando un teclado Bluetooth, el keyboardHeight es 44, que es la altura de la barra de herramientas [anterior] [siguiente].

Hay un pequeño parpadeo cuando realiza esta detección, pero no parece posible evitarlo.

+4

Acabo de probar esto en iOS 8.2 y no funciona ... ¿dejó de funcionar en algún momento para iOS nuevo? – Ming

+1

No funcionó para mí tampoco - no se activa el cambio de tamaño en iOS9.3 – llamerr

25

Puede utilizar el evento focusout para detectar el despido del teclado. Es como borroso, pero burbujas. Se disparará cuando el teclado se cierre (pero también en otros casos, por supuesto). En Safari y Chrome, el evento solo se puede registrar con addEventListener, no con métodos heredados. Aquí hay un ejemplo que utilicé para restaurar una aplicación Phonegap después del despido del teclado.

document.addEventListener('focusout', function(e) {window.scrollTo(0, 0)}); 

Sin este fragmento, el contenedor de la aplicación permaneció en la posición desplazada hasta la actualización de la página.

+1

mejor solución que encontré para mi problema – Sutulustus

+1

Greaat me funciona, gracias hombre :) – kach

+0

Esto [a menudo no funciona en el Chrome 41/iOS Emulador de 6 en CrossBrowserTesting] (http://i.imgur.com/bZbz9Cm.png). –

0

El problema es que, incluso en 2014, los dispositivos manejan eventos de cambio de tamaño de pantalla, así como eventos de desplazamiento, de forma incoherente mientras el teclado virtual está abierto.

He descubierto que, incluso si usa un teclado bluetooth, iOS en particular desencadena algunos extraños errores de diseño; así que en lugar de detectar un teclado suave, solo tuve que apuntar a dispositivos que son muy estrechos y tienen pantallas táctiles.

Uso las consultas de medios (o window.matchMedia) para la detección de ancho y Modernizr para la detección de eventos táctiles.

1

prueba este:

var lastfoucsin; 

$('.txtclassname').click(function(e) 
{ 
    lastfoucsin=$(this); 

//the virtual keyboard appears automatically 

//Do your stuff; 

}); 


//to check ipad virtual keyboard appearance. 
//First check last focus class and close the virtual keyboard.In second click it closes the wrapper & lable 

$(".wrapperclass").click(function(e) 
{ 

if(lastfoucsin.hasClass('txtclassname')) 
{ 

lastfoucsin=$(this);//to avoid error 

return; 

} 

//Do your stuff 
$(this).css('display','none'); 
});`enter code here` 
3

En lugar de detectar el teclado, tratar de detectar el tamaño de la ventana

Si se redujo la altura de la ventana, y la anchura sigue siendo la misma, significa que el teclado está encendido. De lo contrario, el teclado está apagado, también puede agregar a eso, probar si algún campo de entrada está enfocado o no.

Pruebe este código por ejemplo.

var last_h = $(window).height(); // store the intial height. 
var last_w = $(window).width(); // store the intial width. 
var keyboard_is_on = false; 
$(window).resize(function() { 
    if ($("input").is(":focus")) { 
     keyboard_is_on = 
       ((last_w == $(window).width()) && (last_h > $(window).height())); 
    } 
});  
+0

Parece que ya no funciona en iOS 8. El teclado se superpone al contenido y, en muchos casos, el contenido se desplaza hacia abajo oscureciendo los campos de entrada inicialmente enfocados. –

+3

La altura de la ventana devuelve la altura, incluido el teclado, desde iOS 7, en la ventana IOS6. La altura cambia cuando se abre el teclado. – Michiel

+0

Tenga en cuenta que la altura también cambia cuando la barra de direcciones superior se desliza dentro y fuera de la pantalla cuando se desplaza. Debería agregar un cambio de altura mínima de, diría, 200px (no probado). – oriadam

0

Como se observa en las respuestas anteriores en algún lugar de la variable window.innerHeight se actualiza correctamente ahora en iOS10 cuando aparezca el teclado y ya no necesito el apoyo para las versiones anteriores que se le ocurrió este truco eso podría ser un poco más fácil que las "soluciones" discutidas.

//keep track of the "expected" height 
var windowExpectedSize = window.innerHeight; 

//update expected height on orientation change 
window.addEventListener('orientationchange', function(){ 
    //in case the virtual keyboard is open we close it first by removing focus from the input elements to get the proper "expected" size 
    if (window.innerHeight != windowExpectedSize){ 
     $("input").blur(); 
     $("div[contentEditable]").blur();  //you might need to add more editables here or you can focus something else and blur it to be sure 
     setTimeout(function(){ 
      windowExpectedSize = window.innerHeight; 
     },100); 
    }else{ 
     windowExpectedSize = window.innerHeight; 
    } 
}); 

//and update the "expected" height on screen resize - funny thing is that this is still not triggered on iOS when the keyboard appears 
window.addEventListener('resize', function(){ 
    $("input").blur(); //as before you can add more blurs here or focus-blur something 
    windowExpectedSize = window.innerHeight; 
}); 

continuación, puede utilizar:

if (window.innerHeight != windowExpectedSize){ ... } 

para comprobar si el teclado es visible. Lo he estado utilizando durante un tiempo en mi aplicación web y funciona bien, pero (como todas las demás soluciones) es posible que encuentre una situación en la que falla porque el tamaño "esperado" no se actualiza correctamente o algo así.

0

Quizás es más fácil tener una casilla de verificación en la configuración de su aplicación donde el usuario puede alternar '¿teclado externo conectado?'.

En letra pequeña, explique al usuario que los teclados externos actualmente no son detectables en los navegadores actuales.

Cuestiones relacionadas