Как отключить iOS «Shake to Undo» в веб-приложении - PullRequest
13 голосов
/ 29 июня 2011

Я создаю игру как веб-приложение для iPad.Он включает в себя действие встряхивания для запуска события для одного из экранов, но, поскольку он также имеет форму сбора информации, иногда это действие встряхивания вызывает раздражающий диалог «Встряхнуть для отмены».Ввод формы, введенный пользователем, даже не существует в DOM, когда пользователь достигает действия встряхивания, поэтому, на мой взгляд, функция отмены не должна вызываться, но, к сожалению, это так.Нет никакого способа, которым это может быть обернуто в нативную оболочку (PhoneGap или другую), поэтому мне было интересно, если кто-нибудь знает, возможно ли вообще отключить эту функцию для определенной веб-страницы / приложения через CSS или JavaScript?

Спасибо.

Ответы [ 9 ]

9 голосов
/ 29 июня 2011

В этом блоге описывается очень простое обнаружение сотрясений с помощью прослушивателя 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.

Я не уверен, можно ли предотвратить действие встряхивания через свойства -webkit- в CSS. Вот список определенных CSS-свойств webkit (которые могут не содержать 100% доступных свойств).

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

8 голосов
/ 09 мая 2013

Для PhoneGap я просто вставил следующую строку: [UIApplication sharedApplication] .applicationSupportsShakeToEdit = NO;в классе webViewDidFinishLoad, и он для меня творит чудеса.

Просто зайдите на MainViewController.m и измените webViewDidFinishLoad, чтобы он выглядел так:

4 голосов
/ 05 августа 2014

Objective-C

Просто добавьте строку кода внутри приложения "- (BOOL): (UIApplication *) приложение didFinishLaunchingWithOptions: (NSDictionary *) launchOptions"

[application setApplicationSupportsShakeToEdit:NO];

Swift 2.x

Добавить одну строку кода в appDelegate.swift didFinishLaunchingWithOptions метод

Функциональное приложение (приложение: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    application.applicationSupportsShakeToEdit = false
    return true
}

Swift 3.x

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

    application.applicationSupportsShakeToEdit = false
    return true
}
4 голосов
/ 24 апреля 2013

Недавно я столкнулся с этой проблемой при разработке игры, в которой пользователь объединяет устройства с помощью WebSockets. К сожалению, ни одно из упомянутых выше решений не работает.

Короче говоря, в игре участвовал пользователь, подписывающийся на канал через форму на своем телефоне. После подписки они встряхивают устройство, и на их рабочем столе разворачивается сценарий. Проблема заключалась в том, что каждый раз, когда кто-то встряхивал устройство iOS, появлялось предупреждение «отменить ввод».

Вот только два решения, которые я нашел для этой проблемы.

  1. Предотвратите ваш ввод от потери фокуса. Это потребует от вас запрета отправки формы, если ввод является частью формы. Вы также должны прослушивать «touchstart» вместо «click» на любых привязках и предотвращать распространение события touchstart. Это предотвратит фокусировку этого якоря, а ваш ввод потеряет фокус. Такой подход наверняка имеет некоторые недостатки.

  2. Добавить обработчик события «keydown» в окно и предотвратить распространение события. Это предотвращает вставку любых значений во входные данные на устройствах iOS. Я также должен был создать объект, который сопоставил коды клавиш с соответствующим символом. Это маршрут, который я закончил, потому что все, что мне было нужно для ввода, было 6-значным кодом, поэтому мне нужны были только цифры. Если вам нужно больше, чем просто цифры, это может быть боль в заднице. Нажав клавишу, поймайте этот символ с помощью кода клавиши и установите значение для ввода. Это заставляет iOS думать, что никакое значение не было введено во ввод с клавиатуры, поэтому отменить его нечего.

Имейте в виду, что предотвращение распространения события нажатия клавиш не препятствует вводу данных в стандартном браузере Android, поэтому оно будет нормально функционировать. Но это нормально, так как это не проблема Android. Вы можете предотвратить вставку повторяющихся значений, прослушивая событие ввода на самом входе и удаляя прослушиватель клавиатуры, если это событие получено.

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); 
1 голос
/ 18 апреля 2017

Первое решение

Самый простой способ - использовать этот плагин:

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>
1 голос
/ 05 октября 2012

См .: Как запретить UITextField реагировать на жест встряхивания?

Для пробела в телефоне установите это свойство в методе webViewFinishLoad в AppDelegate.m

1 голос
/ 29 июня 2011

Возможно, попробуйте event.preventDefault(); в вашем прослушивателе DeviceMotionEvent?

Оглядываясь вокруг переполнения стека, я вижу, что другие люди успешно отключили «события» по умолчанию с помощью CSS (странно).

Запретить по умолчанию Нажмите, но не по умолчанию Перетащите в iOS MobileSafari?

0 голосов
/ 21 июня 2018

Я нашел обходной путь, который работает последовательно: вы можете разместить ввод текста во фрейме.Когда вы закончите с вводом, удалите рамку со страницы.Это, кажется, делает трюк.

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/

0 голосов
/ 15 марта 2016

Поместите ввод в iframe, перезагрузите iframe, когда вам не нужен ввод.

...