H5内嵌开发的兼容问题

1,051 阅读1分钟

1. 刘海屏(安全区域)

  • IOS 使用CSS函数

    const density = window.innerWidth / window.screen.width; // 密度;IphoneX为2    
    document.body.style.paddingTop = `${density * 44}px`;    
    document.body.style.paddingTop = `calc(${density}*constant(safe-area-inset-top))`;    
    document.body.style.paddingTop = `calc(${density}*env(safe-area-inset-top))`;    /* 适配底部小黑条 */    
    document.body.style.paddingBottom = 0;    
    document.body.style.paddingBottom = `calc(${density}*constant(safe-area-inset-bottom))`;    
    document.body.style.paddingBottom = `calc(${density}*env(safe-area-inset-bottom))`;
    

另外IOS的安全区域除了受设备本身型号影响。还受webview的范围影响。

如果webview提供了NavBar ,则获取到的顶部安全区域为设备的安全区域 + NavBar的高度。

如果提供了TabBar, 则获取到的底部安全区域为设备的安全区域 + TabBar的高度。

注意:

如果使用webView加载单页面应用时,路由切换时如果需要切换隐藏或者显示NavBar或者TabBar, 需要注意安全区域的变换。

  • Android通过jsBridge中获取安全区域的top,bottom,left,right

    getSafeArea().then((result) => {  // 获取安全区域高度
       const { top, bottom, left, right } = result;  
       const isAndroid = new RegExp('\\bAndroid|\\bAdr', 'i').test(window.navigator.userAgent);  
       document.body.style.boxSizing = 'border-box';  
       if (isAndroid) {    
          document.body.style.paddingTop = `${top / window.devicePixelRatio}px`;    
          document.body.style.paddingBottom = `${bottom / window.devicePixelRatio}px`;    
          document.body.style.paddingLeft = `${left / window.devicePixelRatio}px`;    
          document.body.style.paddingRight = `${right / window.devicePixelRatio}px`;  
       }
    })
    

2. 搜索框对应的键盘文字

  • Android

    <input type="search" />

  • IOS (action不能省略)

    <form action="">
       <input type="search" />
    </form>
    

3. 返回按钮(goBack)

  • Andorid

    history.goBack(); // 和Android的返回按钮一致

  • IOS

自定义路由

// 监听路由变化
const history = createHashHistory();
history.listen((location) => {  
   const { state: { type } = {} } = location;  
   let historyList = JSON.parse(localStorage.getItem('history'));  
   if (!historyList || historyList.length === 0) {    
      historyList = ['/'];  
   }  
   if (`${historyList[historyList.length - 1]}` !== location.pathname) {    
       if (type === 'replace') {      
         return;    
       }    
       localStorage.setItem('history', JSON.stringify(historyList.concat(location.pathname)));  
    }
});

自定义返回方法

// 自定义实现history.goBack()
function onClickBack(history, onBack) {  
   const isIPhone = new RegExp('\\biPhone\\b|\\biPod\\b', 'i').test(window.navigator.userAgent);  
   if (isIPhone) {    
       if (onBack) {      
           onBack();    
        } else {      
            const historyList = JSON.parse(localStorage.getItem('history'));      
            const { length } = historyList || [];      
            localStorage.setItem('history', JSON.stringify(historyList.slice(0, length - 2)));      
            if (length < 2) {        
                localStorage.setItem('history', JSON.stringify(null));      
            }      
            history.push({ 
                pathname: `${historyList[length - 2] || '/'}`, 
                state: 'back' 
            });    
       }  
  } else { // Android使用history处理    
     history.goBack();  
  }
}

4. 图片的展示问题

在Andorid和IOS的webview中img标签展示存在样式兼容问题。为了统一,需要给img标签设置具体的宽高值。

  • Android

<img/>标签没有任何属性的时候,默认按照width:auto显示,图片尺寸超出屏幕范围,显示异常。

解决办法:

在Android的webview中必须设置img元素的尺寸

  • IOS

IOS中默认显示图片的原有尺寸。