目的
说来惭愧,最近在做项目时又出现了NavBar导致的视图偏移问题。问题出现的主要原因还是因为之前没有把translucent、automaticallyAdjustsScrollViewInsets、edgesForExtendedLayout 这些属性搞清楚记下来。
下面就完整的实验一下,然后记录下来以便自己查看,也可以帮助其他困惑的朋友。
问题
AppDelegate.m中的代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
[self.window makeKeyAndVisible];
return YES;
}
ViewController中的主要代码:(tableView的数据源方法省略了)
- (void)viewDidLoad
{
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tableView.delegate = self;
tableView.dataSource = self;
tableView.backgroundColor = [UIColor clearColor];
[self.view addSubview:tableView];
UIView *view = [UIView new];
view.backgroundColor = [UIColor greenColor];
view.frame = CGRectMake(0, 0, self.view.bounds.size.width, 100);
view.alpha = 0.3;
[self.view addSubview:view];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"点我" style:UIBarButtonItemStylePlain target:self action:nil];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat offsetY = scrollView.contentOffset.y;
NSLog(@"%f", offsetY);
}
效果:
问题很明显,tableView和view的y值都是0,可是tableview相对于view向下偏移了64像素,也就是navBar的高度。
滚动tableView后:
发现默认把tableview的contentOffset.y设为-64了。
过程
与上述问题相关的其实有三个属性:
self.automaticallyAdjustsScrollViewInsets = NO;
self.navigationController.navigationBar.translucent = NO;
self.edgesForExtendedLayout = UIRectEdgeNone;
1.automaticallyAdjustsScrollViewInsets属性
automaticallyAdjustsScrollViewInsets属性默认是Yes,这个属性的作用是,在navBar下,系统会自动将scrollView向下偏移64像素。如果设置成No,就不会偏移了。
现在tableView没有偏移了,和绿色的view对齐。当然,contentOffset.y也是0了。
2.translucent属性
这个属性是设置navigationController的navigationBar的。默认也是Yes。
把它设置为No后,效果:
可以发现,两个视图都向下偏移了64,其实本质上是系统把(0, 64)这个点作为坐标原点了。但是需要注意,这时navBar不透明了。有没有什么办法可以既透明又把(0, 64)这个点作为坐标原点呢。自然是有的。
3.edgesForExtendedLayout属性
这个属性就能做到既透明又把(0, 64)这个点作为坐标原点。
设置属性:
self.edgesForExtendedLayout = UIRectEdgeNone;
效果:
注意以上设置其中一个属性的时候,其他两个属性都是默认状态的哦!
总结
1.automaticallyAdjustsScrollViewInsets
self.automaticallyAdjustsScrollViewInsets = NO;
automaticallyAdjustsScrollViewInsets只是作用于scrollView上的,不管设不设置,原点都在(0,0)上,设置后只是更改了scrollView的contentOffset.y。
同时,这个属性只对当前设置的控制器起作用。
2.translucent
self.navigationController.navigationBar.translucent = NO;
translucent设置后,原点在(0,64)处,bar不透明。
同时,这个属性对navController下的所有视图控制器都起作用。
3.edgesForExtendedLayout
self.edgesForExtendedLayout = UIRectEdgeNone;
edgesForExtendedLayout设置后,原点在(0,64)处,bar半透明。
同时,该属性只对当前设置的控制器起作用。
(其实看作用于哪里,就看他是谁的属性就好啦☺)
更新
发现了一个新问题。在设置
self.edgesForExtendedLayout = UIRectEdgeNone;
时候,vc的高度不再是整个屏幕的高度了,而是整个屏幕的高度减去navBar的高度。
先看问题的效果:
问题描述:当我使劲的向下拉tableView,放开后,看上去tableView并没有被拉倒最后。当然!只是看上去没有!
然后我上网查了一下,说设置edgesForExtendedLayout后,vc的高度不再是整个屏幕的高度了。
既然这样我就打印一下vc的高度。
代码也很简单,看效果:
发现确实变了,减少了64像素。也就是navBar的高度。
解决方法:很简单,就在设置edgesForExtendedLayout后,设置tableView高度时减64。
UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height - self.navigationController.navigationBar.bounds.size.height - 20) style:UITableViewStylePlain];