安卓ios开发问题-安全边距

js 复制代码
  override func viewDidLayoutSubviews() {
    webView.frame = self.view.bounds
  }

关键发现 :iOS项目中WebView使用的是 self.view.bounds ,这意味着WebView占据了整个视图控制器的边界, 包括安全区域 。

H5项目中的安全区域处理

js 复制代码
.app {
  height: 100vh;
  display: flex;
  flex-direction: column;
  padding-top: constant(safe-area-inset-top);
  padding-top: env(safe-area-inset-top);
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}

.bottom {
  flex: 0;
  border-top: solid 1px var(--adm-color-border);
  background-color: #fff;
  position: relative;
  z-index: 1;
  
  /* 添加底部安全区域适配 */
  padding-bottom: env(safe-area-inset-bottom);
  padding-bottom: constant(safe-area-inset-bottom);
}

问题根源

底部留有距离的原因是 双重安全区域处理 :

  1. iOS层面 :WebView已经占据了包含安全区域的完整视图边界
  2. H5层面 :CSS又额外添加了安全区域的padding 这导致在有Home Indicator的iPhone设备上,底部会有双倍的安全区域间距。

iPhone Safe Area 安全区域适配解决方案

问题描述

iPhone X 系列及更新设备引入了"刘海"和底部"Home Indicator",导致网页内容可能被遮挡或与底部留有过大间距。

解决方案概述

1. iOS 原生项目修改

文件 : t-ios/t/ViewController.swift

修改内容:

  • 使用 Auto Layout 约束替代手动设置 frame
  • WebView 顶部适配到 safeAreaLayoutGuide
  • 底部延伸到屏幕底部,由 H5 页面处理安全区域
swift 复制代码
// 设置 WebView 约束,确保适配安全区域
webView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
  webView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
  webView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
  webView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
  webView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
])

2. H5 项目全局配置

文件 : t1-h5/.umirc.ts

Viewport 配置:

javascript 复制代码
metas: [
  {
    name: 'viewport',
    content: 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover',
  },
]

关键 : viewport-fit=cover 确保页面延伸到屏幕边缘。

3. CSS 安全区域变量

文件 : t1-h5/src/less/index.less

css 复制代码
:root {
  --safe-area-inset-top: constant(safe-area-inset-top);
  --safe-area-inset-right: constant(safe-area-inset-right);
  --safe-area-inset-bottom: constant(safe-area-inset-bottom);
  --safe-area-inset-left: constant(safe-area-inset-left);
  
  // 支持新语法
  --safe-area-inset-top: env(safe-area-inset-top);
  --safe-area-inset-right: env(safe-area-inset-right);
  --safe-area-inset-bottom: env(safe-area-inset-bottom);
  --safe-area-inset-left: env(safe-area-inset-left);
}

4. 布局组件适配

文件 : t1-h5/src/layouts/layout.less

css 复制代码
.bottom {
  // 为底部 TabBar 添加安全区域适配
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}

5. 固定定位元素适配

对于使用 position: fixed 的底部元素,统一添加安全区域适配:

css 复制代码
.fixedBottomElement {
  position: fixed;
  bottom: 0;
  padding-bottom: calc(16px + constant(safe-area-inset-bottom));
  padding-bottom: calc(16px + env(safe-area-inset-bottom));
}

工具类使用

文件 : t1-h5/src/utils/safeArea.ts

typescript 复制代码
import { useSafeArea } from '@/utils/safeArea';

// 在组件中使用
const { hasBottomInset, safeAreaInsets } = useSafeArea();

// 动态应用安全区域样式
const elementRef = useRef<HTMLDivElement>(null);
useEffect(() => {
  if (elementRef.current) {
    applySafeAreaStyles(elementRef.current, { bottom: true });
  }
}, []);

适配原则

  1. iOS 原生层面: WebView 顶部适配安全区域,底部延伸到屏幕底部
  2. H5 全局层面: 使用 CSS 环境变量定义安全区域
  3. 组件层面: 固定定位的底部元素添加安全区域 padding
  4. 通用性: 提供工具类便于新组件快速适配

测试验证

在以下设备上验证效果:

  • iPhone X/XS/XR 系列
  • iPhone 11 系列
  • iPhone 12/13/14/15 系列
  • iPad Pro (Face ID)

注意事项

  1. 使用 constant()env() 双重声明确保兼容性
  2. 对于固定定位元素,使用 calc() 函数叠加原有 padding
  3. 避免在全局容器上直接添加安全区域 padding,应在具体组件上处理
  4. 横屏模式下左右安全区域也需要考虑适配

影响范围

✅ 已适配的页面/组件:

  • 底部导航栏 (TabBar)
  • 拍照结果页面 (PicResult)
  • 分析结果页面 (AnalysisResult)
  • 订正详情页面 (CorrectionDetail)
  • 关于页面 (About)
  • 评分页面 (Grading)
  • 作业批改页面 (HomeworkGrading)

📝 需要继续关注的页面:

  • 其他包含固定定位元素的页面
  • 弹窗组件的安全区域适配
  • 横屏页面的左右安全区域适配
相关推荐
宁静_致远3 分钟前
React 性能优化:深入理解 useMemo 、useCallback 和 memo
前端·react.js·面试
旺仔牛仔QQ糖4 分钟前
项目中TypeScript 编译器的工作流程
前端·typescript
coding丨4 分钟前
自制微信小程序popover菜单,气泡悬浮弹窗
前端·javascript·vue.js
anyup12 分钟前
10000+ 个点位轻松展示,使用 Leaflet 实现地图海量标记点聚类
前端·数据可视化·cursor
林太白14 分钟前
Rust认识安装
前端·后端·rust
掘金酱15 分钟前
🔥 稀土掘金 x Trae 夏日寻宝之旅火热进行ing:做任务赢大疆pocket3、Apple watch等丰富大礼
前端·后端·trae
1024小神15 分钟前
tauri项目添加多文件下载功能,并支持下载进度回调显示在前端页面上
前端·javascript
Ace_317508877616 分钟前
义乌购拍立淘API接入指南
前端
不想说话的麋鹿22 分钟前
《NestJS 实战:RBAC 系统管理模块开发 (四)》:用户绑定
前端·后端·全栈
我是谁谁35 分钟前
JavaScript 中的 Map、WeakMap、Set 详解
前端