[Phonegap Sencha Touch] 移動開發23 Android和IOS的webview 點選穿透/鬼點選(Ghost Click) 的緩解辦法

NO IMAGE

原文地址:http://blog.csdn.net/lovelyelfpop/article/details/28855051

安卓的webview和自帶瀏覽器下有個奇怪的現象。

現象

1、如果輸入框input或者textarea的正上方(z軸方向,即上層)有個div,當點選這個div使得div隱藏了之後,input會得到焦點,導致軟鍵盤彈出。

2、瀏覽檢視點選某個地方切換到編輯檢視,如果瀏覽檢視點選的位置 在 編輯檢視相應位置有個輸入框,那麼切換過去之後,編輯頁的輸入框會自動得到焦點。

這個體驗很不舒服。

討論

這個不是點選事件的事件冒泡導致的(因為e.stopPropagation()和return false是沒有用的),因為如果把輸入框換成一個按鈕,按鈕的事件是不會觸發的。

其實是因為先觸發的是touchstart,手指離開後觸發touchend,300ms之後觸發了click。如果在300ms之後的位置剛好有一個input,那就被click了,也就是被focus,自動彈出鍵盤了。

安卓自帶瀏覽器和webview有這個問題,IOS也有,移動版chrome沒有這個現象。

所以這個就是webview的bug了。

昨天找到一個緩解辦法,為什麼不叫解決辦法?因為安卓的bug我沒法去改進,只能通過一些技巧來避免這個問題。

好了,辦法如下:

1、寫一個名為prevent-pointer-events的css(名字無所謂,自己取),內容如下:

.x-container.prevent-pointer-events input, .x-container.prevent-pointer-events textarea {
pointer-events: none;
}

pointer-events: none:顧名思意,就是滑鼠事件拜拜的意思(當然,觸控事件也一樣)。元素應用了該CSS屬性,連結啊,點選啊什麼的都變成了“浮雲牌醬油”。

有了這個css樣式的input和textarea是不能被聚焦的。

2、監聽Ext.Viewport的avtiveitemchange事件之前和之後。在avtiveitemchange事件之前,給將要切換到的新檢視新增prevent-pointer-events樣式;在avtiveitemchange事件之後,給已經切換到的新檢視移除prevent-pointer-events樣式(當然,要一段時間之後才能移除,不然沒效果,比如300ms之後)

Ext.Viewport.onBefore('activeitemchange', function(container, newItem, oldItem) {
if (newItem.element)
newItem.element.addCls('prevent-pointer-events');
}, this);
Ext.Viewport.onAfter('activeitemchange', function(container, newItem, oldItem) {
setTimeout(function() {
if (newItem.element)
newItem.element.removeCls('prevent-pointer-events');
}, 300);
}, this);

如果你用了navigationview進行檢視間切換的,那麼你也應該在navigationview的avtiveitemchange事件之前和之後新增這兩個事件處理函式(記得navigationview在destroy的時候移除這兩個事件監聽處理函式,否則可能有指令碼錯誤can’t call method ‘removeCls’ of undefined。移除監聽用unBefore和unAfter)。

3、還有一處。當Ext.Msg彈出訊息框之後,點選訊息框按鈕使訊息框隱藏,如果訊息框按鈕正下方有輸入框,輸入框也會聚焦到。所以這裡也要處理下(同理,其他各種各樣的情形)。

訊息框彈出的時候會有個mask遮罩層顯示,我們可以在mask顯示出來的時候,把它正下方的檢視新增prevent-pointer-events樣式;mask隱藏的時候,把它正下方的檢視移除prevent-pointer-events樣式

Ext.Viewport.on({
delegate: 'mask',
show: function(mask) {
var activeItem = Ext.Viewport.getActiveItem();
if (activeItem.element)
activeItem.element.addCls('prevent-pointer-events');
},
hide: function(mask) {
var activeItem = Ext.Viewport.getActiveItem();
setTimeout(function() {
if (activeItem.element)
activeItem.element.removeCls('prevent-pointer-events');
}, 300);
}
});

歡迎加入Sencha Touch Phonegap交流群

1群:194182999 (滿)

2群:419834979

共同學習交流(博主QQ:479858761