安卓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)

📝 需要继续关注的页面:

  • 其他包含固定定位元素的页面
  • 弹窗组件的安全区域适配
  • 横屏页面的左右安全区域适配
相关推荐
芒果1252 分钟前
【转载文章】ECharts-GL 实现世界级、国家级、省市级 3D 地图
前端
一只小风华~12 分钟前
JavaScript:数组常用操作方法的总结表格
前端·javascript·数据结构·vue.js·算法
前端老鹰16 分钟前
JavaScript Array.prototype.some ():数组判断的 “快捷侦探”
前端·javascript
张元清17 分钟前
揭秘JS事件循环:一道字节跳动面试题带你深入理解async/await、Promise与RAF
前端·react.js·面试
KenXu21 分钟前
F2C-Chrome插件-Figma免费的DevMode来了!
前端
北海几经夏27 分钟前
React组件中的this指向问题
前端·react.js
passer98139 分钟前
列表项切换时同步到可视区域
前端
FogLetter41 分钟前
移动端适配的终极奥义:从lib-flexible到postcss-pxtorem的全方位指南
前端·postcss
易元42 分钟前
设计模式-访问者模式
前端·后端·设计模式
兵临天下api42 分钟前
Elasticsearch 查询性能优化:从 3 秒到 300ms 的 6 个核心参数调优指南
前端