iOS7之后UI发生大变化。apple鼓励开发者进行全屏设计,这些并在UI的一些特性上也有所表现。
1.屏幕坐标起始点的变化
新建一个UIViewController并作为项目的RootController,在其View顶部添加一个UILabel,frame=(0,0,200,20)如图:
可以发现label与导航栏发生了重叠,由此可以推知:
iOS7后,坐标(0, 0)从整个屏幕的左上顶点开始计算。
当我们在该UIViewController外套一个UINavigationController后显示如图:
bar02.png
整个label被UINavigationBar覆盖了。
利用检测任意view的subviews的关系树一文中提供的工具方法打印keyWIndow的subViews树:如图
bar03.png由上图可以知晓:
UINavigationBar的高度依旧是44px,
其子View: UINavigationBarBackground高度为64px,origin.y=-20,
所以UINavigationBarBackground充当了状态栏和导航栏的背景。这也解释了通过修改UINavigationBar背景来改变导航栏背景的原理。
我们为UINavigationBar添加背景图片:如图
bar04.png此时打印视图树,如图:
bar05.pnglabel视图出现在了导航栏下方,该效果由UIViewController的一个属性决定的:extendedLayoutIncludesOpaqueBars
,这个属性指定了当Bar使用了不透明图片时,视图是否延伸至Bar所在区域,默认值时NO。如果把这个属性设置为YES,那么视图将会延伸至导航栏区域,即使我们把导航栏设置成了自定义背景。
1, 通过修改UINavigationBar的背景可以来修改状态栏背景
2, 当UIViewController. extendedLayoutIncludesOpaqueBars = NO 时,UINavigationBar添加背景图片后,UIViewController的视图的原点坐标为(0, 64), 下移了64px,并且高度缩减了64px。
通过设置UIViewController的属性:edgesForExtendedLayout
来使label出现在导航栏下方:
self.edgesForExtendedLayout = UIExtendedEdgeNone;
如图:视图不会再延伸到导航栏后面了
bar06.png bar07.png可以发现界面的变化,由此得出:
与为UINavigationBar添加背景图片效果相同
当视图中存在UIScrollView时
1,存在唯一一个
UIScrollView或者其子类时:<注意唯一一个>
- ScrollView为添加的
第一个
子视图
代码:
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.whiteColor()
/*****添加顶部UITableView*****/
let table = UITableView.init(frame: self.view.bounds, style: .Plain);
table.delegate = self;
table.dataSource = self;
self.view .addSubview(table)
self.automaticallyAdjustsScrollViewInsets = true;
/*****添加顶部UILabel*****/
let label = UILabel.init(frame: CGRectMake(0, 0, 200, 20))
label.text = "I am a label";
self.view .addSubview(label)
}
效果和视图树如图:
bar08.pngbar09.png
分析:
以上代码self.automaticallyAdjustsScrollViewInsets = true;
,其中属性automaticallyAdjustsScrollViewInsets
默认为true; 当其值为true
时,如果视图里面存在唯一一个UIScrollView或其子类View,那么它会自动设置相应的内边距,但是不会重置scrollView的frame,这样可以让scroll占据整个视图,又不会让导航栏遮盖。
- ScrollView不是添加的
第一个
子视图或者不止一个ScrollView
代码:
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.whiteColor()
/*****添加顶部UILabel*****/
let label = UILabel.init(frame: CGRectMake(0, 0, 200, 20))
label.text = "I am a label";
self.view .addSubview(label)
/*****添加顶部Table*****/
let table = UITableView.init(frame: self.view.bounds, style: .Plain);
table.delegate = self;
table.dataSource = self;
self.view .addSubview(table)
self.automaticallyAdjustsScrollViewInsets = true;
}
本次是先添加label然后添加ScrollView,其效果和子视图如图:
bar11.png bar10.png分析:代码self.automaticallyAdjustsScrollViewInsets = true;
失效了。
此时我门可以使用属性:self.edgesForExtendedLayout = UIExtendedEdgeNone;
,然后将ScrollView的高相应的缩减64px,来达到目的。
总结
iOS7之后apple鼓励开发者使用全屏布局,这样导致了视图的原点(0,0)为屏幕左上顶点,而不再是状态栏左下位置开始。
UIViewController的属性:
extendedLayoutIncludesOpaqueBars
, 默认为false,
说明:这个属性指定了当Bar使用了不透明图片时,视图是否延伸至Bar所在区域,默认值时false。
所以我们如果自定义了导航栏的背景图片,那么视图会从导航栏以下开始,不会延伸到导航栏区域。
如果把这个属性设置为true,那么视图将会延伸至导航栏区域,即使我们把导航栏设置成了自定义背景
edgesForExtendedLayout
, 默认为UIExtendedEdgeNone,
说明: 这个属性指定边缘要延伸的方向。
因为iOS7鼓励全屏布局,它的默认值很自然地是UIRectEdgeAll,四周边缘均延伸,就是说,如果即使视图中上有navigationBar,下有tabBar,那么视图仍会延伸覆盖到四周的区域。
automaticallyAdjustsScrollViewInsets
, 默认为true
当设置为YES时(默认YES),如果视图里面存在唯一一个且为第一个加入视图的UIScrollView或其子类View,那么它会自动设置相应的内边距,这样可以让scroll占据整个视图,又不会让导航栏遮盖。若ScrollView不止一个或者不是第一个加入子视图则该属性将失效。
导航栏图片背景
添加背景图片
self.navigationController?.navigationBar .setBackgroundImage(UIImage.init(imageLiteral: "barbar66.png"), forBarPosition: UIBarPosition.Top, barMetrics: UIBarMetrics.Default)
1,作为导航背景的图片:该图片是一个@2x图片:160*88
barbar88@2x.png效果如图:
bar12.png2,将图片换成barbar66@2x.png:160*66
效果如图:
3,将图片换成barbar100@2x.png:182*100
效果如图:
4,将图片换成barbar100@2x.png:182*128
效果如图:
5,将图片换成barbar228@2x.png:415*228
效果如图:
有以上结果可见:
假设图片高度为h,
- 当h<88 或者 88<h<128时,纵向横向平铺,覆盖导航栏
- 当h=88时,横向平铺,不覆盖导航栏
- 当h=128时,横向平铺,覆盖导航栏
- 当h>128时,纵向截取,横向平铺,覆盖导航栏
得到以上结论的前提是:所有图片是@2x图。关于一倍图,无论何种情况都是横向平铺纵向拉伸。
有关参数:BarPosition和barMetrics的确切作用目前还不十分清楚,等弄清楚了后续补充。
附上UINavigationBar的扩展,内涵:bar去下边线,bar透明,bar恢复默认状态等。见地址:http://pan.baidu.com/s/1i4UqdFJ
以上内容如有不足或错误欢迎指正留言。
网友评论