[英]How to disable iOS “Shake to Undo” in a webapp
我正在構建一個游戲作為iPad的webapp。 它結合了一個搖動動作來觸發其中一個屏幕的事件,但是,由於它還有一個信息收集表單,有時搖動動作會觸發惱人的“搖動撤消”對話框。 當用戶到達搖動動作時,用戶輸入的表單輸入甚至不再存在於DOM中,所以在我看來不應該觸發撤銷功能,但不幸的是它是。 沒有辦法將它包裝在本機包裝器(PhoneGap或其他)中,所以我想知道是否有人知道是否可以通過CSS或JavaScript禁用特定網頁/應用程序的此功能?
謝謝。
此博客描述了使用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%可訪問的屬性)。
對於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];
}
我最近遇到了這個問題,同時開發了一個用戶使用WebSockets配對設備的游戲。 遺憾的是,上述解決方案都不起作用。
簡而言之,游戲涉及用戶通過手機上的表格訂閱頻道。 一旦訂閱,他們就會動搖設備並在他們的桌面上播放一個場景。 問題是每當有人震動iOS設備時,都會彈出“撤消打字”警報。
以下是我為此問題找到的唯一兩個解決方案。
防止您的輸入失去焦點。 如果輸入是表單的一部分,這將要求您阻止表單提交。 您還必須在任何錨點上偵聽“touchstart”而不是“click”,並防止touchstart事件傳播。 這樣可以防止錨點獲得焦點,輸入也不會失去焦點。 這種方法肯定有一些缺點。
向窗口添加“keydown”事件處理程序並阻止事件傳播。 這可以防止任何值插入到iOS設備上的輸入中。 我還必須創建一個將鍵碼映射到正確字符的對象。 這是我結束的路線,因為我輸入的所有內容都是6個字符的代碼所以我只需要數字。 如果你需要的不僅僅是數字,這可能是一個痛苦的屁股。 在按鍵時,通過鍵碼捕獲該字符並設置輸入值。 這讓iOS認為沒有任何值通過鍵盤輸入到輸入中,所以沒有任何東西可以撤消。
請記住,防止keydown事件傳播不會阻止在股票android瀏覽器上輸入,因此它將正常運行。 但這沒關系,因為這不是一個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);
Objective-C的
只需在“ - (BOOL)應用程序:(UIApplication *)應用程序中添加代碼行didFinishLaunchingWithOptions:(NSDictionary *)launchOptions”
[application setApplicationSupportsShakeToEdit:NO];
Swift 2.x
在appDelegate.swift didFinishLaunchingWithOptions方法中添加單行代碼
func應用程序(應用程序: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
}
對於phonegap,請在AppDelegate.m中的webViewFinishLoad方法中設置此屬性
第一解決方案
最簡單的方法是使用這個插件:
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>
也許嘗試event.preventDefault();
在您的DeviceMotionEvent偵聽器中?
看看Stack Overflow,我可以看到其他人已成功使用CSS禁用默認“事件”(奇怪)。
將輸入放入iframe,在不需要輸入時重新加載iframe。
我找到了一致的解決方法:您可以在框架中托管文本輸入。 完成輸入后,從頁面中刪除框架。 這似乎可以解決問題。
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/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.