ios5 - ultimo - iOS 5 de posicionamiento fijo y teclado virtual
noticias de apple (26)
En caso de que alguien quisiera probar esto. Obtuve lo siguiente para mí en un pie de página fijo con un campo de entrada.
<script>
$(''document'').ready(
function() {
if (navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)
|| navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/Windows Phone/i)) {
var windowHeight = $(window).height();
var documentHeight = $(document).height();
$(''#notes'').live(''focus'', function() {
if (documentHeight > windowHeight) {
$(''#controlsContainer'').css({
position : ''absolute''
});
$("html, body").animate({
scrollTop : $(document).height()
}, 1);
}
});
$(''#notes'').live(''blur'', function() {
$(''#controlsContainer'').css({
position : ''fixed''
});
$("html, body").animate({
scrollTop : 0
}, 1);
});
}
});
</script>
Tengo un sitio web móvil que tiene un div fijado en la parte inferior de la pantalla a través de la posición: fijo. Todo funciona bien en iOS 5 (estoy probando en un iPod Touch) hasta que estoy en una página con un formulario. Cuando toco en un campo de entrada y aparece el teclado virtual, de repente la posición fija de mi div se pierde. El div ahora se desplaza con la página siempre que el teclado esté visible. Una vez que haga clic en Listo para cerrar el teclado, el div volverá a su posición en la parte inferior de la pantalla y obedecerá la posición: regla fija.
¿Alguien más ha experimentado este tipo de comportamiento? Es esto esperado? Gracias.
En nuestro caso, esto se solucionaría tan pronto como el usuario se desplace. Esta es la solución que hemos estado utilizando para simular un desplazamiento en blur
en cualquier input
o área de textarea
:
$(document).on(''blur'', ''input, textarea'', function () {
setTimeout(function () {
window.scrollTo(document.body.scrollLeft, document.body.scrollTop);
}, 0);
});
Encontré esta solución en Github.
https://github.com/Simbul/baker/issues/504#issuecomment-12821392
Asegúrate de tener contenido desplegable.
// put in your .js file
$(window).load(function(){
window.scrollTo(0, 1);
});
// min-height set for scrollable content
<div id="wrap" style="min-height: 480px">
// website goes here
</div>
La barra de direcciones se pliega como una ventaja adicional.
Estaba teniendo el mismo problema con iOS7. Los elementos fijos inferiores arruinarían mi vista y no se enfocarían correctamente.
Todo comenzó a funcionar cuando agregué esta metaetiqueta a mi html.
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,height=device-height" >
La parte que marcó la diferencia fue:
height=device-height
Espero que ayude a alguien.
Este es el código que usamos para arreglar el problema con ipad. Básicamente detecta discrepancias entre la posición de desplazamiento y desplazamiento, lo que significa que "fijo" no funciona correctamente.
$(window).bind(''scroll'', function () {
var $nav = $(".navbar")
var scrollTop = $(window).scrollTop();
var offsetTop = $nav.offset().top;
if (Math.abs(scrollTop - offsetTop) > 1) {
$nav.css(''position'', ''absolute'');
setTimeout(function(){
$nav.css(''position'', ''fixed'');
}, 1);
}
});
Este es un problema difícil para estar "bien". Puede intentar ocultar el pie de página en el foco del elemento de entrada y mostrar el desenfoque, pero eso no siempre es confiable en iOS. De vez en cuando (una vez cada diez, por ejemplo, en mi iPhone 4S) el evento de enfoque parece no disparar (o tal vez hay una condición de carrera), y el pie de página no se oculta.
Después de mucho ensayo y error, se me ocurrió esta interesante solución:
<head>
...various JS and CSS imports...
<script type="text/javascript">
document.write( ''<style>#footer{visibility:hidden}@media(min-height:'' + ($( window ).height() - 10) + ''px){#footer{visibility:visible}}</style>'' );
</script>
</head>
Esencialmente: use JavaScript para determinar el alto de la ventana del dispositivo, luego cree dinámicamente una consulta de medios CSS para ocultar el pie de página cuando la altura de la ventana se reduce en 10 píxeles. Debido a que la apertura del teclado cambia el tamaño de la pantalla del navegador, esto nunca falla en iOS. Porque usa el motor de CSS en lugar de JavaScript, ¡es mucho más rápido y más suave también!
Nota: Encontré usando ''visibilidad: oculto'' menos errores que ''visualización: ninguno'' o ''posición: estática'', pero su kilometraje puede variar.
Este problema es realmente molesto.
Combiné algunas de las técnicas mencionadas anteriormente y se me ocurrió esto:
$(document).on(''focus'', ''input, textarea'', function() {
$(''.YOUR-FIXED-DIV'').css(''position'', ''static'');
});
$(document).on(''blur'', ''input, textarea'', function() {
setTimeout(function() {
$(''.YOUR-FIXED-DIV'').css(''position'', ''fixed'');
$(''body'').css(''height'', ''+=1'').css(''height'', ''-=1'');
}, 100);
});
Tengo dos barras de navegación fijas (encabezado y pie de página, usando Twitter bootstrap). Ambos actuaron de manera extraña cuando el teclado está activo y extraño de nuevo después de que el teclado está inactivo.
Con esta corrección temporizada / demorada, funciona. Todavía encuentro un error de vez en cuando, pero parece ser lo suficientemente bueno para mostrárselo al cliente.
Hazme saber si esto funciona para ti. Si no, podríamos encontrar algo más. Gracias.
Este sigue siendo un gran error para cualquier página HTML con Bootstrap Modals más alto en iOS 8.3. Ninguna de las soluciones propuestas anteriores funcionó y después de hacer zoom en cualquier campo debajo del pliegue de un alto modal, Mobile Safari y / o WkWebView moverían los elementos fijos al lugar donde estaba ubicado el desplazamiento del cuerpo HTML, dejándolos desalineados con el lugar donde estaban realmente Dispuesto.
Para solucionar el error, agregue un detector de eventos a cualquiera de sus entradas modales como:
$(select.modal).blur(function(){
$(''body'').scrollTop(0);
});
Supongo que esto funciona porque al forzar la altura de desplazamiento del cuerpo del HTML se vuelve a alinear la vista real con el lugar donde iOS 8 WebView espera que el contenido del div modal modal sea.
Funciona para mi
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
$(document).on(''focus'', ''input, textarea'', function() {
$(''header'').css({''position'':''static''});
});
$(document).on(''blur'', ''input, textarea'', function() {
$(''header'').css({''position'':''fixed''});
});
}
He arreglado la posición fija de mi contenido de diseño principal de Ipad de esta manera:
var mainHeight;
var main = $(''.main'');
// hack to detects the virtual keyboard close action and fix the layout bug of fixed elements not being re-flowed
function mainHeightChanged() {
$(''body'').scrollTop(0);
}
window.setInterval(function () {
if (mainHeight !== main.height())mainHeightChanged();
mainHeight = main.height();
}, 100);
Los elementos de posición fija simplemente no actualizan su posición cuando el teclado está arriba. Descubrí que al engañar a Safari para que pensara que la página había cambiado de tamaño, los elementos volverán a posicionarse. No es perfecto, pero al menos no tiene que preocuparse por cambiar a ''posición: absoluta'' y el seguimiento cambia usted mismo.
El siguiente código solo escucha cuando es probable que el usuario esté usando el teclado (debido a que se enfoca una entrada), y hasta que escucha un desenfoque, solo escucha los eventos de desplazamiento y luego realiza el truco de cambio de tamaño. Parece estar funcionando bastante bien para mí hasta ahora.
var needsScrollUpdate = false;
$(document).scroll(function(){
if(needsScrollUpdate) {
setTimeout(function() {
$("body").css("height", "+=1").css("height", "-=1");
}, 0);
}
});
$("input, textarea").live("focus", function(e) {
needsScrollUpdate = true;
});
$("input, textarea").live("blur", function(e) {
needsScrollUpdate = false;
});
Mi respuesta es que no se puede hacer.
Veo 25 respuestas pero ninguna funciona en mi caso. Es por eso que Yahoo y otras páginas ocultan el encabezado fijo cuando el teclado está encendido. Y Bing convierte toda la página en no desplazable (overflow-y: hidden).
Los casos discutidos anteriormente son diferentes, algunos tienen problemas al desplazarse, otros tienen foco o desenfoque. Algunos tienen pie de página fijo o encabezado. No puedo probar ahora cada combinación, pero podría terminar dándose cuenta de que no se puede hacer en su caso.
Ninguna de las otras respuestas que he encontrado para este error me ha funcionado. Pude solucionarlo simplemente desplazando la página hacia arriba 34px, la cantidad de safari móvil lo desplaza hacia abajo. con jquery:
$(''.search-form'').on(''focusin'', function(){
$(window).scrollTop($(window).scrollTop() + 34);
});
Esto obviamente tendrá efecto en todos los navegadores, pero evita que se rompa en iOS.
Ninguna de las soluciones de desplazamiento pareció funcionar para mí. En cambio, lo que funcionó fue establecer la posición del cuerpo para que se fijara mientras el usuario editaba el texto y luego restaurarlo a estático cuando el usuario terminaba. Esto evita que Safari desplace su contenido hacia usted. Puede hacer esto ya sea en el enfoque / desenfoque del elemento (s) (que se muestra a continuación para un solo elemento pero podría ser para todas las entradas, áreas de texto), o si un usuario está haciendo algo para comenzar a editar como abrir un modal, puede hacerlo sobre esa acción (p. ej. modal abierto / cerrado).
$("#myInput").on("focus", function () {
$("body").css("position", "fixed");
});
$("#myInput").on("blur", function () {
$("body").css("position", "static");
});
Probé todos los enfoques de este hilo, pero si no ayudaron, lo hicieron aún peor. Al final, decidí que el dispositivo de fuerza pierde el foco:
$(<selector to your input field>).focus(function(){
var $this = $(this);
if (<user agent target check>) {
function removeFocus () {
$(<selector to some different interactive element>).focus();
$(window).off(''resize'', removeFocus);
}
$(window).on(''resize'', removeFocus);
}
});
y funcionó como un amuleto y arregló mi formulario de inicio de sesión adhesivo.
Por favor NOTA:
- El código JS anterior es solo para presentar mi idea. Para ejecutar este fragmento, reemplace los valores en llaves angulares (<>) con los valores adecuados para su situación.
- Este código está diseñado para funcionar con
jQuery v1.10.2
Realmente trabajé duro para encontrar esta solución, que en resumen busca el enfoque y los eventos de desenfoque en las entradas, y el desplazamiento para cambiar selectivamente el posicionamiento de la barra fija cuando ocurren los eventos. Esto es a prueba de balas, y cubre todos los casos (navegando con <>, desplazamiento, botón hecho). Nota id = "nav" es mi divisor de pie de página fijo. Puede transferir fácilmente esto a js estándar o jquery. Esto es dojo para aquellos que usan herramientas eléctricas ;-)
define (["dojo / listo", "dojo / consulta",], función (listo, consulta) {
ready(function(){
/* This addresses the dreaded "fixed footer floating when focusing inputs and keybard is shown" on iphone
*
*/
if(navigator.userAgent.match(/iPhone/i)){
var allInputs = query(''input,textarea,select'');
var d = document, navEl = "nav";
allInputs.on(''focus'', function(el){
d.getElementById(navEl).style.position = "static";
});
var fixFooter = function(){
if(d.activeElement.tagName == "BODY"){
d.getElementById(navEl).style.position = "fixed";
}
};
allInputs.on(''blur'', fixFooter);
var b = d.body;
b.addEventListener("touchend", fixFooter );
}
});
}); // fin definir
Sí, parece que Apple no pensó que este fuera tan bueno para IOS5. Cualquier elemento de posición fijo se vuelve relativo a la página tan pronto como aparece el teclado virtual. Probablemente estaría bien si los elementos volvieran a una posición absoluta ya que esto no rompería el diseño. Lamentablemente, la ubicación real de estos elementos es mucho menos predecible.
Tengo este problema exacto con mi encabezado fijo en [ELIMINADO]. Desplácese hacia abajo en la página, luego haga clic en el cuadro de búsqueda y bang ... diseño roto. Incluso he intentado solucionarlo volviendo al posicionamiento absoluto en el evento de enfoque, que funciona pero luego pierdo el foco (el teclado permanece abierto pero el cursor ya no está en el cuadro de búsqueda).
De todos modos, estoy trabajando en eso, así que te dejaré saber si lo clasifico
Aclamaciones
Si alguien estaba buscando una ruta completamente diferente (como si ni siquiera está buscando anclar este div "pie de página" mientras se desplaza pero solo quiere que el div se quede al final de la página), puede establecer la posición del pie de página como relativo.
Eso significa que, incluso si el teclado virtual aparece en el navegador de su dispositivo móvil, su pie de página simplemente permanecerá anclado en la parte inferior de la página, sin tratar de reaccionar ante el show o el cierre del teclado virtual.
Obviamente se ve mejor en Safari si la posición es fija y el pie de página sigue la página a medida que se desplaza hacia arriba o hacia abajo, pero debido a este extraño error en Chrome, terminamos cambiando para hacer que el pie de página sea relativo.
Solo en caso de que alguien descubra este hilo como lo hice mientras investigaba este tema. Encontré este hilo útil para estimular mi pensamiento sobre este tema.
Esta fue mi solución para esto en un proyecto reciente. Solo necesita cambiar el valor de "targetElem" a un selector jQuery que represente su encabezado.
if(navigator.userAgent.match(/iPad/i) != null){
var iOSKeyboardFix = {
targetElem: $(''#fooSelector''),
init: (function(){
$("input, textarea").on("focus", function() {
iOSKeyboardFix.bind();
});
})(),
bind: function(){
$(document).on(''scroll'', iOSKeyboardFix.react);
iOSKeyboardFix.react();
},
react: function(){
var offsetX = iOSKeyboardFix.targetElem.offset().top;
var scrollX = $(window).scrollTop();
var changeX = offsetX - scrollX;
iOSKeyboardFix.targetElem.css({''position'': ''fixed'', ''top'' : ''-''+changeX+''px''});
$(''input, textarea'').on(''blur'', iOSKeyboardFix.undo);
$(document).on(''touchstart'', iOSKeyboardFix.undo);
},
undo: function(){
iOSKeyboardFix.targetElem.removeAttr(''style'');
document.activeElement.blur();
$(document).off(''scroll'',iOSKeyboardFix.react);
$(document).off(''touchstart'', iOSKeyboardFix.undo);
$(''input, textarea'').off(''blur'', iOSKeyboardFix.undo);
}
};
};
Hay un poco de retraso en la toma de control porque iOS detiene la manipulación DOM mientras se desplaza, pero funciona ...
Tengo el mismo problema. Pero me di cuenta de que la posición fija solo se retrasa y no se rompe (al menos para mí). Espere de 5 a 10 segundos y vea si el div se ajusta a la parte inferior de la pantalla. Creo que no es un error sino una respuesta demorada cuando el teclado está abierto.
Tengo una solución similar a @NealJMD, excepto que la mía solo se ejecuta para iOS y determina correctamente el desplazamiento de desplazamiento midiendo scollTop antes y después del desplazamiento del teclado nativo, así como el uso de setTimeout para permitir el desplazamiento nativo:
var $window = $(window);
var initialScroll = $window.scrollTop();
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
setTimeout(function () {
$window.scrollTop($window.scrollTop() + (initialScroll - $window.scrollTop()));
}, 0);
}
Tuve este problema en mi aplicación. Así es como estoy trabajando a su alrededor:
input.on(''focus'', function(){
header.css({position:''absolute''});
});
input.on(''blur'', function(){
header.css({position:''fixed''});
});
Simplemente me desplazo hacia arriba y lo coloco allí, para que el usuario de iOS no note que pasa nada extraño. Envuelva esto en alguna detección de agente de usuario para que otros usuarios no obtengan este comportamiento.
Tuve un problema de iPad ligeramente diferente donde el teclado virtual empujó mi ventana fuera de la pantalla. Luego, después de que el usuario cerró el teclado virtual, mi ventana todavía estaba fuera de pantalla. En mi caso, hice algo como lo siguiente:
var el = document.getElementById(''someInputElement'');
function blurInput() {
window.scrollTo(0, 0);
}
el.addEventListener(''blur'', blurInput, false);
Tuve un problema similar a @ ds111 s. Mi sitio web fue empujado hacia arriba por el teclado, pero no se movió hacia abajo cuando el teclado se cerró.
Primero probé la solución @ ds111 pero tenía dos campos de input
. Por supuesto, primero el teclado se va, entonces ocurre la borrosidad (o algo así). Entonces, la segunda input
estaba debajo del teclado, cuando el foco cambiaba directamente de una entrada a la otra.
Además, el "salto" no fue lo suficientemente bueno para mí, ya que toda la página solo tiene el tamaño del ipad. Así que hice el pergamino suave.
Finalmente, tuve que adjuntar el oyente del evento a todas las entradas, incluso aquellas, que estaban actualmente ocultas, de ahí el live
.
Todos juntos puedo explicar el siguiente fragmento de JavaScript como: Adjunte el siguiente detector de eventos de desenfoque a la entrada actual y futura y área de textarea
(= en live
): Espere un período de gracia (= window.setTimeout(..., 10)
) y sin problemas desplazarse hacia arriba (= animate({scrollTop: 0}, ...)
) pero solo si "no se muestra el teclado" (= if($(''input:focus, textarea:focus'').length == 0)
) .
$(''input, textarea'').live(''blur'', function(event) {
window.setTimeout(function() {
if($(''input:focus, textarea:focus'').length == 0) {
$("html, body").animate({ scrollTop: 0 }, 400);
}
}, 10)
})
Tenga en cuenta que el período de gracia (= 10
) puede ser demasiado corto o que el teclado aún puede mostrarse, aunque no se enfoca ninguna input
o área de textarea
. Por supuesto, si desea que el desplazamiento sea más rápido o más lento, puede ajustar la duración (= 400
)
iOS9: el mismo problema.
TLDR: fuente del problema Para la solución, desplazarse hacia abajo
Tenía un formulario en una position:fixed
iframe position:fixed
con id = ''subscribe-popup-frame''
Según la pregunta original, en el enfoque de entrada, el iframe iría a la parte superior del documento en lugar de a la parte superior de la pantalla.
El mismo problema no ocurrió en el modo safari dev con el agente de usuario configurado en un idevice. Entonces parece que el problema es causado por el teclado virtual de iOS cuando aparece.
Obtuve cierta visibilidad de lo que sucedía al registrar la posición del iframe en la consola (por ejemplo, $(''#subscribe-popup-frame'', window.parent.document).position()
) y desde allí pude ver que iOS parecía estar configurando el posición del elemento en {top: -x, left: 0}
cuando el teclado virtual apareció (es decir, se centró en el elemento de entrada).
Así que mi solución fue tomar esa molesta -x
, invertir el signo y luego usar jQuery para agregar esa posición top
al iframe. Si hay una solución mejor, me encantaría escucharla, pero después de probar una docena de enfoques diferentes, fue la única que funcionó para mí.
Inconveniente: Necesitaba establecer un tiempo de espera de 500 ms (tal vez menos funcionaría, pero quería estar seguro) para asegurarme de haber capturado el valor x
final después de que iOS hiciera su travesura con la posición del elemento. Como resultado, la experiencia es muy desigual. . . Pero al menos funciona
Solución
var mobileInputReposition = function(){
//if statement is optional, I wanted to restrict this script to mobile devices where the problem arose
if(screen.width < 769){
setTimeout(function(){
var parentFrame = $(''#subscribe-popup-frame'',window.parent.document);
var parentFramePosFull = parentFrame.position();
var parentFramePosFlip = parentFramePosFull[''top''] * -1;
parentFrame.css({''position'' : ''fixed'', ''top'' : parentFramePosFlip + ''px''});
},500);
}
}
Luego simplemente llame a mobileInputReposition
en algo como $(''your-input-field).focus(function(){})
y $(''your-input-field).blur(function(){})
Jory Cunningham
y lo mejoré:
En muchos casos, no es solo un elemento el que se vuelve loco, sino varios elementos de posición fija, por lo que en este caso, targetElem
debe ser un objeto jQuery que tenga todos los elementos fijos que desee "arreglar". Ho, esto parece hacer que el teclado iOS desaparezca si te desplazas ...
No hace falta mencionar que debe usar este evento DESPUÉS del documento DOM ready
o justo antes de la etiqueta de cierre </body>
.
(function(){
var targetElem = $(''.fixedElement''), // or more than one
$doc = $(document),
offsetY, scrollY, changeY;
if( !targetElem.length || !navigator.userAgent.match(/iPhone|iPad|iPod/i) )
return;
$doc.on(''focus.iOSKeyboardFix'', ''input, textarea, [contenteditable]'', bind);
function bind(){
$(window).on(''scroll.iOSKeyboardFix'', react);
react();
}
function react(){
offsetY = targetElem.offset().top;
scrollY = $(window).scrollTop();
changeY = offsetY - scrollY;
targetElem.css({''top'':''-''+ changeY +''px''});
// Instead of the above, I personally just do:
// targetElem.css(''opacity'', 0);
$doc.on(''blur.iOSKeyboardFix'', ''input, textarea, [contenteditable]'', unbind)
.on(''touchend.iOSKeyboardFix'', unbind);
}
function unbind(){
targetElem.removeAttr(''style'');
document.activeElement.blur();
$(window).off(''scroll.iOSKeyboardFix'');
$doc.off(''touchend.iOSKeyboardFix blur.iOSKeyboardFix'');
}
})();