2011-06-29 6 views
12

Estoy compilando un juego como una aplicación web para el iPad. Incorpora una acción de sacudida para activar un evento para una de las pantallas, pero, dado que también tiene un formulario de recopilación de información, a veces esa acción de sacudida desencadena el molesto diálogo "Shake to Undo". La entrada de formulario que el usuario ha tipeado ya no existe en el DOM cuando el usuario alcanza la acción de agitar, por lo que en mi opinión la función Deshacer no debería activarse, pero desafortunadamente sí lo está. No hay forma de que esto pueda envolverse en un contenedor nativo (PhoneGap u otro), así que me pregunto si alguien sabe si es posible deshabilitar esta funcionalidad para una página web/aplicación específica, a través de CSS o JavaScript.Cómo deshabilitar iOS "Shake to Undo" en una aplicación web

Gracias.

Respuesta

4

poco me encontré con este problema, mientras que el desarrollo de un juego en el que un usuario utilizando dispositivos pares WebSockets. Lamentablemente, ninguna de las soluciones mencionadas anteriormente funciona.

En resumen, el juego involucraba a un usuario que se suscribía a un canal a través de un formulario en su teléfono. Una vez suscritos, sacudirían el dispositivo y se vería un escenario en su escritorio. El problema era que cada vez que alguien sacudía un dispositivo iOS, aparecía la alerta "deshacer tipeo".

Aquí están las dos únicas soluciones que he encontrado para este problema.

  1. Evite que su entrada pierda el foco. Esto requerirá que evite el envío de formularios si la entrada es parte de un formulario. También debe escuchar "touchstart" en lugar de "hacer clic" en cualquier delimitador y evitar que el evento touchstart se propague. Esto evitará que el anclaje obtenga el foco y que su entrada pierda el foco. Este enfoque tiene algunas desventajas con seguridad.

  2. Agregar un controlador de eventos "keydown" a la ventana y evitar que el evento de propagación. Esto evita que cualquier valor se inserte en la entrada de los dispositivos iOS. También tuve que crear un objeto que asignara los códigos clave al personaje apropiado. Esta es la ruta que terminé yendo porque todo lo que necesitaba en mi entrada era un código de 6 caracteres, así que solo necesitaba números. Si necesita más que solo números, esto puede ser un dolor en el culo. Al pulsar la tecla, enganche ese carácter a través del código clave y establezca el valor de la entrada. Esto engaña a iOS para que piense que nunca se insertó ningún valor en la entrada a través del teclado, por lo que no hay nada que deshacer.

Tenga en cuenta la prevención de la propagación de evento KeyDown no impide la entrada en el navegador de Android de valores, por lo que sólo funcionará con normalidad. Pero eso está bien, ya que este no es un problema de Android. Puede evitar que los valores duplicados se inserten escuchando el evento de entrada en la entrada en sí y eliminando el oyente de selección si se recibe este evento.

var codes = { 
    48: 0, 
    49: 1, 
    50: 2, 
    51: 3, 
    52: 4, 
    53: 5, 
    54: 6, 
    55: 7, 
    56: 8, 
    57: 9 
}, 
myInput = document.getElementById("myInput"); 

var keydownHelper = function (e) { 
    e.preventDefault(); 
    myInput.removeEventListener("input", inputHelper); 

    var val = myInput.value; 

    // Delete 
    if (e.keyCode === 8 && val.length) { 
    myInput.value = val.slice(0, val.length - 1); 
    return; 
    } 

    // If not a number, do nada 
    if (typeof codes[e.keyCode] === "undefined") { return; } 

    val += codes[e.keyCode]; 
    myInput.value = val; 
}; 

var inputHelper = function (e) { 
    e.preventDefault(); 
    window.removeEventListener("keydown", keydownHelper); 
}; 

myInput.addEventListener("input", inputHelper); 
window.addEventListener("keydown", keydownHelper); 
+0

¡Gracias por compartir! No estoy en condiciones de establecer un caso de prueba en este momento, pero su respuesta parece estar muy bien investigada y hacer lo que solicité en la pregunta original, por lo que la estoy aceptando como la correcta si nadie tiene cualquier objeción :) –

9

Este blog describe una forma muy sencilla de detección de movimiento de la usando el oyente DeviceMotionEvent:

http://www.jeffreyharrell.com/blog/2010/11/creating-a-shake-event-in-mobile-safari/

Prueba el código siguiente para deshabilitar deshacer evento sucediendo:

window.addEventListener('devicemotion', function (e) { 
    // This is where you put your code for dealing with the shake event here 

    // Stop the default behavior from triggering the undo dialog (hopefully) 
    e.preventDefault(); 
}); 

Hay es otra cosa que puedo pensar que sería convertir la entrada de texto en un solo ite m después de que haya terminado con él. Presumiblemente, un campo de entrada de solo lectura no puede hacer uso de la función deshacer, aunque no lo he probado. Es extraño que la característica se dispare incluso después de que la entrada ya no forma parte del DOM.

No estoy seguro de si la prevención de una acción de sacudida se puede hacer a través de las propiedades -webkit en CSS. Aquí hay una lista de propiedades CSS específicas de webkit (que pueden no contener el 100% de las propiedades accesibles).

http://qooxdoo.org/documentation/general/webkit_css_styles

+0

+1 de mí, buen ejemplo. –

+0

Buena idea, pero desafortunadamente no hay suerte. Incluso cuando se adjunta (o utilizando la función de delegado de Zepto) el evento a los elementos de entrada, el cuadro de diálogo Deshacer aparece aún. –

+0

Ah, y establecer la entrada solo para leer todavía hace que el cuadro de diálogo aparezca también, desafortunadamente. –

7

Para PhoneGap I acaba de insertar esta línea: [UIApplication sharedApplication] .applicationSupportsShakeToEdit = NO; en la clase webViewDidFinishLoad y funcionó de maravilla para mí.

Sólo tienes que ir a la MainViewController.m y cambiar webViewDidFinishLoad a tener este aspecto:

- (void)webViewDidFinishLoad:(UIWebView*)theWebView 
{ 
    // Black base color for background matches the native apps 
    theWebView.backgroundColor = [UIColor blackColor]; 

[UIApplication sharedApplication].applicationSupportsShakeToEdit = NO; 

    return [super webViewDidFinishLoad:theWebView]; 
} 
3

Objective-C

Simplemente añadir la línea de código dentro "- aplicación (BOOL) :(UIApplication *) didFinishLaunchingWithOptions de aplicación: (NSDictionary *) launchOptions"

[application setApplicationSupportsShakeToEdit:NO]; 

2.x Swift

Añadir sola línea de código en appDelegate.swift didFinishLaunchingWithOptions método

aplicación func (aplicación: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

application.applicationSupportsShakeToEdit = false 
    return true 
} 

3.x Swift

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 

    application.applicationSupportsShakeToEdit = false 
    return true 
} 
+1

¡esto funciona 100%! –

0

Coloque la entrada en un iframe, vuelva a cargar el iframe cuando no necesite la entrada.

1

Primera solución

La forma más sencilla es utilizar este plugin:

https://github.com/nleclerc/cordova-plugin-ios-disableshaketoedit

segunda solución

Si no desea utilizar el plugin anterior, entonces deberías hacerlo manualmente abriendo MainViewController.m y el cambio webViewDidFinishLoad a este aspecto:

- (void)webViewDidFinishLoad:(UIWebView*)theWebView 
{ 
    // Black base color for background matches the native apps 
    theWebView.backgroundColor = [UIColor blackColor]; 

[UIApplication sharedApplication].applicationSupportsShakeToEdit = NO; 

    return [super webViewDidFinishLoad:theWebView]; 
} 

tercera solución

es otra solución I, diseñado para desactivar "Shake Para deshacer", que funciona en las entradas de texto. tenga en cuenta que los usuarios no pueden insertar emojis.

<body> 
    <textarea cols="40" rows="8" name="textarea" id="textarea"></textarea> 

    <script> 
    textArea = document.getElementById("textarea"); 

    textArea.onkeypress = function(event){ 
     event.preventDefault(); 
     var nationUnicode=event.which; 
     var utf8=encodeURIComponent(String.fromCharCode(parseInt(nationUnicode, 10))); 
     if (utf8.search("%EF") != 0) //value is not an Emoji 
      textArea.value= textArea.value + String.fromCharCode(nationUnicode); 
    } 

    textArea.onkeydown = function (event){ 
     if (event.keyCode == 8){ 
      event.preventDefault(); 
      var txtval = textArea.value; 
      textArea.value = txtval.slice(0, - 1); 
     } 
    } 
    </script> 
</body> 
+0

muchas gracias por la solución 3! ¡Exactamente lo que estaba buscando! Algunos emoji parecen estar funcionando (flash, por ejemplo) – vinni

Cuestiones relacionadas