iOS 使用 Objective-C 适配刘海屏与灵动岛 UI 完整示例

552 阅读4分钟

随着 iPhone 手机的设备设计逐渐变更,刘海屏和灵动岛(Dynamic Island)成为了重要的 UI 适配需求。为了保证应用在这些设备上的良好用户体验,我们IOS的开发者需要在应用中进行相应的适配。

本文将详细介绍如何在 iOS 应用中使用 Objective-C 适配刘海屏与灵动岛,包括如何调整视图布局、处理安全区域(safe area)等关键要点。

适配设备

  1. 刘海屏(Notch) :主要指 iPhone X 及之后的设备,顶部有一个“刘海”区域,用于放置前置摄像头和传感器。
  2. 灵动岛(Dynamic Island) :自 iPhone 14 Pro 起引入,屏幕顶部有一个动态变化的交互区域,取代了传统的刘海区域。

在这两种设备上,开发者需要特别处理顶部视图与内容区域的适配,确保 UI 不会被遮挡,并且能够兼容不同的屏幕形态。

适配步骤

一、获取设备状态

首先,我们需要检查设备是否为刘海屏或灵动岛设备。可以使用 hasNotchisDynamicIsland 来判断当前设备的屏幕类型。


#import <UIKit/UIKit.h>

@interface DeviceHelper : NSObject

+ (BOOL)hasNotch;
+ (BOOL)isDynamicIsland;

@end

@implementation DeviceHelper

// 判断是否为刘海屏(iPhone X及以后)
+ (BOOL)hasNotch {
    if (@available(iOS 11.0, *)) {
        UIWindow *window = [UIApplication sharedApplication].windows.firstObject;
        return window.safeAreaInsets.top > 20.0;
    }
    return NO;
}

// 判断是否为灵动岛设备(iPhone 14 Pro及以后)
+ (BOOL)isDynamicIsland {
    if (@available(iOS 16.0, *)) {
        return [self hasNotch] && [UIScreen mainScreen].nativeBounds.size.height > 2000; // 具体尺寸可以根据实际设备调整
    }
    return NO;
}

@end

二、处理安全区域(Safe Area)

在刘海屏和灵动岛设备上,视图的顶部、底部、左右两侧都有可能被遮挡。为了避免视图内容被刘海、灵动岛或者设备底部的 Home Bar 遮挡,我们可以使用 安全区域(Safe Area)来布局。

获取和设置安全区域:

// 获取当前设备的安全区域
UIEdgeInsets safeAreaInsets = self.view.safeAreaInsets;

// 设置视图的顶部间距(避开刘海或灵动岛区域)
CGFloat topMargin = safeAreaInsets.top;
CGFloat bottomMargin = safeAreaInsets.bottom;

// 设置视图布局
CGRect frame = CGRectMake(0, topMargin, self.view.bounds.size.width, self.view.bounds.size.height - topMargin - bottomMargin);

使用自动布局(Auto Layout)适配安全区域:

// 使用Auto Layout设置顶部视图(例如:UILabel)
UILabel *titleLabel = [[UILabel alloc] init];
titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:titleLabel];

// 设置约束
[NSLayoutConstraint activateConstraints:@[
    [titleLabel.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
    [titleLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20],
    [titleLabel.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-20]
]];

三、处理灵动岛(Dynamic Island)

灵动岛是一个动态区域,可能显示多种信息,开发者在进行 UI 布局时,需要考虑该区域的高度。可以通过获取安全区域的顶部间距来动态调整视图。

判断设备类型并动态调整视图布局:

if ([DeviceHelper isDynamicIsland]) {
    // 如果是灵动岛设备,灵动岛区域有较大的动态显示空间
    // 获取灵动岛的动态区域高度
    CGFloat dynamicIslandHeight = 30.0; // 根据设备模型动态调整
    // 设置顶部视图间距
    CGRect frame = CGRectMake(0, dynamicIslandHeight, self.view.bounds.size.width, self.view.bounds.size.height - dynamicIslandHeight);
    self.view.frame = frame;
}

使用灵动岛时的适配建议:

  • 避免直接覆盖灵动岛区域:确保视图内容不会直接覆盖灵动岛区域,可以通过调整顶部视图的位置来避开。
  • 使用动画优化体验:灵动岛区域具有动态变化,因此可以利用动画使得 UI 在灵动岛状态下变化更为平滑和自然。

适配技巧与优化

1. 在不同设备上自适应布局

为了确保布局在不同屏幕尺寸和屏幕类型的设备上都能良好显示,可以使用 Auto Layout(自动布局)进行适配。通过 safeAreaLayoutGuide 和设置 priority,可以确保视图自适应。

2. 动态调整视图区域

使用动态计算视图位置的方式,确保视图不会被刘海或者灵动岛区域遮挡。例如:

CGFloat topMargin = self.view.safeAreaInsets.top;
CGFloat dynamicIslandHeight = 0.0;

if ([DeviceHelper isDynamicIsland]) {
    dynamicIslandHeight = 30.0; // 灵动岛设备的动态区域高度
}

// 计算视图的顶部位置
CGRect newFrame = CGRectMake(0, topMargin + dynamicIslandHeight, self.view.bounds.size.width, self.view.bounds.size.height - topMargin - dynamicIslandHeight);

3. 注意屏幕旋转适配

刘海屏和灵动岛设备的适配不仅仅是横屏和竖屏的切换,还要处理屏幕旋转时的布局变化。确保在 viewWillTransitionToSize: 中重新计算视图的安全区域。

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    
    // 更新视图布局,重新计算安全区域
    [self updateLayoutForNewOrientation];
}

- (void)updateLayoutForNewOrientation {
    CGFloat topMargin = self.view.safeAreaInsets.top;
    // 重新设置视图的顶部间距
}

最后

本文张介绍了如何在 iOS 中使用 Objective-C 适配刘海屏与灵动岛设备。通过使用安全区域和动态计算布局,开发者可以确保应用的 UI 在这些设备上显示良好,避免内容被刘海或灵动岛区域遮挡。

对于支持刘海屏、灵动岛的设备,建议使用 Auto LayoutsafeAreaInsets 来处理视图布局,同时要注意动态调整视图位置,以提供最佳的用户体验。

如有说错的地方,烦请大家指正,一起进步~