You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求更优手机刘海屏检测方案:现有iOS检测方法偶现失效

核心问题定位

你现有代码存在两个致命缺陷,是概率性检测失效的根本原因:

  • 异步返回值丢失:setTimeout回调内的return不会作为hasNotch函数的返回值,直接调用hasNotch()拿到的永远是undefined,赋值给$rootScope.hasNotch后控制器判断undefined == true自然为false,只有极偶然的时序巧合下才能碰对结果,刚好对应你说的20%成功率的情况。
  • 固定100ms延迟不可靠:不同设备DOM渲染速度差异极大,固定延迟无法保证样式计算完成。

修复现有JS检测逻辑

第一步:改造hasNotch为异步Promise函数

用requestAnimationFrame代替固定延迟,保证浏览器完成样式计算后再取值,同时用Promise处理异步返回:

function hasNotch() {
  return new Promise((resolve) => {
    if (!CSS.supports('padding-bottom: env(safe-area-inset-bottom)')) {
      errMgmt("preIndex/hasNotch ",101.3,"READY: Notch Not Supported") ;
      return resolve(false);
    }
    const div = document.createElement('div');
    // 给检测元素加固定定位,避免受页面其他样式影响
    div.style.cssText = 'padding-bottom: env(safe-area-inset-bottom); position: fixed; left: 0; bottom: 0; z-index: -9999; visibility: hidden;';
    document.body.appendChild(div);
    // 双raf确保样式更新完成,比setTimeout可靠性高100%
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        const calculatedPadding = parseInt(window.getComputedStyle(div).paddingBottom, 10);
        document.body.removeChild(div);
        const res = calculatedPadding > 0;
        res ? errMgmt("preIndex/hasNotch ",101.1,"READY: Notch Detected") : errMgmt("preIndex/hasNotch ",101.2,"READY: Notch Not Detected");
        resolve(res);
      });
    });
  });
}

第二步:修改赋值逻辑

拿到检测结果后手动触发脏检查更新scope值:

$ionicPlatform.ready(function() {
  hasNotch().then(res => {
    $rootScope.$apply(() => {
      $rootScope.hasNotch = res;
    });
  });
  // ...其他原有逻辑
}) ;

第三步:控制器适配异步更新

因为控制器可能早于检测完成初始化,不要直接在初始化时做if判断,用$watch监听值变化:

.controller('HomeCtrl', function($rootScope,$scope,$state,$stateParams,$ionicModal,$q,apiService) {
  const unwatch = $scope.$watch('$root.hasNotch', function(newVal) {
    if (newVal === true) {
      // 执行你的css相关逻辑
      unwatch(); // 执行一次后取消监听,避免重复执行
    }
  });
}) ;

更稳定的跨平台通用适配方案

90%以上的刘海适配场景不需要JS参与,直接用CSS原生语法适配即可,完全规避时序问题,同时兼容iOS和安卓9+所有刘海设备:

/* 需要适配刘海底部的元素直接写该样式,无刘海设备env取值为0,自动降级 */
.bottom-action-bar {
  padding-bottom: calc(16px + env(safe-area-inset-bottom, 0));
}
/* 需要适配顶部刘海的元素同理 */
.top-nav-bar {
  padding-top: calc(12px + env(safe-area-inset-top, 0));
}

如果确实需要JS拿到刘海状态做业务逻辑,可以在之前的检测函数中加入安卓兜底逻辑,覆盖更低版本的安卓设备:

// 安卓厂商刘海兜底检测,可根据需求补充更多厂商适配规则
function checkAndroidNotchFallback() {
  try {
    // 安卓9+原生接口判断
    const cutout = window.document?.documentElement?.style?.displayCutout;
    if (cutout) return true;
    // 屏幕比例兜底,刘海屏设备比例大多≥19.5:9
    const screenRatio = Math.max(window.screen.height, window.screen.width) / Math.min(window.screen.height, window.screen.width);
    return screenRatio >= 1.95;
  } catch(e) {
    return false;
  }
}

内容的提问来源于stack exchange,提问作者rolinger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 10:18:02