iOS屏幕适配方案

iOS屏幕适配方案及场景案例

文档说明

本文档汇总iOS开发全场景屏幕适配方案,覆盖AutoLayout、SizeClass、百分比适配、字体/图片适配、刘海屏/灵动岛适配、多设备兼容等核心内容,搭配实战代码案例,适配iPhone全机型(SE/标准版/ProMax/Plus)、iPad全系列,解决横竖屏切换、异形屏、多分辨率适配问题,无第三方依赖,原生API实现,兼容iOS 13+主流版本。

一、iOS屏幕适配核心基础

1.1 核心概念

点(pt):iOS开发通用尺寸单位,与屏幕像素(px)无关,系统自动适配像素密度,1pt = 2px/3px(根据设备倍率)。

安全区域(Safe Area):避开刘海、状态栏、导航栏、底部指示条、键盘的可视区域,是适配异形屏的核心。

SizeClass:iOS设备屏幕尺寸分类方案,分为紧凑(Compact)、常规(Regular)两种尺寸类型,兼容iPhone/iPad横竖屏、分屏模式。

1.2 主流适配方案选型

  • AutoLayout(自动布局):苹果官方推荐,纯代码/XIB/Storyboard均可实现,适配绝大多数场景

  • SizeClass:配合AutoLayout,实现多设备、横竖屏差异化布局

  • 百分比/比例适配:针对全屏布局、等比控件、轮播图等场景

  • 手动计算frame:小众定制化布局、自定义UI控件场景

  • 自动缩放适配:针对老项目、全屏UI快速适配


二、AutoLayout自动布局(核心方案)

2.1 纯代码实现(SnapKit/原生NSLayoutConstraint)

优先使用原生API,无第三方依赖;复杂布局推荐SnapKit简化代码,以下为两种实现方式,均贴合安全区域适配。

2.1.1 原生NSLayoutConstraint适配

import UIKit

class AutoLayoutViewController: UIViewController {

// 声明控件

private let contentView = UIView()

private let testLabel = UILabel()

复制代码
override func viewDidLoad() {
    super.viewDidLoad()
    setupUI()
}

private func setupUI() {
    view.backgroundColor = .white
    // 关闭AutoresizingMask
    contentView.translatesAutoresizingMaskIntoConstraints = false
    testLabel.translatesAutoresizingMaskIntoConstraints = false
    
    view.addSubview(contentView)
    contentView.addSubview(testLabel)
    
    // 配置控件属性
    testLabel.text = "iOS屏幕适配示例"
    testLabel.textAlignment = .center
    testLabel.backgroundColor = .lightGray
    
    // 约束布局:贴合安全区域
    NSLayoutConstraint.activate([
        // contentView铺满安全区域
        contentView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
        contentView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
        contentView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
        contentView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
        
        // label居中,左右留白20pt,高度固定
        testLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
        testLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
        testLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
        testLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
        testLabel.heightAnchor.constraint(equalToConstant: 50)
    ])
}

}

2.1.2 SnapKit实现(简化版)

import UIKit

import SnapKit

class SnapKitLayoutViewController: UIViewController {

private let contentView = UIView()

private let testLabel = UILabel()

复制代码
override func viewDidLoad() {
    super.viewDidLoad()
    setupUI()
}

private func setupUI() {
    view.backgroundColor = .white
    view.addSubview(contentView)
    contentView.addSubview(testLabel)
    
    testLabel.text = "SnapKit适配示例"
    testLabel.textAlignment = .center
    testLabel.backgroundColor = .lightGray
    
    // SnapKit约束
    contentView.snp.makeConstraints { make in
        // 绑定安全区域
        make.edges.equalTo(view.safeAreaLayoutGuide)
    }
    
    testLabel.snp.makeConstraints { make in
        make.center.equalToSuperview()
        make.leading.trailing.equalToSuperview().inset(20)
        make.height.equalTo(50)
    }
}

}

2.2 安全区域适配要点

  • 禁止控件直接贴合view边缘,必须绑定safeAreaLayoutGuide

  • 刘海屏、灵动岛、底部Home指示条,均通过安全区域自动避开

  • 横竖屏切换时,安全区域会自动适配,无需手动修改约束


三、SizeClass多设备差异化适配

解决iPhone竖屏、横屏,iPad全屏/分屏,不同尺寸设备的布局差异,通过监听SizeClass变化,动态调整约束。

3.1 SizeClass分类规则

  • iPhone竖屏:宽紧凑(C)、高常规(R)

  • iPhone横屏(全面屏):宽紧凑(C)、高紧凑(C)

  • iPad全场景:宽常规(R)、高常规(R)

3.2 代码实现差异化布局

import UIKit

class SizeClassViewController: UIViewController {

private let testView = UIView()

// 存储约束,方便动态修改

private var viewWidthConstraint: NSLayoutConstraint!

复制代码
override func viewDidLoad() {
    super.viewDidLoad()
    setupUI()
}

// 监听SizeClass变化
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    // 判断屏幕宽度类型
    if traitCollection.horizontalSizeClass == .compact {
        // 紧凑宽度:iPhone竖屏/横屏
        viewWidthConstraint.constant = UIScreen.main.bounds.width - 40
    } else {
        // 常规宽度:iPad
        viewWidthConstraint.constant = 500
    }
}

private func setupUI() {
    view.backgroundColor = .white
    testView.translatesAutoresizingMaskIntoConstraints = false
    testView.backgroundColor = .systemBlue
    view.addSubview(testView)
    
    // 初始化约束
    viewWidthConstraint = testView.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width - 40)
    
    NSLayoutConstraint.activate([
        testView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        testView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        testView.heightAnchor.constraint(equalToConstant: 200),
        viewWidthConstraint
    ])
}

}


四、百分比/比例适配(实战场景)

针对等比例控件、全屏布局、流式布局、轮播图等场景,通过屏幕宽度/高度百分比计算尺寸,适配所有机型分辨率。

4.1 基础百分比工具类

import UIKit

// MARK: - 屏幕适配工具类

struct ScreenAdaptationUtil {

// 屏幕宽度

static let screenWidth = UIScreen.main.bounds.width

// 屏幕高度

static let screenHeight = UIScreen.main.bounds.height

// 基准宽度(以iPhone 15 Pro宽度393pt为基准)

private static let baseWidth: CGFloat = 393

复制代码
/// 宽度百分比适配
static func widthPercent(_ percent: CGFloat) -> CGFloat {
    return screenWidth * percent
}

/// 高度百分比适配
static func heightPercent(_ percent: CGFloat) -> CGFloat {
    return screenHeight * percent
}

/// 等比缩放(基于基准宽度)
static func scale(_ value: CGFloat) -> CGFloat {
    return value * (screenWidth / baseWidth)
}

}

4.2 实战场景:流式布局+百分比控件

import UIKit

class PercentLayoutViewController: UIViewController {

override func viewDidLoad() {

super.viewDidLoad()

setupPercentLayout()

}

复制代码
private func setupPercentLayout() {
    view.backgroundColor = .white
    
    // 一行两个控件,各占45%屏幕宽度,间距10%
    let leftView = UIView(frame: CGRectMake(
        ScreenAdaptationUtil.widthPercent(0.05),
        ScreenAdaptationUtil.heightPercent(0.2),
        ScreenAdaptationUtil.widthPercent(0.4),
        ScreenAdaptationUtil.heightPercent(0.3)
    ))
    leftView.backgroundColor = .systemRed
    
    let rightView = UIView(frame: CGRectMake(
        ScreenAdaptationUtil.widthPercent(0.55),
        ScreenAdaptationUtil.heightPercent(0.2),
        ScreenAdaptationUtil.widthPercent(0.4),
        ScreenAdaptationUtil.heightPercent(0.3)
    ))
    rightView.backgroundColor = .systemGreen
    
    view.addSubview(leftView)
    view.addSubview(rightView)
}

}


五、字体&图片适配

5.1 字体自动适配

支持动态字体、机型差异化字体大小,兼顾无障碍适配与多设备兼容。

import UIKit

extension UIFont {

// 自适应字体

static func adaptiveFont(size: CGFloat, weight: UIFont.Weight = .regular) -> UIFont {

// 屏幕缩放字体大小

let scaleSize = size * (UIScreen.main.bounds.width / 393)

return UIFont.systemFont(ofSize: scaleSize, weight: weight)

}

复制代码
// 动态字体(支持系统字体大小设置)
static func dynamicFont(style: UIFont.TextStyle) -> UIFont {
    if #available(iOS 15.0, *) {
        return UIFont.preferredFont(forTextStyle: style, compatibleWith: .current)
    } else {
        return UIFont.preferredFont(forTextStyle: style)
    }
}

}

// 使用示例

// label.font = .adaptiveFont(size: 16)

// label.font = .dynamicFont(style: .body)

5.2 图片适配

  • 图片资源配置@2x/@3x图,系统自动加载对应分辨率图片

  • 图片控件设置contentMode,避免拉伸变形:

// 常用图片填充模式

imageView.contentMode = .scaleAspectFit // 等比缩放,完整显示

imageView.contentMode = .scaleAspectFill // 等比缩放,填充控件,裁剪多余部分

imageView.clipsToBounds = true // 开启裁剪


六、异形屏/特殊场景适配

6.1 刘海屏/灵动岛/底部指示条适配

// 获取安全区域边距

let safeTop = UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0

let safeBottom = UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0

// 自定义导航栏/底部按钮,避开安全区域

customNavView.frame = CGRectMake(0, safeTop, ScreenAdaptationUtil.screenWidth, 44)

customBottomBtn.frame = CGRectMake(20, ScreenAdaptationUtil.screenHeight - safeBottom - 50, ScreenAdaptationUtil.screenWidth - 40, 50)

6.2 横竖屏切换适配

  1. 开启项目横竖屏权限

  2. 通过viewWillLayoutSubviews监听屏幕旋转,刷新约束

override func viewWillLayoutSubviews() {

super.viewWillLayoutSubviews()

// 屏幕旋转后,重新更新约束/frame

testView.snp.updateConstraints { make in

make.height.equalTo(ScreenAdaptationUtil.heightPercent(0.25))

}

}

6.3 iPad分屏/多任务适配

全程使用AutoLayout+SizeClass,避免固定frame,不写死屏幕尺寸,所有尺寸通过比例/约束实现,即可兼容iPad分屏模式。


七、常见适配避坑指南

  • ✅ 优先使用安全区域,禁止直接使用view边缘约束

  • ✅ 不使用固定frame,优先AutoLayout/SnapKit约束

  • ✅ 字体/控件尺寸不写死数值,使用比例/自适应方法

  • ✅ 横屏适配需重新计算布局,避免控件超出屏幕

  • ✅ 图片避免拉伸,合理设置contentMode

  • ✅ 刘海屏机型不忽略底部安全区域,防止按钮被遮挡


八、接入使用说明

  1. 基础布局优先使用AutoLayout+安全区域,适配绝大多数场景

  2. 多设备兼容引入SizeClass,实现横竖屏、iPhone/iPad差异化布局

  3. 流式/等比布局使用百分比适配方案,引入工具类简化代码

  4. 字体图片使用自适应扩展,兼顾显示效果与兼容性

  5. 异形屏重点处理安全区域,避开刘海、底部指示条

相关推荐
终端安全笔记7 小时前
描述文件、企业证书、MDM 不是三个名字,是三层
android·ios·智能手机
传奇开心果编程8 小时前
【SwiftUI入门练中学】第1课 从零开始
学习·ui·ios·swiftui·swift
丿Wayne14 小时前
iOS Token 刷新实战(Actor 避免并发重复刷新)
ios·swift·token·actor·swift并发
终端安全笔记1 天前
iOS 27 给了租赁一个新工具,但它只认受监督的设备
android·网络·安全·ios
大熊猫侯佩1 天前
独立 App 首发完成 iPhone Duo 展开态适配
ios·swiftui·swift
光影少年1 天前
setImmediate 和 setTimeout(0) 的区别
android·前端·react.js·ios·前端框架
2501_916008891 天前
SSE 和 gRPC 流式接口如何抓包,调试 SSE 与 gRPC 流式接口
网络协议·计算机网络·网络安全·ios·adb·https·udp
HouWan2 天前
Flutter: MediaQuery.of(context) 为什么可能拖慢页面?
android·flutter·ios
用户38034165882972 天前
Broadcast Extension 里的 Live Activity:一次跨进程妥协
ios·音视频开发
匠测AI说2 天前
XCUITest 自动化全解:同进程白盒、XCTest 架构、自动同步机制与 iOS 端选型指南
测试工具·ios·自动化