当前位置: 首页 > 编程日记 > 正文

iOS 11 安全区域适配总结

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

 

导语:本文主要是对iOS 11下APP中tableView内容下移20pt或下移64pt的问题适配的一个总结。内容包括五个部分:问题的原因分析、adjustContentInset属性的计算方式、什么情况下的tableView会发生内容下移、有哪些解决方法、解决这个问题时遇到的另外一个小问题。

一、iOS 11下APP中tableView内容下移20pt或下移64pt的原因分析

问题如下图所示:

问题.png

1. 原因分析

原因是iOS 11中Controller的automaticallyAdjustsScrollViewInsets属性被废弃了,所以当tableView超出安全区域时系统自动调整了SafeAreaInsets值,进而影响adjustedContentInset值,在iOS 11中决定tableView的内容与边缘距离的是adjustedContentInset属性,而不是contentInsetadjustedContentInset的计算方式见本文第二部分内容。因为系统对adjustedContentInset值进行了调整,所以导致tableView的内容到边缘的距离发生了变化,导致tableView下移了20pt(statusbar高度)或64pt(navigationbar高度)。

如果你的APP中使用的是自定义的navigationbar,隐藏掉系统的navigationbar,并且tableView的frame为(0,0,SCREEN_WIDTH, SCREEN_HEIGHT)开始,那么系统会自动调整SafeAreaInsets值为(20,0,0,0),如果使用了系统的navigationbar,那么SafeAreaInsets值为(64,0,0,0),如果也使用了系统的tabbar,那么SafeAreaInsets值为(64,0,49,0)。关于什么情况下会发生内容下移的问题,本文第三部分有介绍。

2. 安全区域的概念

系统自动调整tableView内容偏移量,是根据安全区域来调整的。安全区域是iOS 11新提出的,如下图所示:


SafeArea of an interface.png

安全区域帮助我们将view放置在整个屏幕的可视的部分。即使把navigationbar设置为透明的,系统也认为安全区域是从navigationbar的bottom开始的。
安全区域定义了view中可视区域的部分,保证不被系统的状态栏、或父视图提供的view如导航栏覆盖。可以使用additionalSafeAreaInsets去扩展安全区域去包括自定义的content在你的界面。每个view都可以改变安全区域嵌入的大小,Controller也可以。

safeAreaInsets属性反映了一个view距离该view的安全区域的边距。对于一个Controller的根视图而言,SafeAreaInsets值包括了被statusbar和其他可视的bars覆盖的区域和其他通过additionalSafeAreaInsets自定义的insets值。对于view层次中得其他view,SafeAreaInsets值反映了view被覆盖的部分。如果一个view全部在它父视图的安全区域内,则SafeAreaInsets值为(0,0,0,0)。

二、 adjustContentInset属性的计算方式

首先看scrollView在iOS11新增的两个属性:adjustContentInsetcontentInsetAdjustmentBehavior

/* Configure the behavior of adjustedContentInset.
Default is UIScrollViewContentInsetAdjustmentAutomatic.
*/
@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior

adjustContentInset表示contentView.frame.origin偏移了scrollview.frame.origin多少;是系统计算得来的,计算方式由contentInsetAdjustmentBehavior决定。有以下几种计算方式:

  1. UIScrollViewContentInsetAdjustmentAutomatic:如果scrollview在一个automaticallyAdjustsScrollViewInsets = YES的controller上,并且这个Controller包含在一个navigation controller中,这种情况下会设置在top & bottom上 adjustedContentInset = safeAreaInset + contentInset不管是否滚动。其他情况下与UIScrollViewContentInsetAdjustmentScrollableAxes相同

  2. UIScrollViewContentInsetAdjustmentScrollableAxes: 在可滚动方向上adjustedContentInset = safeAreaInset + contentInset,在不可滚动方向上adjustedContentInset = contentInset;依赖于scrollEnabled和alwaysBounceHorizontal / vertical = YES,scrollEnabled默认为yes,所以大多数情况下,计算方式还是adjustedContentInset = safeAreaInset + contentInset

  3. UIScrollViewContentInsetAdjustmentNever: adjustedContentInset = contentInset

  4. UIScrollViewContentInsetAdjustmentAlways: adjustedContentInset = safeAreaInset + contentInset

contentInsetAdjustmentBehavior设置为UIScrollViewContentInsetAdjustmentNever的时候,adjustContentInset值不受SafeAreaInset值的影响。

三、什么情况下的tableView会发生上述问题

如果设置了automaticallyAdjustsScrollViewInsets = YES,那么不会发生问题,一直都是由系统来调整内容的偏移量。

接下来排查下自己的项目中哪些页面会发生以上问题。

当tableView的frame超出安全区域范围时,系统会自动调整内容的位置,SafeAreaInsets值会不为0,于是影响tableView的adjustContentInset值,于是影响tableView的内容展示,导致tableView的content下移了SafeAreaInsets的距离。SafeAreaInsets值为0时,是正常的情况。

需要了解每个页面的结构,看tableView是否被系统的statusbar或navigationbar覆盖,如果被覆盖的话,则会发生下移。也可以通过tableview.safeAreaInsets的值来确认是因为安全区域的问题导致的内容下移。

如下代码片段,可以看出系统对tableView向下调整了20pt的距离,因为tableView超出了安全区域范围,被statusbar覆盖。

tableview.contentInset: {64, 0, 60, 0}
tableview.safeAreaInsets: {20, 0, 0, 0}
tableview.adjustedContentInset: {84, 0, 60, 0}

四、这个问题的解决方法有哪些?

1. 重新设置tableView的contentInset值,来抵消掉SafeAreaInset值,因为内容下移偏移量 = contentInset + SafeAreaInset;

如果之前自己设置了contentInset值为(64,0,0,0),现在系统又设置了SafeAreaInsets值为(64,0,0,0),那么tableView内容下移了64pt,这种情况下,可以设置contentInset值为(0,0,0,0),也就是遵从系统的设置了。

2. 设置tableView的contentInsetAdjustmentBehavior属性

如果不需要系统为你设置边缘距离,可以做以下设置:

 //如果iOS的系统是11.0,会有这样一个宏定义“#define __IPHONE_11_0  110000”;如果系统版本低于11.0则没有这个宏定义
#ifdef __IPHONE_11_0   
if ([tableView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
#endif

contentInsetAdjustmentBehavior属性也是用来取代automaticallyAdjustsScrollViewInsets属性的,推荐使用这种方式。

3. 通过设置iOS 11新增的属性addtionalSafeAreaInset;

iOS 11之前,大家是通过将Controller的automaticallyAdjustsScrollViewInsets属性设置为NO,来禁止系统对tableView调整contentInsets的。如果还是想从Controller级别解决问题,那么可以通过设置Controller的additionalSafeAreaInsets属性,如果SafeAreaInset值为(20,0,0,0),那么设置additionalSafeAreaInsets属性值为(-20,0,0,0),则SafeAreaInsets不会对adjustedContentInset值产生影响,tableView内容不会显示异常。这里需要注意的是addtionalSafeAreaInset是Controller的属性,要知道SafeAreaInset的值是由哪个Controller引起的,可能是由自己的Controller调整的,可能是navigationController调整的。是由哪个Controller调整的,则设置哪个Controller的addtionalSafeAreaInset值来抵消掉SafeAreaInset值。

五、遇到的另外一个与安全区域无关的tableView内容下移的问题

我的作品页面的tableView下移了约40pt,这里是否跟安全区域有关呢?

查了下页面结构,tableView的父视图的frame在navigationbar的bottom之下,tableView在父视图的安全区域内,打印出来tableView的SafeAreaInset值也是(0,0,0,0);所以不是安全区域导致的内容下移。

经过查看代码,发现tableView的style:UITableViewStyleGrouped类型,默认tableView开头和结尾是有间距的,不需要这个间距的话,可以通过实现heightForHeaderInSection方法(返回一个较小值:0.1)和viewForHeaderInSection(返回一个view)来去除头部的留白,底部同理。

iOS 11上发生tableView顶部有留白,原因是代码中只实现了heightForHeaderInSection方法,而没有实现viewForHeaderInSection方法。那样写是不规范的,只实现高度,而没有实现view,但代码这样写在iOS 11之前是没有问题的,iOS 11之后应该是由于开启了估算行高机制引起了bug。添加上viewForHeaderInSection方法后,问题就解决了。或者添加以下代码关闭估算行高,问题也得到解决。

self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;


链接:http://www.jianshu.com/p/efbc8619d56b

转载于:https://my.oschina.net/daniels/blog/1560411

相关文章:

(广州)软件开发定制服务,工作流引擎 OA 库存管理系统

本人专注于工作流的研究设计同时提供软件开发定制服务,工作流引擎 OA系统 库存管理系统 如果有机会合作共事请联系:15817167503(本人在广州) QQ:1311663711 加时请注明软件定制 广州软件定制开发 转载于:https://www.cnblogs.com/…

Java类加载机制详解【java面试题】

Java类加载机制详解【java面试题】 (1)问题分析: Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户…

C#获取文件的当前路径

1. System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName -获取模块的完整路径。 2.System.Environment.CurrentDirectory -获取和设置当前目录(该进程从中启动的目录)的完全限定目录。 3.System.IO.Directory.GetCurrentDirectory() &a…

c# ThreadPool 判断子线程全部执行完毕的四种方法

1、先来看看这个多线程编程多线程用于数据采集时,速度明显很快,下面是基本方法,把那个auto写成采集数据方法即可。using System;using System.Collections.Generic;using System.Text;using System.Threading;namespace ConsoleApplication1{…

腾讯精选练习 50 题(Leetcode)笔记 PDF下载!

昨天在知识星球中立了一个Flag,第一步采取的行动就是把以前刷的“腾讯精选练习 50 题”重新梳理一下,就有了今天这本170多页的小册子。 这本小册子即可以作为学习数据结构与算法课程的参考资料,也可以作为备考计算机类研究生的备考资料。希望…

Python培训:try-except语句与else子句联合使用处理可能出现的程序异常

异常处理的主要目的是防止因外部环境的变化导致程序产生无法控制的错误,而不是处理程序的设计错误。因此,将所有的代码都用try语句包含起来的做法是不推荐的,try语句应尽量只包含可能产生异常的代码。Python中try-except语句还可以与else子句…

Backup Exec 2012 备份和还原活动目录(非授权还原)

延续以上两篇,安装配置完毕后,开始进行备份操作。 环境一如上篇: DC: pdc1.fengdian.info BE2012 Svr: backup.fengdian.info 本例使用BE2012对活动目录进行备份和后续的还原操作,通过模拟误删除DC中的两个OU及其用户账号,使用先…

hdu3368 Reversi

题意:一种翻转棋游戏,对当前的棋局,问黑子下一步最多能将几个白子翻为黑子,(当前黑子与原先棋盘中的黑子的连线中间的白子会翻成黑子) 分析:很简单的搜索题,不过一开始一直WA&#x…

有符号整型的数据范围为什么负数比正数多一个?

背景 我们先看Leetcode的这道题目: 标题:50. Pow(x, n)难度:中等https://leetcode-cn.com/problems/powx-n/ 实现 pow(x, n) ,即计算 x 的 n 次幂函数。 示例 1: 输入: 2.00000, 10 输出: 1024.00000示例 2: 输入: 2.10000, 3…

UI设计培训:UI构思创意技巧和方法

想要作为一名合格的UI设计师,那么创意技巧和方法是非常重要的,很多刚入职场的新人或者是工作多年的设计师都会在创意技巧和方法上遇到瓶颈,下面小编为大家整理一些UI构思创意技巧和方法,希望能够帮助到大家。 UI设计培训&#xff…

博客园 cnblogs博客添加Google Analytics统计

在cnblogs的文章列表中只可以看到自己的每篇文章的页面浏览量,没有详细的统计信息。Google Analytics作为强大的统计工具,能得到几乎所有想要的统计信息,是博客不可多得的好工具,本文介绍如何在cnblogs博客中使用Google Analytics…

技术图文:Python 位运算防坑指南

背景 我们先看这个题目: 标题:137. 只出现一次的数字 II难度:中等https://leetcode-cn.com/problems/single-number-ii/ 给定一个 非空 整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出…

聊聊nginx报错499问题

序本文主要来聊一下nginx的access log当中出现的499问题。 问题描述499 CLIENT CLOSED REQUESTA non-standard status code introduced by nginx for the case when a client closes the connection while nginx is processing the request. 原因服务器返回http头之前&#xff…

UI设计需要报培训班学习吗

UI设计在很多企业已经是不可或缺的一个岗位了,所以UI设计的发展空间是非常大的,想要做UI设计师,光靠自学是不行的,那么UI设计需要报培训班学习吗?来看看下面小编的详细介绍就知道了。 UI设计需要报培训班学习吗?目前学习UI设计主…

技术图文:位运算技术在求解算法题中的应用

背景 前段时间,在知识星球立了一个Flag,这是总结Leetcode刷题的第一篇图文。 在总结这篇图文的时候,顺便把遇到的坑写了两篇辅助的图文,大家可以参考一下: 有符号整型的数据范围为什么负数比正数多一个?P…

JavaScript学习系列6 充实文档的内容

JavaScript 两项基本原则渐进增强:你应该总是从最核心的部分,也就是从内容开始。应该根据内容使用标记实现良好的结构;然后再逐步加强这些内容。平稳退化:不支持JavaScript也能访问基本内容。内容:我们在Html文件中编辑…

mapreduce中设置自定义的输入类,进行文本解析(默认以tab键为分隔符)

job.setInputFormatClass(KeyValueTextInputFormat.class);//此时map端输入的键的内容为第一个tab键以左的内容,值得内容为第一个tab键以右的内容转载于:https://www.cnblogs.com/le-ping/p/7788973.html

如何分辨Web前端培训机构的好坏

web前端在互联网行业有着非常高的薪水和很好的前景,想要学习web前端的人越来越多,对于web前端培训机构的选择让很多人犯了难,那么如何分辨Web前端培训机构的好坏呢?该如何选择呢?来看看下面的详细介绍。 如何分辨Web前端培训机构的好坏? 1…

mysql dba系统学习(19)配置mysql+lvs+keeplived实现Mysql读操作的负载均衡

配置mysqllvskeeplived实现Mysql读操作的负载均衡 环境: test1192.168.46.131master test2192.168.46.130slave备份test库 test3调度器 1、安装与配置Keepalived 首先在节点test1、test2上安装Keepalived软件,软件安装非常简单。 12345678910111213[root…

技术图文:浅析 C# Dictionary实现原理

背景 对于 C# 中的 Dictionary类 相信大家都不陌生,这是一个 Collection(集合) 类型,可以通过 Key/Value (键值对) 的形式来存放数据;该类最大的优点就是它查找元素的时间复杂度接近 O(1),实际项目中常被用来做一些数据的本地缓存…

思念水饺吃成泡沫水饺(图)思念质量门

思念再曝水饺吃出泡沫 !思念带着“创可贴汤圆”和“泡沫水饺”“拜晚年”了,而失去新国标的“护身符”,思念这次还要找出什么样的借口为汤圆里的创可贴和水饺里的泡沫找“台阶”下呢?思念汤圆刚被爆吃出创可贴,思念水饺…

jQuery动画的显示与隐藏效果

jQuery中用于控制元素显示和隐藏效果的方法如表1所示。 表1 控制元素的显示和隐藏 在表1中,参数speed表示动画的速度,可设置为动画时长的毫秒值(如1000),或预定的3种速度(slow、fast和normal);参数easing表示切换效果,默认效果为s…

技术图文:字典技术在求解算法题中的应用

背景 前段时间,在知识星球立了一个Flag,这是总结Leetcode刷题的第二篇图文。 在总结这篇图文的时候,顺便总结了 C# 中Dictionary类的实现,大家可以参考一下: 浅析 C# Dictionary实现原理 理论部分 C# 中字典的常…

[WCF REST] 解决资源并发修改的一个有效的手段:条件更新(Conditional Update)

条件获取(Conditional Update)可以避免相同数据的重复传输,进而提高性能。条件更新(Conditional Update)用于解决资源并发操作问题。如果我们预先获取一个资源进行修改或者删除,条件更新检验帮助我们确认资…

Netty 之 Zero-copy 的实现(下)

上一篇说到了 CompositeByteBuf ,这一篇接着上篇的讲下去。 FileRegion 让我们先看一个Netty官方的example // netty-netty-4.1.16.Final\example\src\main\java\io\netty\example\file\FileServerHandler.java public void channelRead0(ChannelHandlerContext ctx…

Java中final关键字如何使用?

final变量只能赋值一次,赋值的方式有三种: 1)声明变量时直接赋值; 2)非静态成员变量在{}块中赋值,静态成员变量在static{}块中赋值; 3)非静态成员变量在构造方法中赋值。 final修饰类 final类不能被继承,因此不会有子类。final类中…

技术图文:双指针在求解算法题中的应用

背景 前段时间,在知识星球立了一个Flag,这是总结Leetcode刷题的第三篇图文。 理论部分 Python list 的源码地址: https://github.com/python/cpython/blob/master/Include/listobject.h https://github.com/python/cpython/blob/master/O…

【CSON原创】HTML5游戏框架cnGameJS开发实录(外部输入模块篇)

返回目录 1.为什么我们需要外部输入模块? 在游戏中我们常常用到类似这样的操作:鼠标点击某位置,玩家对象移动到该位置,或者按鼠标方向键,玩家向不同方向移动,等等。这些操作无一不用与外部输入设备打交道。…

中国科协(深圳)海外人才离岸创新创业基地源创力中心开业,主打国际创业服务...

2017年9月28日,由深圳市科学技术协会主办、深圳市罗湖区人民政府支持,深圳市源创力离岸创新中心承办的“梧桐山基地开园仪式暨梧桐湾未来论坛”于深圳举办。 据介绍, “中国科协(深圳)海外人才离岸创新创业基地”是在深…

找java培训机构如何挑选

​ java技术在互联网行业的需求率还是非常高的,它的发展前景非常可观,想要学好java技术,那么寻找一个好的java培训机构是非常重要的,那么找java培训机构如何挑选呢?来看看下面的详细介绍。 ​  找java培训机构如何挑选? 在选择…