extjs6、sencha touch 点击穿透/鬼点击(Ghost Click) 的缓解办法



安卓的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(名字无所谓,自己取),内容如下:

[css]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. .x-container.prevent-pointer-events input, .x-container.prevent-pointer-events textarea {  
  2.     pointer-events: none;  
  3. }  

pointer-events: none :顾名思意,就是鼠标事件拜拜的意思(当然,触摸事件也一样)。元素应用了该CSS属性,链接啊,点击啊什么的都变成了“浮云牌酱油”。

有了这个css样式的input和textarea是不能被聚焦的。


2、监听Ext.Viewport的avtiveitemchange事件之前和之后。在avtiveitemchange事件之前,给将要切换到的新视图添加prevent-pointer-events样式;在avtiveitemchange事件之后,给已经切换到的新视图移除prevent-pointer-events样式(当然,要一段时间之后才能移除,不然没效果,比如300ms之后)

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Ext.Viewport.onBefore('activeitemchange'function(container, newItem, oldItem) {  
  2.      if (newItem.element)  
  3.          newItem.element.addCls('prevent-pointer-events');  
  4.  }, this);  
  5.    
  6. Ext.Viewport.onAfter('activeitemchange'function(container, newItem, oldItem) {  
  7.     setTimeout(function() {  
  8.         if (newItem.element)  
  9.             newItem.element.removeCls('prevent-pointer-events');  
  10.     }, 300);  
  11. }, 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样式

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Ext.Viewport.on({  
  2.     delegate: 'mask',  
  3.     show: function(mask) {  
  4.         var activeItem = Ext.Viewport.getActiveItem();  
  5.         if (activeItem.element)  
  6.             activeItem.element.addCls('prevent-pointer-events');  
  7.     },  
  8.     hide: function(mask) {  
  9.         var activeItem = Ext.Viewport.getActiveItem();  
  10.         setTimeout(function() {  
  11.             if (activeItem.element)  
  12.                 activeItem.element.removeCls('prevent-pointer-events');  
  13.         }, 300);  
  14.     }  
  15. });  





安卓的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(名字无所谓,自己取),内容如下:

[css]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. .x-container.prevent-pointer-events input, .x-container.prevent-pointer-events textarea {  
  2.     pointer-events: none;  
  3. }  

pointer-events: none :顾名思意,就是鼠标事件拜拜的意思(当然,触摸事件也一样)。元素应用了该CSS属性,链接啊,点击啊什么的都变成了“浮云牌酱油”。

有了这个css样式的input和textarea是不能被聚焦的。


2、监听Ext.Viewport的avtiveitemchange事件之前和之后。在avtiveitemchange事件之前,给将要切换到的新视图添加prevent-pointer-events样式;在avtiveitemchange事件之后,给已经切换到的新视图移除prevent-pointer-events样式(当然,要一段时间之后才能移除,不然没效果,比如300ms之后)

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Ext.Viewport.onBefore('activeitemchange'function(container, newItem, oldItem) {  
  2.      if (newItem.element)  
  3.          newItem.element.addCls('prevent-pointer-events');  
  4.  }, this);  
  5.    
  6. Ext.Viewport.onAfter('activeitemchange'function(container, newItem, oldItem) {  
  7.     setTimeout(function() {  
  8.         if (newItem.element)  
  9.             newItem.element.removeCls('prevent-pointer-events');  
  10.     }, 300);  
  11. }, 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样式

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Ext.Viewport.on({  
  2.     delegate: 'mask',  
  3.     show: function(mask) {  
  4.         var activeItem = Ext.Viewport.getActiveItem();  
  5.         if (activeItem.element)  
  6.             activeItem.element.addCls('prevent-pointer-events');  
  7.     },  
  8.     hide: function(mask) {  
  9.         var activeItem = Ext.Viewport.getActiveItem();  
  10.         setTimeout(function() {  
  11.             if (activeItem.element)  
  12.                 activeItem.element.removeCls('prevent-pointer-events');  
  13.         }, 300);  
  14.     }  
  15. });  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值