iOS小技能:适配安全区域高度 您所在的位置:网站首页 ios底部导航栏高度 iOS小技能:适配安全区域高度

iOS小技能:适配安全区域高度

2023-08-15 19:36| 来源: 网络整理| 查看: 265

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情

引言

应用场景1:自定义导航栏内容,导航栏显示公告和标题

应用场景2:自定义视图底部工具栏

应用场景3: 适配上拉加载更多控件 _vcView.tableView.mj_footer.ignoredScrollViewContentInsetBottom = k_ignoredScrollViewContentInsetBottom;

//推荐使用API获取高度 #define k_safeAreaInsetsBottom [UIApplication sharedApplication].delegate.window.safeAreaInsets.bottom #define isIphoneX isHasSafeAreaInsets #define k_ignoredScrollViewContentInsetBottom (isIphoneX?k_safeAreaInsetsBottom:0) static inline BOOL isIPhoneXSeries() { if (@available(iOS 11.0, *)) { UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window]; if (mainWindow.safeAreaInsets.bottom > 0.0) { return YES; } } return NO; } I 适配安全区域距离

The safe area of a view reflects the area not covered by navigation bars, tab bars, toolbars, and other ancestors that obscure a view controller's view. (In tvOS, the safe area reflects the area not covered by the screen's bezel.) You obtain the safe area for a view by applying the insets in this property to the view's bounds rectangle. If the view is not currently installed in a view hierarchy, or is not yet visible onscreen, the edge insets in this property are 0.

safeArea是指没有被导航栏, tabbar栏, toolbars, 或其他视图遮盖的区域。

通过safeAreaInsets属性可以获取到视图的安全距离. 但是如果一个view没有在视图层次结构中或未在屏幕上显示, 则safeAreaInsets为0;

1.1 问题

视图底部工具栏显示到安全区域之外

1.2 判断安全区域距离 #define isIphoneX [QCT_Common isiPhoneX] + (BOOL)isiPhoneX { if (@available(iOS 11.0, *)) { if ([UIApplication sharedApplication].delegate.window.safeAreaInsets.bottom > 0) {//iphoneX横屏 return YES; } else { return NO; } } else { return NO; } }

定义相应宏

///*状态栏和导航栏总高度*/ #define kStatusBarHeight (CGFloat)(isIphoneX?(88.0):(64.0)) /*iPhoneX的状态栏高度差值*/ #define kPtatusBarHeight (CGFloat)(isIphoneX?(24.0):(0)) /*底部安全区域远离高度*/ #define kDtatusBarHeight (CGFloat)(isIphoneX?(34.0):(0)) //推荐使用API获取高度 #define k_safeAreaInsetsBottom [UIApplication sharedApplication].delegate.window.safeAreaInsets.bottom #define isIphoneX isHasSafeAreaInsets #define k_ignoredScrollViewContentInsetBottom (isIphoneX?k_safeAreaInsetsBottom:0)

推荐使用API获取高度

#define kstatusBarH [[UIApplication sharedApplication] statusBarFrame].size.height #define knavHeight self.navigationController.navigationBar.frame.size.height //获取状态栏的高度 CGFloat statusHeight = [[UIApplication sharedApplication] statusBarFrame].size.height; NSLog(@"状态栏高度:%f",statusHeight); //获取导航栏的高度 CGFloat navHeight = self.navigationController.navigationBar.frame.size.height; NSLog(@"导航栏高度:%f",navHeight); //获取tabBar的高度 //1.在tabBarController中使用(你的继承自UITabBarController的VC) CGFloat tabBarHeight = self.tabBar.frame.size.height; NSLog(@"tabBar高度:%f",tabBarHeight); //2.在非tabBarController中使用 UITabBarController *tabBarVC = [[UITabBarController alloc] init];//(这儿取你当前tabBarVC的实例) CGFloat tabBarHeight = tabBarVC.tabBar.frame.size.height; NSLog(@"tabBar高度:%f",tabBarHeight); 1.3 使用static inline方式编译函数,防止静态分析

使用inline方式将函数在调用处强制展开,防止被hook和追踪符号。

static __attribute__((always_inline)) void anti_debug() //一般的函数调用都会通过call的方式来调用,hacker很容易对一个函数做手脚,如果是以inline的方式编译的,会把该函数的code拷贝到每次调用该函数的地方;而static会让生成的二进制文件中没有清晰的符号表,让逆向的人很难弄清楚代码逻辑

查看汇编文件: 选中xx.m文件-->Xcode 菜单 --> Product --> Perform Action --> Assemble "xx.m" 在这里插入图片描述

与#define的区别:

使用#define宏定义的代码,编译器不会对其进行参数有效性检查,仅仅只是对符号表进行替换。 #define宏定义的代码,其返回值不能被强制转换成可转换的适合的类型。

应用到本文案例

static inline BOOL isIPhoneXSeries() { if (@available(iOS 11.0, *)) { UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window]; if (mainWindow.safeAreaInsets.bottom > 0.0) { return YES; } } return NO; } II 应用场景 2.1 应用场景1:自定义导航栏

///*状态栏和导航栏总高度*/ #define kStatusBarHeight (CGFloat)(isIphoneX?(88.0):(64.0)) navView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, kWidth, kStatusBarHeight)]; 2.2 应用场景2:自定义视图底部工具栏

自定义视图底部工具栏显示到安全区域之外

如果有安全区域距离,则视图距离底部的高度进行相应调整

[_vcView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.left.right.offset(0); if(isHasSafeAreaInsets()){ UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window]; CGFloat bottom = mainWindow.safeAreaInsets.bottom; make.bottom.equalTo(weakSelf.view).offset(-bottom); }else{ make.bottom.equalTo(weakSelf.view); } }];

2.3 应用场景3: 适配上拉加载更多控件

问题:没有上拉的时候加载更多控件的文案也显示出来了

修复方式1:修改视图距离底部的高度

[self.vcView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(weakSelf.view).offset(0); make.right.equalTo(weakSelf.view).offset(- 0); make.top.equalTo(weakSelf.view).offset(0); if(isHasSafeAreaInsets()){// 避免没有上拉的时候加载更多控件的文案也显示出来了 UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window]; CGFloat bottom = mainWindow.safeAreaInsets.bottom; make.bottom.equalTo(weakSelf.view).offset(bottom); }else{ make.bottom.equalTo(weakSelf.view); } }];

修复方式2:修改上拉加载控件距离底部的高度 【推荐】

/** 忽略多少scrollView的contentInset的bottom */ //@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetBottom; UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window]; CGFloat bottom = mainWindow.safeAreaInsets.bottom;//34 _tableView.mj_footer.ignoredScrollViewContentInsetBottom = isIphoneX ? bottom : 0;

适配之后的效果

如果是第三方库建议升级最新版本,比如我把MJRefresh从3.1.16升级至3.7.5

pod 'MJRefresh' , '3.7.5' -> Installing MJRefresh 3.7.5 (was 3.1.16)


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有