Evitar el desplazamiento en el navegador móvil, sin impedir el enfoque de entrada

Utilizo preventDefault () en touchstart en el documento para evitar el desplazamiento en una página. Desafortunadamente esto evita demasiado. El usuario ya no puede dar enfoque a una entrada (y abrir el teclado virtual). Usando jQuery focus (), puedo dar el foco a la entrada en un touchstart. Esto abre el teclado virtual en iOS (la mayoría de las veces), pero nunca en Android.

Antecedentes :

Tengo una página web que quiero hacer tanto como una aplicación móvil como sea posible. Sólo estoy preocupado por Android e iOS, pero cualquier factor de forma. Empezaré haciendo que el contenido de la página tenga exactamente el mismo tamaño que el tamaño de la pantalla. Esto es bueno hasta que el usuario pone su dedo en la página. Necesito impedir el desplazamiento del usuario. El código siguiente logra esto, pero de maneras ligeramente diferentes en los dos sistemas operativos.

$(document).on('touchstart', function(e) { e.preventDefault(); }); 

En iOS, esto evita el desplazamiento elástico: cuando un usuario puede revelar una textura detrás de la página web intentando desplazarse por la página. La característica es agradable para una página web regular, pero en mi caso, le resta valor a la UX.

En Android, evita la revelación de un hack práctico que utilizo para ocultar la barra de direcciones. Los navegadores de Android comienzan con la barra de direcciones visible, pero cuando el usuario desplaza hacia abajo la página, desaparece. Para forzar programaticamente el navegador, oculte la barra de direcciones, simplemente agregue esta línea de código a su función llamada en carga.

 $('html, body').scrollTop(1); 

Esta es una manera hacky (pero también la única) para decirle al navegador android que hemos explorado, y la barra de direcciones ya no es necesario.

Sin el preventDefault en el documento, el navegador de Android permitirá el desplazamiento y la barra de direcciones se puede revelar.

Por lo tanto, ambos sistemas operativos tienen una buena razón para tener este preventDefault () llamado a cada touchstart en el documento, pero evita demasiado. Tocar en un campo de entrada no hace nada. El uso de una llamada a jQuery focus () puede ayudar, pero sólo abre el teclado virtual en iOS, no en Android.

 $('input').on('touchstart', function() { $(this).focus(); }); 

¿Cómo puedo evitar que la página se desplace, pero usar la funcionalidad nativa del navegador para dar enfoque a los campos de entrada?

Nota: Este código

 $(document).on('touchstart', function(e) { if (e.target.nodeName !== 'INPUT') { e.preventDefault(); } }); 

Es defectuoso porque el usuario todavía puede desplazarse por la página siempre que el toque inicial se origina dentro del campo de entrada.

Realmente resolví este problema en otro proyecto, lo olvidé y lo recordé casi todo el tiempo escribiendo esto.

Ellos clave es hacerlo en touchmove.

 $(document).on('touchmove', function(e) { e.preventDefault(); }); 

Sin embargo, preventDefault en touchstart hace todo tipo de cosas agradables como prevenir el menú de guardar imágenes en una presentación de diapositivas con gestos. Mis proyectos también incluyen esto.

 $(document).on('touchstart', function(e) { if (e.target.nodeName !== 'INPUT') { e.preventDefault(); } }); 

Si alguien tiene algunas sugerencias sobre contenido adicional o cómo reformatear esto para que pueda llegar a un público mayor que sería genial. Nunca he visto el contenido que tengo aquí en un solo lugar, así que sentí que necesitaba estar en SO.

Combinar los dos!

 // prevent scrolling from outside of input field $(document).on('touchstart', function(e) { if (e.target.nodeName !== 'INPUT') { e.preventDefault(); } }); // prevent scrolling from within input field $(document).on('touchmove', function(e) { if (e.target.nodeName == 'INPUT') { e.preventDefault(); } }); 

Esto probablemente no es perfecto tampoco, y estoy especialmente preocupado de que la primera función evitará los siguientes enlaces, pero voy a dejar que otros hagan pruebas extensas.

La respuesta simple a su pregunta es no utilizar "preventDefault" en su lugar utilizar la propiedad pointer-events css para deshabilitar el desplazamiento en el elemento que se desplaza.

CSS para sus entradas:

 input { pointer-events: auto !important; } 

Touchstart listener de eventos:

 document.body.addEventListener('touchstart', function(e) { if (e.target.nodeName === 'INPUT') { this.style.pointerEvents = 'none'; } }); 

Tendrá que restablecer los eventos de puntero cuando borre la entrada.

 document.body.pointerEvents = 'auto'; 

+1 Buena Pregunta

  • Cómo encontrar el navegador predeterminado establecido en el dispositivo Android
  • ¿Cómo admitir la visualización de PDF para todos los navegadores móviles?
  • Cómo enfocar un campo de entrada en el navegador de Android a través de javascript o jquery
  • Página web del navegador web de Android
  • "SDK-buildable" Navegadores Web de código abierto para Android
  • Combinando el front-end de html y el "back-end" de python en la aplicación móvil
  • Border-radius no funciona en el moderno navegador nativo de Android
  • Crear navegador-marcador de la aplicación
  • Escala del navegador de Android?
  • El navegador predeterminado de Android crea la barra de desplazamiento horizontal para diseño responsivo
  • Cómo ocultar la barra de direcciones del navegador cuando la altura de la página es fija y tiene jQuery desplazamiento interno
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.