H5运行环境判断、适配app全屏模式

618 阅读2分钟

前言

app环境有状态栏和导航栏,需要独立适配

一、判断是处于APP环境

判断系统环境

const terminals = {
    // IOS系列
    ios: /iPad|iPhone|iPod/i,
    // 安卓系统
    android: /Android/i,
    // windows系统
    windows: /windows|win32|win64/i,
    // mac系统
    mac: /macintosh|mac os x/i
}

export const getTerminal = () => {
    // 判断undefined主要是因为链式调用在快应用等三方小程序会报错
    const ua = typeof navigator !== 'undefined' ? navigator?.userAgent?.toLowerCase() || '' : ''
    return Object.keys(terminals).find((key) => terminals[key] && terminals[key].test(ua)) || ''
}

判断运行环境

const runenvs = {
// 微信
weixin: (ua: string) => /MicroMessenger/i.test(ua),
// 淘宝
tbapp: (ua: string) => /Taobao/i.test(ua),
// 支付宝,支付宝还需考虑UC和夸克
alipay: (ua: string) => /AlipayClient|AliApp/i.test(ua),
// 华为
hwapp: (ua: string) => /.*hap\/(\d|\.)+\/huawei.*/i.test(ua),
// 快应用
quickapp: (ua: string) => /.*hap\/(\d|\.)+\/.*/i.test(ua),
// 百度
baidu: (ua: string) => /baidu/i.test(ua),
// 头条
toutiao: (ua: string) => /newsarticle/i.test(ua),
// QQ
qq: (ua: string) => /qq/i.test(ua)
}

export const getRunEnv = () => {
    // 判断undefined主要是因为链式调用在快应用等三方小程序会报错
    const ua = typeof navigator !== 'undefined' ? navigator?.userAgent?.toLowerCase() || '' : ''
    return Object.keys(runenvs).find((key) => runenvs[key] && runenvs[key](ua)) || 'browser'
}

判断webview环境

const webviews = {
    // 微信小程序
    wxapp: (ua: string) => /Micromessenger/i.test(ua) && /miniProgram/i.test(ua),
    // 微信
    weixin: (ua: string) => /Micromessenger/i.test(ua) && !/miniProgram/i.test(ua),
    // 支付宝小程序
    aliapp: (ua: string) => /AlipayClient/i.test(ua) && ua.includes('miniprogram'),
    // 支付宝生活号
    alilife: (ua: string) => /AlipayClient|AliApp/i.test(ua) && /alipay-proxy/i.test(ua),
    // 支付宝
    alipay: (ua: string) => /AlipayClient|AliApp/i.test(ua) && !ua.includes('miniprogram') && !/alipay-proxy/i.test(ua),
    // 百度小程序
    bdapp: (ua: string) => typeof window !== 'undefined' && (/swan\//.test(ua) || /^webswan-/.test(window?.name || '')),
    // 百度
    baidu: (ua: string) => /baidu/i.test(ua) && !/swan\//.test(ua) && !/^webswan-/.test(window?.name || ''),
    // 头条小程序
    ttapp: (ua: string) => ua.includes('toutiaomicroapp'),
    // 头条
    toutiao: (ua: string) => /newsarticle/i.test(ua) && !ua.includes('toutiaomicroapp'),
    // qq小程序
    qqapp: (ua: string) => /qq/i.test(ua) && ua.includes('miniprogram'),
    // QQ
    qq: (ua: string) => /qq/i.test(ua) && !ua.includes('miniprogram'),
    // 华为快应用
    hwapp: (ua: string) => /.*hap\/(\d|\.)+\/huawei.*/i.test(ua),
    // 快应用
    quickapp: (ua: string) => /.*hap\/(\d|\.)+\/.*/i.test(ua)
}

export const getWebview = () => {
    // 判断undefined主要是因为链式调用在快应用等三方小程序会报错
    const ua = typeof navigator !== 'undefined' ? 
                 navigator?.userAgent?.toLowerCase() || '' : ''
    return Object.keys(webviews).find((key) => webviews[key] && webviews[key](ua)) || ''

}

二、设置APP全屏模式

import { appNavigator } from 'syttunnel'

// 设置title
export const setAppTitle = (title) => {
    appNavigator.setNavigatorTitle({
        title
    })}

// 设置导航栏样式
export const setNavigatorStyle = (param: INavigatorStyle) => {
    appNavigator.setNavigatorStyle({
        ...param
    })
}

// 设置App全屏模式
export const setAppFullScreenMode = () => {
    setNavigatorStyle({
        rightTextStyle: {
            // 右边的返回按钮隐藏
            display: 'none'
        },
        style: {
            // 导航栏颜色
            backgroundColor: 'transparent'
        },
        rightItemDisable: true, // 右边关闭按钮禁用
        // 导航栏标题
        title: '',
        contentMode: 'fullScreen' // 全屏模式
    })
}

三、设置APP环境头部高度

计算app的webview头部高度

import { appNavigator } from 'syttunnel'

// 获取导航栏和状态栏高度
export const getNavigatorFrame = () => appNavigator.getNavigatorFrame()

// 设置app环境头部的高度
const [appTopHeight, setAppTopHeight] = useState<number>()

// 获取并设置APP webview情况下头部样式
const setAppHeaderHeight = async () => {
    const height = await getNavigatorFrame()
    const { navigationBar, statusbar } = height
    const { clientWidth, clientHeight } = document.documentElement // 设备宽度,高度
    const appTopHeightCalc = clientWidth / clientHeight < 0.75 ?
               navigationBar.height + statusbar.height : 
               statusbar.height // 折叠屏展开时不导航在白屏两侧
        setAppTopHeight(appTopHeightCalc)
}

页面最外层元素样式设置paddingTop属性

<div style={{ paddingTop: `${appTopHeight}px` }}>
 ...
</div>