zoukankan      html  css  js  c++  java
  • <iOS屏幕适配> iPhoneX SafeArea

    一. 前言

    本文的出发点是对iOS设备的适配, 我们之前的适配只是考虑设备的尺寸, 设备的方向, 而在iPhoneX出来之后呢, 我们又多了一种考量, 那就是刘海和底部横条(HomeIndicator), 我们通过UIKit11.0之后新增的API来解决这个问题, 达到不同设备尺寸, 不同设备方向的完美适配.

     

    二. 之前的做法

     

    注: 该方法只适用于设备的竖屏, 如果是横屏就会出现问题

    我们是用宏, 来解决这个问题的, 像这样:

    /** 设备屏幕宽度 */
    #define LCLScreenWidth [[UIScreen mainScreen] bounds].size.width
    
    /** 设备屏幕高度 */
    #define LCLScreenHeight [[UIScreen mainScreen] bounds].size.height
    
    /** iPhoneX判断 */
    #define LCLIsIphoneX (CGSizeEqualToSize(CGSizeMake(375.f, 812.f), [UIScreen mainScreen].bounds.size) || CGSizeEqualToSize(CGSizeMake(812.f, 375.f), [UIScreen mainScreen].bounds.size))
    
    /** 状态栏高度 */
    #define LCL_StatusBar_Height ((LCLIsIphoneX) ? 44 : 20)
    
    /** 导航栏高度 */
    #define LCL_NavBar_Height ((LCLIsIphoneX) ? 88 : 64)
    
    /** 标签栏高度 */
    #define LCL_TabBar_Height ((LCLIsIphoneX) ? 83 : 49)
    
    /** 底部横条高度 */
    #define LCL_HomeIndicator_Height ((LCLIsIphoneX) ? 34 : 0)

    但是这不能满足我们的需求, 因为这样做它不支持横屏.

    三. 现在的做法

    我们需要用到UIKit11.0的新增属性来完成这个需求

    UIView类的新属性safeAreaLayoutGuide, 它是UILayoutGuide类型, 我们可以理解为一块安全区域(SafeArea), 不被statusBar, navigationBar, toolBar, tabBar所遮挡的区域

    UILayoutGuide类的属性layoutFrame, 安全区域的位置和大小

    UIView类的新属性SafeAreaInsets, 它指示的是这块安全区域距离整个屏幕之间的上下左右边距

    首先我们可以先打印下这三个属性

    - (void)viewWillLayoutSubviews {
        [super viewWillLayoutSubviews];
    
        CGRect frame = self.view.frame;
        NSLog(@"self.view - frame - %@", NSStringFromCGRect(frame));
        
        CGRect layoutFrame = self.view.safeAreaLayoutGuide.layoutFrame;
        NSLog(@"self.view - layoutFrame - %@", NSStringFromCGRect(layoutFrame));
        
        UIEdgeInsets insets = self.view.safeAreaInsets;
        NSLog(@"self.view - insets - %@", NSStringFromUIEdgeInsets(insets));
    }

    打印结果:

    在iPhoneX竖屏(设备朝上)情况下输出为:

    “self.view - frame - {{0, 0}, {375, 812}}”
    “self.view - layoutFrame - {{0, 88}, {375, 690}}”
    “self.view - insets - {88, 0, 34, 0}”

    可以看到, 在竖屏情况下, 整个控制器的view的大小就是整个屏幕的大小, 而安全区域的大小为除去statusBar(状态栏区域:44), navigationBar(导航栏区域:44), home indicator(底部横条区域:34), 剩下的就是安全区域, 如图:

    在iPhoneX横屏(设备朝左)情况下输出为:

    “self.view - frame - {{0, 0}, {812, 375}}”
    “self.view - layoutFrame - {{44, 32}, {724, 322}}”
    “self.view - insets - {32, 44, 21, 44}”

     可以看到, 在横屏情况下, 整个控制器的view的大小就是整个屏幕的大小, 而安全区域的大小为除去statusBar(状态栏区域:44), navigationBar(导航条区域:32), home indicator(底部横条区域:21), 剩下的就是安全区域, 如图:

     

    在了解了这几个属性具体所指的内容之后, 我们也就可以开始UI布局和屏幕适配啦.

     

    首先我们声明两个全局私有属性

    @interface ViewController ()
    
    /** 红色view 用于置顶 */
    @property (nonatomic, strong) UIView * redView;
    
    /** 橘色view 用于置底 */
    @property (nonatomic, strong) UIView * orangeView;
    
    @end

    然后在viewDidLoad方法里面完成视图的创建

    #pragma mark - 创建视图
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        self.title = @"屏幕适配";
        self.view.backgroundColor = [UIColor yellowColor];
        
        /** 创建红色view */
        UIView * redView = [UIView new];
        redView.backgroundColor = [UIColor redColor];
        [self.view addSubview:redView];
        self.redView = redView;
        
        /** 创建橘色view */
        UIView * orangeView = [UIView new];
        orangeView.backgroundColor = [UIColor orangeColor];
        [self.view addSubview:orangeView];
        self.orangeView = orangeView;
    }

    之后在viewWillLayoutSubviews完成对视图的frame设置

    #pragma mark - 设置视图frame
    - (void)viewWillLayoutSubviews {
        
        /**
         layoutFrame.size.width 安全区域宽度
         layoutFrame.size.height 安全区域高度
         */
        CGRect layoutFrame = self.view.safeAreaLayoutGuide.layoutFrame;
        NSLog(@"self.view - layoutFrame - %@", NSStringFromCGRect(layoutFrame));
        
        /**
         inset.left 安全区域距离屏幕最左边的大小
         inset.right 安全区域距离屏幕最右边的大小
         inset.top 安全区域距离屏幕最上边的大小
         inset.bottom 安全区域距离屏幕最下边的大小
         */
        UIEdgeInsets insets = self.view.safeAreaInsets;
        
        /** 红色view置顶 */
        self.redView.frame = CGRectMake(insets.left, insets.top, layoutFrame.size.width, 100);
        
        /** 橘色view置底 */
        self.orangeView.frame = CGRectMake(insets.left, self.view.bounds.size.height - insets.bottom - 100, layoutFrame.size.width, 100);
    }

    现在我们这个简单的Demo适配就算完成啦, 不管是iPhoneX, 还是其它iOS设备, 不管是竖屏, 还是横屏, 都可以完美适配, 如图:

     

      

     

     

      

    用一句名言来结束本节的探讨吧, 那就是完美”!

     

     

    Talk is cheap. Show me the code.

  • 相关阅读:
    图标线性回归移动到指定的位置
    jquery实现图片裁剪
    使用php输出时间格式
    《这些年,我们读过的技术经典图书》主题有奖征文
    JSON数据格式
    设计模式-命令模式
    windows vc6 release 调试
    hdu4530小Q系列故事——大笨钟
    设计模式-建造者模式
    设计模式-外观模式
  • 原文地址:https://www.cnblogs.com/ZeroHour/p/9942921.html
Copyright © 2011-2022 走看看