13

我正在构建一个游戏作为 iPad 的 web 应用程序。它包含一个摇动动作来触发其中一个屏幕的事件,但是,由于它还有一个信息收集表单,因此有时该摇动动作会触发烦人的“摇动以撤消”对话框。当用户达到摇动动作时,用户输入的表单输入甚至不再存在于 DOM 中,所以在我看来,撤消功能不应该被触发,但不幸的是它是。不可能将其包装在本机包装器(PhoneGap 或其他)中,所以我想知道是否有人知道是否可以通过 CSS 或 JavaScript 为特定网页/应用程序禁用此功能?

谢谢。

4

9 回答 9

9

这篇博客描述了一个使用 DeviceMotionEvent 监听器的非常简单的抖动检测:

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

尝试使用以下代码禁用撤消事件发生:

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();
});

我能想到的另一件事是在完成后将文本输入转换为只读项。据推测,只读输入字段不能使用撤消功能,尽管我还没有测试过。奇怪的是,即使输入不再是 DOM 的一部分,该功能也会触发。

我不确定是否可以通过 CSS 中的 -webkit- 属性来防止摇晃动作。以下是 webkit 特定 CSS 属性的列表(可能不包含 100% 的可访问属性)。

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

于 2011-06-29T12:42:10.777 回答
9

对于PhoneGap,我刚刚插入了这一行: [UIApplication sharedApplication].applicationSupportsShakeToEdit = NO; 在 webViewDidFinishLoad 类中,它为我创造了奇迹。

只需转到 MainViewController.m 并将 webViewDidFinishLoad 更改为如下所示:

- (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];
}
于 2013-05-09T11:39:56.323 回答
4

我最近在开发用户使用 WebSockets 配对设备的游戏时遇到了这个问题。不幸的是,上述解决方案都不起作用。

简而言之,游戏涉及用户通过手机上的表格订阅频道。订阅后,他们会摇晃设备,然后在他们的桌面上播放一个场景。问题是,只要有人摇晃 iOS 设备,就会弹出“撤消键入”警报。

这是我为这个问题找到的仅有的两个解决方案。

  1. 防止您的输入永远失去焦点。如果输入是表单的一部分,这将要求您阻止表单提交。您还必须在任何锚点上侦听“touchstart”而不是“click”,并防止 touchstart 事件传播。这将防止该锚获得焦点,并且您的输入不会失去焦点。这种方法肯定有一些缺点。

  2. 将“keydown”事件处理程序添加到窗口并防止事件传播。这可以防止任何值被插入到 iOS 设备上的输入中。我还必须创建一个将键码映射到正确字符的对象。这是我结束的路线,因为我在输入中只需要一个 6 字符的代码,所以我只需要数字。如果您需要的不仅仅是数字,这可能会让人头疼。在按下键时,通过键码捕获该字符并设置输入的值。这使 iOS 误以为从未通过键盘将任何值插入到输入中,因此没有什么可以撤消的。

请记住,阻止 keydown 事件传播不会阻止在股票 android 浏览器上输入,因此它会正常运行。但这没关系,因为这不是安卓问题。您可以通过侦听输入本身的输入事件并在收到此事件时删除 keydown 侦听器来防止插入重复值。

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); 
于 2013-04-24T17:17:42.587 回答
4

Objective-C

只需在“- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions”中添加代码行

[application setApplicationSupportsShakeToEdit:NO];

斯威夫特 2.x

在 appDelegate.swift didFinishLaunchingWithOptions方法中添加单行代码

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

    application.applicationSupportsShakeToEdit = false
    return true
}

斯威夫特 3.x

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

    application.applicationSupportsShakeToEdit = false
    return true
}
于 2014-08-05T15:19:58.383 回答
1

也许尝试event.preventDefault();在您的 DeviceMotionEvent 侦听器中?

环顾 Stack Overflow,我可以看到其他人已经成功地使用 CSS 禁用了默认“事件”(奇怪的是)。

在 iOS MobileSafari 中防止默认按下而不是默认拖动?

于 2011-06-29T12:06:49.967 回答
1

请参阅:如何阻止 UITextField 响应摇动手势?

对于 phonegap,在 AppDelegate.m 的 webViewFinishLoad 方法中设置此属性

于 2012-10-05T00:01:51.120 回答
1

我找到了一个始终如一的解决方法:您可以将文本输入托管在一个框架中。完成输入后,从页面中删除框架。这似乎可以解决问题。

function resetIframe() {
  // Remove the old frame
  document.body.removeChild(frame);

  // Create a new frame that has an input internally
  frame = document.createElement('iframe');
  frame.src = '/html-with-input.html';
  frame.style = 'border: 0; height: 30px; width: 200px;'
  document.body.appendChild(frame);

  // When the frame is ready, grab a reference to the input
  frame.addEventListener('load', () => {  
    const input = frame.contentDocument.body.querySelector('input');
    console.log(frame, frame.contentDocument.body)

    // When the input changes, grab the value
    input.addEventListener('input', e => {
      document.getElementById('output').innerText = e.target.value;
    });
  });
}

这是一个概念证明:https ://codepen.io/joshduck/full/RJMYRd/

于 2018-06-21T10:09:23.683 回答
1

第一个解决方案

最简单的方法是使用这个插件:

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

第二种解决方案

如果您不想使用上面的插件,那么您应该通过打开 MainViewController.m 手动执行它并将 webViewDidFinishLoad 更改为如下所示:

- (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];
}

第三个解决方案

这是我设计的另一个解决方案,用于禁用适用于文本输入的“Shake To Undo”。请注意,不允许用户插入表情符号。

<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>
于 2017-04-18T20:19:07.863 回答
0

将输入放入 iframe,当您不需要输入时重新加载 iframe。

于 2016-03-15T06:19:23.950 回答