android界面布局错位,IOS 浏览器页面布局错位(如:点不到)的分析与解决

IOS 浏览器页面布局错位(如:点不到)的分析与解决

IOS 浏览器软键盘的拉起与收缩、微信 IOS 浏览器底部导航条的显示与隐藏,很容易导致页面布局错位(相对窗体的绝对定位元素):

明明按钮在这里,却要在上面一点儿点击屏幕才能点到它

明明弹框是居中显示的,却向上偏移了很多,导致下面很多空白

明明是固定浮动在某个位置,却点不到它

1. Android 与 IOS 的差异

在 Android 中,软键盘的弹起与收缩会触发 window 对象的 resize 事件,而 IOS 不会

微信 IOS 浏览器底部导航条的显示与隐藏会触发 window 对象的 resize 事件,而 Android 中没有底部导航条

2. IOS 里的一些特性

为了达到极致的体验,IOS 浏览器很多特性是不遵循 W3C 规范的

软键盘的弹起与收缩不会触发 window 对象的 resize 事件

软键盘收缩后,固定定位的元素处于错位状态,需要滑动页面后才能刷新页面恢复到正常状态

3. 具体情况分析

不管是 IOS 浏览器软键盘的拉起与收缩,还是微信 IOS 浏览器底部导航条的显示与隐藏,都是改变的 window 窗体的大小。

微信 IOS 浏览器底部导航条的显示与隐藏跟软键盘的拉起与收缩是差不多的,但微信 IOS 浏览器底部导航条还有一个很大的特点:

在单页面应用(SPA)中,当路由发生变化时,底部导航条会一下子就显示,而这很难确定是先渲染了页面还是先显示了底部导航条,

这也很容易导致元素布局错位。

4. 怎么解决

4.1 监听键盘弹起与收缩,自动做一些操作

新建 watch-keyboard.js 脚本,引入到页面中。

当页面中键盘弹起时,body 会有 keyboard-active class,可以根据这个隐藏一些元素。

import {isIos} from '../utils';

import debounce from 'lodash/debounce';

// 初始高度

const winHeight = window.innerHeight;

// 判断是不是弹起了软键盘

const judgeDistance = 200;

if (!isIos) {

window.addEventListener(

'resize',

debounce(() => {

if (window.innerHeight < winHeight - judgeDistance) {

// 键盘弹起

document.body.classList.add('keyboard-active');

} else {

document.body.classList.remove('keyboard-active');

}

}, 300),

!1

);

}

else {

// IOS 软键盘的弹起与收缩不会触发 `window` 对象的 `resize` 事件,用定时器实现

// 保证能够滚动

document.body.style.minHeight = (winHeight + 2) + 'px';

// 上两次高度记录

let secondLastWinHeight = winHeight;

// 上一次高度记录

let lastWinHeight = winHeight;

setInterval(() => {

const newWinHeight = window.innerHeight;

// 变化结束

if (secondLastWinHeight !== lastWinHeight && lastWinHeight === newWinHeight) {

if (newWinHeight < winHeight - judgeDistance) {

// 键盘弹起

document.body.classList.add('keyboard-active');

} else {

document.body.classList.remove('keyboard-active');

// window 需要滚动一下,让页面刷新一下,否则弹框会出现错位的问题

window.scrollTo(0, window.scrollY ? window.scrollY - 1 : 1);

}

}

secondLastWinHeight = lastWinHeight;

lastWinHeight = newWinHeight;

}, 300); // 可以根据需要调整间隔时间(越小越精确)

}

4.2 监听窗体大小变化,执行一个回调,做更多操作

当软键盘弹起时,又点击了一个按钮,然后显示弹框(如:从底部向上弹出)的时候,这个时候就需要等待软键盘收起之后,IOS 刷新屏幕之后,再显示弹框。

新建 wait-for-stable-win-height.js 脚本,引入到页面中。

import { isIos } from '../utils';

/**

* 等待 window 高度不变了之后执行一个回调函数

*

* @param onComplete 完成的回调

* @param delay 延迟多少时间再判断

* @param interval 定时器间隔时间

*/

export default ({ onComplete, delay = 200, interval = 50 }) => {

setTimeout(() => {

let winHeight = window.innerHeight;

const timer = setInterval(() => {

const newWinHeight = window.innerHeight;

if (winHeight === newWinHeight) {

clearInterval(timer);

if (onComplete) {

if (!isIos) {

setTimeout(() => {

onComplete();

}, 100);

return;

}

// window 需要滚动一下,让页面刷新一下,否则弹框会出现错位的问题

window.scrollTo(0, window.scrollY ? window.scrollY - 1 : 1);

setTimeout(() => {

onComplete();

}, 200);

}

} else {

winHeight = newWinHeight;

}

}, interval);

}, delay);

};

后续

版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值