移动端ios升级到11及以上时,手机弹框输入光标出现错位问题

移动端ios升级到11及以上时,手机弹框输入光标出现错位问题

引起原因:弹框的定位采取position:fixed,而ios(safari)对定位属性position:fixed的解析不一致导致。

解决方案:

方案一

一开始上网找解决方案,找到如下处理方式。但存在当页面出现滚动条时,弹框弹出后,页面回滚至顶部。在不改变原有弹框代码的情况下,有效地解决光标错位问题,但严重影响用户使用,只能忍痛舍去~

//弹框弹出后执行如下代码
$('body').css({'position': 'fixed', 'width': '100%'});
//弹框关闭后执行如下代码
$('body').css({'position': 'relative'});

方案二

尝试多种方式后,只能从源头解决,不使用position:fixed。重写弹框定位,但问题是,这个弹框涉及所有页面,后台开发用这弹框做了很多操作,弹框中间内容由于可以自定义,所以是牵一发而动全身,不敢轻易改,就连上传图片的进度条显示都是用这个弹框做的(就是为了套用弹框的一个遮罩效果)

解决思路:

1.弹框(#pop )采用position:absolute定位,遮罩(#shadow)采用fixed定位(原先采用absolute定位的,由于有些页面内容是根据用户滚动进行动态加载,导致原先的遮罩不能完全遮住所有内容,当然也可以对某些元素定高进行加载内容,避免此类问题出现,但这次的修改要考虑通用性,后台开发有时候根本不管你这些,关键目前系统很多页面都已经出现这问题了)

2.弹框采用absolute定位后,关键是top值的确定

    var initTopH = function() {
        var tempH = $('#pop').height(); //弹框高度
var screenH = $(window).height();//手机屏幕高度
var scrollH = $(document).scrollTop();//文档内容滚动高度
var topH = scrollH + (screenH - tempH) / 2;//top值高度
return topH;
};

3.以为这样就可以解决问题,但新的问题出现,当输入框获得焦点时,移动端会弹出键盘挤压弹框上移,关闭键盘后,弹框不会恢复原位,所以需要对弹框失焦后在进行重新定位执行initTopH()

  $("#pop input,textarea").off('blur').on('blur', function() {
//这里只是对input和textarea处理
$('#pop').css({'top':initTopH()});
});

4.  要成功解决一个问题,就会引发更多的问题需要解决,成功操作1-3的操作后,当弹框弹出后,若页面存在滚动条,此时滚动页面,弹框是不会跟着页面下移的,因为top是写死的。想当然是监听页面滚动(scroll)事件,实时改变top值,但问题是效果太差,抖动、弹跳太明显,qa肯定会提bug的~

另一途径就是弹出弹框后禁止页面滚动,以为设置body页面overflow:hidden就好了,然而pc端模拟测试有效果,真实环境仍然不起作用。以为没有给body定高,就都设置html,body标签的高度为100%;但然并卵,反而出现  $(document).scrollTop() 取值有问题(用$('body').scrollTop()替换仍没用,关键pc端模拟都有效果,一到真实环境就出问题),影响前面弹框定位。烦~烦~烦~,反复测试,都没有实质性的进展~

前面一直纠结于给body定高,但想想还是不妥,很多页面开发者给各自页面都会重新定义样式,我这么暴力地修改,担心影响其他页面布局,所以果断放弃这条路子~

如何在不影响大局的情况下重新布局呢?突然想到了阻止默认事件  e.preventDefault() ,但是新问题又来了,使用这个可以很好的解决页面滚动问题,但也会阻止弹框里内容滚动。纠结ing~

5.左思右想,采取整体除去局部的思想来监听touchmove事件,方法如下,当触摸对象不是弹框时,阻止默认事件,当触摸对象是弹框时,虽然滚动弹框里的内容出现底部页面也滚动的情况,但触摸结束以后恢复原始的滚动高度,经测试效果还不错,也不觉得突兀~

          $('#pop').show();
        var sh;//记录初始滚动高度
$(document).off('touchstart').on('touchstart', function(e) {
sh = $(document).scrollTop();
});
$(document).off('touchmove').on('touchmove', function(e) {
if (e.target.id === "shadow") {//除去#pop
e.preventDefault();
}
});
$(document).off('touchend').on('touchend', function(e) {
$(document).scrollTop(sh);
});

总结:虽然可能会有更好的解决方案,但这是我目前觉得比较好的处理方式,每个人所处的开发环境不一样,考虑的东西也不同,所以此方法并不一定都适应,可以借鉴参考。一天都在解决这个bug问题,找资料,尝试各种方法,虽然问题已解决,但还是想好好理顺下思路,故写下这篇随笔~啦~啦~啦~啦,下班啦~

上一篇:view添加毛玻璃效果两种方法


下一篇:信息学奥赛一本通1000(入门测试题目)