在引入了导航控制器UINavigationController和分栏控制器UITabBarController之后,我们在设置控件的frame的时候就需要注意避开导航栏UINavigationBar 44+电源栏UIStatusBar 20的高度,和底部分栏UITabBar 44的高度。底部分栏并没有太多需要处理的,我们只需要在计算高度的时候避开这44就可以了。而导航栏因为包含透明/半透明、第一个控件是否是UIScrollView或其子类等造成frame.origin.y的起点不同。我们现在来分析一下。

  1.edgesForExtendedLayout:UIRectEdge 扩展布局的边缘

  在iOS7以后 UIViewController 开始使用全屏布局,而且是默认的属性。通常涉及到布局,就离不开这个属性 edgesForExtendedLayout,它是一个类型为UIExtendedEdge的属性,指定UIViewController上的根视图self.view边缘要延伸的方向。由于iOS7鼓励全屏布局,所以它的默认值是UIRectEdgeAll,四周边缘均延伸,就是说,如果即使视图中上有UINavigationBar,下有UITabBar,那么视图仍会延伸覆盖到四周的区域。

  (1)UIRectEdgeAll(Defalut)

图1

  这里放置了一个frame为(0, 0, 100, 100)的view,backgroundColor设置为redColor,就是这个样子。也就是说,此时的self.view是从屏幕顶到屏幕底的。此时我们计算控件frame的y的时候,如果想把控件在导航栏底部开始,那么y就是64。

  (2)UIRectEdgeNone

  因此,我们为了不让我们的控件UIView延伸到UINavigationBar下面,我们可以将该属性设置为UIRectEdgeNone。代码如下:

  [self setEdgesForExtendedLayout:UIRectEdgeNone];

  ps:鉴于之前代码OC与Swift都有,可能带来的阅读不习惯,以后贴代码尽量使用OC,Swift独有的那就没办法了。

图2

  很清晰的可以看出来在设置为UIRectEdgeNone之后,self.view的是从导航栏底部到底部分栏顶部的。此时我们计算控件frame的y的时候,如果想把控件在导航栏底部开始,那么y就是0。

  (3)UIRectEdge

 typedef NS_OPTIONS(NSUInteger, UIRectEdge) {

     UIRectEdgeNone   = ,

     UIRectEdgeTop    =  << ,

     UIRectEdgeLeft   =  << ,

     UIRectEdgeBottom =  << ,

     UIRectEdgeRight  =  << ,

     UIRectEdgeAll    = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight  

 } NS_ENUM_AVAILABLE_IOS(7_0);

  很明显,UIRectEdge是个枚举类型。我们已经分析完了UIRectEdgeNone和UIRectEdgeAll,那么对UIRectEdgeTop和UIRectEdgeBottom也应该有所了解了。UIRectEdgeLeft/UIRectEdgeRight也不难猜测,就是对左右的扩展。目前没有遇到过左右两边系统控件可能覆盖掉自定义控件的情况,但遇到了我想大家也应该心里有数了吧。

  2.translucent:Bool 半透明的

  这个是self.navigationController.navigationBar的属性,设置导航条UINavigationBar是否半透明。默认是YES,也就是半透明,看起来比较高大上,与图1效果相同。

  当设置为不透明NO的时候,就涉及到下面第三条属性了,不过在第三条默认的情况下,则被下压,与图2效果相同。

  [self.navigationController.navigationBar setTranslucent:NO];

          图3

  图中空出的部分,即为导航条UINavigationBar。此时计算frame应从导航栏下部为0开始计算,或者说控件会被下压64。

  不过我们一般不会使用到这一条,因为半透明效果比较好看啊~

  3.extendedLayoutIncludesOpaqueBars:Bool 不透明的条下是否可以扩展

  很明显,这条需要与上一条translucent搭配使用的,默认为NO,也就是不可以扩展。当translucent设置为NO,即导航栏UINavigationBar不透明的时候,默认不能扩展。若我们设置为YES,则会出现这种情况:

        图4

  我并没有改变红色view的frame,而是被不透明的导航条盖住看不到了。很明显此时计算frame又是从屏幕最上方作为0开始计算了。

  为了计算究竟是在电源条下方还是屏幕最上方作为y的0点,改变了红色view的height为64和65重复试验,结果如下

      图5:64开始

      图6:65开始

  结论是从屏幕上方作为y的0开始计算。

  不过第2条都很少用,第3条使用的几率...

 

  4.automaticallyAdjustsScrollViewInsets:Bool 自动校准滚动视图的嵌入视图

  这个其实就很简单了,也是我们最常使用的一个吧。automaticallyAdjustsScrollViewInsets是一个bool类型,默认为YES,也就是会自动校准滚动视图的嵌入视图。不过这个只针对于UIScrollView及其子视图,所以我们是用UITextView做一下测试。

  创建了一个frame为(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)占据整个屏幕的UITextView,并放置了足够多的文字。在默认automaticallyAdjustsScrollViewInsets为YES的前提下,我们测试下可能出现的结果。

 

            图7

  似乎什么毛病都没有啊很正常啊。但是不要忘记我设置的frame的y是0啊。那大家可能就好奇了,难道UIScrollView的滚动视图的frame是从导航栏下边界算起的?

  不忙,我们设置automaticallyAdjustsScrollViewInsets为NO再试试。

  [self setAutomaticallyAdjustsScrollViewInsets:NO];

        图8

  这个是一启动就出现的界面,我并没有向上滑动它的内容区域,也就是说,似乎此时的frame又是从屏幕下方开始的了。

  不要慌,我们改一下设置试试看。

  我将UITextView的frame设置为(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height),也就是y改成了64;然后改变了它的背景颜色为红色redColor;最后将[self setAutomaticallyAdjustsScrollViewInsets:NO];这行代码注掉,让它默认为YES。

  看一下效果。

            图9

  注意:导航栏是半透明的,所以不存在被压到红色看不到的问题,也就是说,UITextView的frame的y的64的位置,是导航栏下方;那么0自然就是在屏幕下方开始计算了。

  很明显,automaticallyAdjustsScrollViewInsets改变的并不是UIScrollView的frame,而是它的内容区域contentView的可滚动区域,也就是scrollIndicatorInsets。这是我们能滚到的最大范围。相当于scrollIndicatorInsets这个属性UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)的值从UIEdgeInsetsMake(0, 0, 0, 0)变为了UIEdgeInsetsMake(64, 0, 0, 0)。这就是automaticallyAdjustsScrollViewInsets这个属性的作用。

  另外再说一点,这个automaticallyAdjustsScrollViewInsets的属性,只对加在self.view上的第一个子视图起作用,所以我们可以在将UIScrollView加载到self.view上之前先加载一个其他控件,这样也能达到同样的效果。

  [self.view addSubView:[[UIView alloc] init]];

  

  涉及导航栏下压的情况大致就有这些,如遇到其他问题,会继续补充。

与导航栏下控件的frame相关的edgesForExtendedLayout、translucent、extendedLayoutIncludesOpaqueBars、automaticallyAdjustsScrollViewInsets等几个属性的详解的更多相关文章

  1. 重新想象 Windows 8 Store Apps (3) - 控件之内容控件: ToolTip, Frame, AppBar, ContentControl, ContentPresenter; 容器控件: Border, Viewbox, Popup

    原文:重新想象 Windows 8 Store Apps (3) - 控件之内容控件: ToolTip, Frame, AppBar, ContentControl, ContentPresenter ...

  2. iOS开发UI篇—手写控件,frame,center和bounds属性

    iOS开发UI基础—手写控件,frame,center和bounds属性 一.手写控件 1.手写控件的步骤 (1)使用相应的控件类创建控件对象 (2)设置该控件的各种属性 (3)添加控件到视图中 (4 ...

  3. iOS开发UI基础—手写控件,frame,center和bounds属性

    iOS开发UI基础—手写控件,frame,center和bounds属性 一.手写控件 1.手写控件的步骤 (1)使用相应的控件类创建控件对象 (2)设置该控件的各种属性 (3)添加控件到视图中 (4 ...

  4. iOS 隐藏导航栏下的黑线

    一.找到导航栏下的黑线 // 寻找导航栏下的黑线 - (UIImageView *)findHairlineImageViewUnder:(UIView *)view { if ([view isKi ...

  5. IOS 设置子控件的frame(layoutSubviews and awakeFromNib)

      如果控件是通过xib或者storyboard创建出来的就会调用该方法 - (void)awakeFromNib :该方法只会调用一次 // 如果控件是通过xib或者storyboard创建出来的就 ...

  6. CSS3——对齐 组合选择符 伪类 伪元素 导航栏 下拉菜单

     水平&垂直对齐 元素居中对齐 .center { margin: auto; width: 50%; border: 3px solid green; padding: 10px; } 文本 ...

  7. 设置TextBlock默认样式后,其他控件的Text相关属性设置失效问题

    问题: 定义了默认TextBlock样式后,再次自定义下拉框 or 其他控件 ,当内部含有TextBlock时,设置控件的字体相关样式无效,系统始终使用TextBlock设置默认样式 解决方案: 为相 ...

  8. Bootstrap框架(基础篇)之按钮,网格,导航栏,下拉菜单

    一,按钮 注意:虽然在Bootstrap框架中使用任何标签元素都可以实现按钮风格,但个人并不建议这样使用,为了避免浏览器兼容性问题,个人强烈建议使用button或a标签来制作按钮. 框架中提供了基础按 ...

  9. 手写控件,frame,center和bounds属性

    一.手写控件 1.手写控件的步骤 (1)使用相应的控件类创建控件对象 (2)设置该控件的各种属性 (3)添加控件到视图中 (4)如果是button等控件,还需考虑控件的单击事件等 (5)注意:View ...

随机推荐

  1. #数论-模运算#POJ 1150、1284、2115

    1.POJ 1150 The Last Non-zero Digit #质因数分解+模运算分治# 先贴两份题解: http://www.hankcs.com/program/algorithm/poj ...

  2. VS2012 此模板尝试加载组件程序集”NuGet.VisualStudio.interop,Version=1.0.0.0 的解决

    VS2012 此模板尝试加载组件程序集”NuGet.VisualStudio.interop,Version=1.0.0.0 的解决办法 2014 年 5 月 3 日作者:mingceng 阅读次数: ...

  3. Struts2的DMI跟SMI

    我使用的Struts2的版本是2.5.2,今天在使用Struts2的DMI(动态方法调用)的时候出现了一个有趣的问题,我先把我的配置及代码展示一下: web.xml <filter> &l ...

  4. .Net 第三方工具包整理

    抓取数据 Jumony (http://www.jumony.net/)是一个基于 .NET 技术,用 C# 编写的一个 HTML 引擎,其可以用来分析解读 HTML 文档中的数据,也可以修改和绑定数 ...

  5. 史上最详细SharePoint 2013安装步骤图解新手教程

    来源:// http://www.itexamprep.com/cn/microsoft/soft/sharepoint2013/2013/0408/2866.html 文章就是SharePoint2 ...

  6. servlet就实现在线用户表

    在学习servlet的过程中,学习了如何用servlet实现在线用户表. 只有服务器处于开机状态才会有在线用户表的存在,在服务器关机的情况下自然就不存在在线用户表的说法:所以,楼主认为在线用户表的信息 ...

  7. webuploader限制只上传图片文件

    // 如果上传的文件不为图片格式, 那么就提示"上传文件格式不正确" if (file.type!="image/jpg" && file.ty ...

  8. linux 文件和目录操作

    1 相对路径和绝对路径 (与C++中概念相似) cd /root/cat 绝对路径 cd ../文件名/ 相对路径,指相对某个文件而言的 2 切换目录 cd  当前目录 进入某个目录 pwd 显示当前 ...

  9. 【CSS】display: inline-block,内联元素

    什么是内联元素? <CSS权威指南>中文字显示:任何不是块级元素的可见元素都是内联元素.其表现的特性是“行布局”形式,这里的“行布局”的意思就是说其表现形式始终以行进行显示.比如,我们设定 ...

  10. HDU - 3068 最长回文(manacher)

    HDU - 3068 最长回文 Time Limit: 2000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Subm ...