UINavigationController和UIScrollView滚动-92

2021-01-12 22:13:23

这个问题是在计算UIScrollView滚动式发生的。可费了很多劲解决的。最后是通过获取系统栏高度,tartab高度,减去这些高度解决的。

参考地址 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


  • 2018-04-07 23:35:16

    使用Intent传递对象的两种方式

    Intent 的用法相信你已经比较熟悉了,我们可以借助它来启动活动、发送广播、启动服务等。在进行上述操作的时候,我们还可以在Intent 中添加一些附加数据,以达到传值的效果,比如在FirstActivity 中添加如下代码:

  • 2018-04-10 14:59:59

    JS实现数组去重方法总结(六种方法)

    这篇文章给大家总结下JS实现数组去重方法(六种方法),面试中也经常会遇到这个问题。文中给大家引申的还有合并数组并去重的方法,感兴趣的朋友跟随脚本之家小编一起学习吧

  • 2018-04-13 17:28:33

    jsoup 使用总结4--高级用法之 script js 脚本

    大部分时候,我们使用jsoup解析网页的时候,都是直接找到某一类元素,或者按某种selector查询;具体使用方法可以参考jsoup官网文档 那么你有没有实际操作过,查找script js 脚本呢,因为很多时候页面的内容是根据js动态生成的,或者数据是动态变更;那么这个时候,我们只是获取html页面中script js脚本之间的内容。

  • 2018-04-15 12:56:05

    WebView控件之WebSettings各种配置方法源码总结

    WebSettings用于管理WebView状态配置,当WebView第一次被创建时,WebView包含着一个默认的配置,这些默认的配置将通过get方法返回,通过WebView中的getSettings方法获得一个WebSettings对象,如果一个WebView被销毁,在WebSettings中所有回调方法将抛出IllegalStateException异常。

  • 2018-04-16 07:28:10

    android点击事件,第一次无效,第二次才响应的问题

    今天碰到的问题,android的标题栏一个回退button,每次进入的时候第一次点击无效,一直到第二次点击时才响应,然后把代码copy到系统的回退按钮里面,结果每次都能响应,后面想了想,应该跟焦点有关系