UINavigationController + UIScrollView组合,视图尺寸的设置探秘(三)

还是在苹果的 View Controller Catalog for iOS 文章中找到答案。文中提到了两点:

1、If the navigation bar or toolbar are visible but not translucent, it does not matter if the view controller wants its view to be displayed using a full-screen layout.

如果navigation bar或者toolbar不透明,view controller就无法让它的view全屏显示。换句话说,如果不希望view controller里面的view全屏显示,就应该把navigation bar设为不透明。

2、If the main view of the underlying view controller is a scroll view, the navigation bar automatically adjusts the content inset value to allow content to scroll out from under the navigation bar. It does not make this adjustment for other types of views.

如果view controller下的主视图是scroll view,navigation bar 会自动调整其content inset的值,以便被盖在navigation bar底下的内容能被滚动出来,对于其他类型的视图则不会做此调整。

结论很清楚:要想解决navigation controller下scroll bar诡异的滚动问题,只需要把navigation bar设为不透明。再做一把实验,在viewDidLoad中插入一行,将navigationController.navigationBar.translucent属性设为NO:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationController.navigationBar.translucent = NO;

    self.scrollView.pagingEnabled = YES;
    CGRect rect = self.scrollView.frame;
    rect.size.width *= 2;
    self.scrollView.contentSize = rect.size;

    CGRect rtViewA = self.scrollView.frame;
    rtViewA.origin.y = 0;
    UIView *viewA = [[UIView alloc]initWithFrame:rtViewA];
    viewA.backgroundColor = [UIColor redColor];
    [self.scrollView addSubview:viewA];

    CGRect rtViewB = self.scrollView.frame;
    rtViewB.origin.x = rtViewA.size.width;
    rtViewB.origin.y = 0;
    UIView *viewB = [[UIView alloc]initWithFrame:rtViewB];
    viewB.backgroundColor = [UIColor blueColor];
    [self.scrollView addSubview:viewB];
}

再运行,结果如下:

视图错位的问题倒是没有了,可是竖直方向的滚动条还是在的呀!再打开Debug View Hierarchy,观察scroll view的位置是没问题了:

打印视图信息,发现新情况:scrollview的contentSize高度比frame高出64,viewA的也是:

Printing description of $3:
<UIScrollView: 0x7ffc3400c600; frame = (0 64; 375 603); autoresize = W+H; gestureRecognizers = <NSArray: 0x7ffc33d036a0>; layer = <CALayer: 0x7ffc33c56100>; contentOffset: {0, 0}; contentSize: {750, 667}>
Printing description of $4:
<UIView: 0x7ffc33c40650; frame = (0 0; 375 667); layer = <CALayer: 0x7ffc33c1c6b0>>

可是scroll view的contentSize跟它的frame的高度应该是一样的,为什么此时比它高了呢?肯定是frame的高度被调整过,而contentSize不知道,因此不会跟着改变。调整frame的只能是autolayout执行了约束,根据机型做了适配。我们必须在autolayout约束策略执行之后再去调整contentSize。应该在哪里做呢?文档里介绍:当view的bounds改变或者当视图改变子视图的位置,系统将调用viewDidLayoutSubviews函数,我们应该在这里调整scrollView.contentSize的大小。于是添加viewDidLayoutSubviews函数,如下:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    CGRect rect = self.scrollView.frame;
    rect.size.width *= 2;
    self.scrollView.contentSize = rect.size;

    CGRect rtViewA = self.scrollView.frame;
    rtViewA.origin.x = 0;
    rtViewA.origin.y = 0;
    self.viewA.frame = rtViewA;

    CGRect rtViewB = self.scrollView.frame;
    rtViewB.origin.x = rtViewB.size.width;
    rtViewB.origin.y = 0;
    self.viewB.frame = rtViewB;
}

再次运行,终于正常了:

完美!示例代码可参见:https://github.com/palanceli/NavigationScrollView

时间: 2024-10-23 14:35:29

UINavigationController + UIScrollView组合,视图尺寸的设置探秘(三)的相关文章

UINavigationController + UIScrollView组合,视图尺寸的设置探秘(一)

UINavigationController和UIScrollView是iOS下几种主要的交互元素,但当我搭配二者在一起时,UIScrollView的滚动区域出现了很诡异的现象.我希望UIScrollView横向可翻页,纵向与其frame等高不可滚动,但诡异的是:1.我把UIScrollView的contentSize设为和其frame高度相同,可结果是他总能上下滚动一小段.2.我在UIScrollView的(0, 0)位置创建一个子视图,运行时也总往下偏移几十个像素. 我的程序最初是这么写的:

UINavigationController + UIScrollView组合,视图尺寸的设置探秘(二)

承接上文,我想把view布局修改为如下模式,让ScrollView长在NavigationBar的下方,这总不会有遮挡的问题了吧: story board内容如下,主要是右侧视图蓝色区域添加了ScrollView: ViewController的代码如下: @interface ViewController () @property (weak, nonatomic) IBOutlet UIScrollView *scrollView; @property (nonatomic, strong)

UI:UIScrollView滚动视图

1.初始化 UIScrollView *scrollView = [[UIScrollViewalloc] init]; 2.设置尺寸 (1)按照屏幕尺寸 scrollView.frame =self.view.bounds; (2)自定义尺寸 scrollView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); 3.设置背景色 scrollView.backgroundColo

bootstrap-datetimepicker年视图中endDate设置之后比正常时间提前两个月

bootstrap-datetimepicker年视图中endDate设置结束时间为2016-08,(即8月之后的日期不能选)而在日历上显示时为2016-06,相差两个月,即6月之后的日期不能选 解决方法:设置结束日期时默认添加两个月 但是当需要endDate为11或12月时,需要给endDate设置为2016-13/2016-14,这非日期格式,插件不认,最终的解决方法就是修改插件 在datetimepicker.js的800行左右 if (year == endYear) { months.

UIScrollView —— 分页控件详解(三)——(第一讲)

1 . 所用知识 须知,要达到分页效果,所以会用到UIScrollView的ContentOffset属性,设置其UIScrollView分页移动位置,要有页码就用到了UIPageControl控件显示页码条,而且不要开始不要忘记了设置UIScrollView的属性ContentSize来设置其展示内容范围,要让UIScrollView达到分页效果,还要设置其属性pagingEnabled为YES. 2 . 案例详情 1> 在storyboard上拖拽一个UIScrollView和UIPageC

UIScrollView 滚动视图的方法总结

UIScrollView的属性总结 属性 作用 CGPoint contentOffSet-------------------------- 监控目前滚动的位置 CGSize contentSize------------------------------ 滚动范围的大小 UIEdgeInsets contentInset--------------------- 视图在scrollView中的位置 id<UIScrollerViewDelegate> delegate------ 设置协

UIScrollVIew 滚动视图内容总结

1 - (void)viewDidLoad 2 3 { 4 5 [super viewDidLoad]; 6 7 // Do any additional setup after loading the view. 8 9 10 11 // 滚动视图 12 13 UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(20, 20, 280, 440)]; 14 15 scrollView.backgro

UIScrollView(滚动视图)和(UIPageController)页面控制器+ 定时器的使用

////  Teacher_ViewController.m//  友家家教////  Created by 邹贤 on 15/7/28.//  Copyright (c) 2015年 友家科技公司. All rights reserved.// #import "Teacher_ViewController.h" #import "ArtViewController.h" #import "PrimaryViewController.h" #i

UIScrollView滚动视图

一.基本知识 1.初始化 UIScrollView #import "ViewController.h" #define WIDTH[[UIScreen mainScreen]bounds].size.width #define HEIGHT[[UIScreen mainScreen]bounds].size.height@interface ViewController ()<UIScrollViewDelegate> @end UIScrollView *scroll