彻底解决IOS HTML页面上光标跳行、光标不跟随页面问题
声明:这里只是说明一种处理方法
继上一篇文章,处理IOS滑动时,光标不跟随页面滚动,处理方法是,监听touchmove事件,获取当focus的元素,使之失去光标;但是这种方法并不能真正的解决问题,比如,你进入页面,并不滑动页面,而是去点击屏幕可见区域最底下的输入框时,问题就出来了,如图:
这里说一下,网络上大多说是IOS上fixed定位,修改定位为absolute;或者是添加fastclick.js库,加速手机上tap事件的响应;
问题就出在这里,你确定你的页面是定位的因素?你确定添加了fastclick库就可以了?如果尝试了上面两种方法还不行,你可以接着往下看;
仔细观察页面,当你点击最后一行输入框时、滑动页面时,或者是弹框;你可以看到页面上的活动元素先聚焦再滚动;也就是说,activate元素的聚焦事件在页面滚动之前或者滚动完成之前就已经完成了,所以这时候页面滚动,而光标又不跟随滚动,就造成了光标跳行、错乱的问题。
解决方法:
一、输入框在聚焦的时候,会弹起软键盘;所以,我们监听软键盘弹起事件,在弹起事件后,进行dom重绘,但是这种必须要加延时,代码如下:
document.body.addEventListener('focusin', function () { //软键盘弹起事件
var node = document.activeElement; //当前focus的dom元素
setTimeout(function () {
if (node) {
if (node.nodeName == "TEXTAREA" || node.nodeName == 'INPUT') { //如果是input或textarea
if (node.style.textShadow === '') {
node.style.textShadow = 'rgba(0,0,0,0) 0 0 0'; //改变某个不可见样式,触发dom重绘
} else {
node.style.textShadow = '';
}
}
}
}, 1000);
});
二、监听屏幕滚动事件;是屏幕滚动,不是手指滑动的事件,因为我这里使用的是sencha Touch移动端框架,所以,可能会不适应,但是道理是一样的;代码如下:
initialize: function () {
var me = this;
me.callParent();
me.element.on({
submit: 'onSubmit',
scope: me
});
var scrollable = this.getInitialConfig().scrollable;
if (scrollable == null || scrollable == false) {
this.isScrollable = false;
} else {
this.isScrollable = true;
}
//添加scroll事件监听
me.getScrollable().getScroller().on({
scroll: 'onScroll',
scope: me
});
},
//添加scroll事件响应函数
onScroll: function () {
var node = document.activeElement; //当前focus的dom元素
if (node) {
if (node.nodeName == "TEXTAREA" || node.nodeName == 'INPUT') { //如果是input或textarea
if (node.style.textShadow === '') {
node.style.textShadow = 'rgba(0,0,0,0) 0 0 0'; //改变某个不可见样式,触发dom重绘
} else {
node.style.textShadow = '';
}
}
}
},
这里是修改sencha Touch formpanel容器的源码,添加了事件的监听
对于第二个方法,如果你使用的是其他的框架,同样的你需要做一些修改。但是道理是一样的
三、理论,未实现;同样是监听屏幕滚动事件,使用定时器,实时监听该页面scrollTop,如果scrollTop在改变,那么就说明页面在滚动,如果在滚动,就获取当前页面activate元素,使之重绘
最后说一下,为什么不能监听touchmove事件,因为我们在滑动屏幕时,并不是手指离开了屏幕,屏幕就停止滚动了,屏幕还会有一个关心滚动存在;所以,单单是监听touchmove并不能解决光标错乱、跳行问题。除非,当你手指离开时,屏幕立马停止滚动。所以还是监听屏幕滚动最为靠谱
补充:如果你在touchmove中处理了光标不跟随,也就是move时取消光标聚焦;这里你可以将touchmove注释掉,因为监听scroll处理后,光标便会跟随页面滚动