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


  • 2019-05-21 12:43:26

    (重要)RecycleView的缓存机制

    RecycleView的四级缓存是由三个类共同作用完成的,Recycler、RecycledViewPool和ViewCacheExtension。Recycler用于管理已经废弃或者与RecyclerView分离的ViewHolder,这里面有两个重要的成员,为可以看见的屏幕的内部缓存成员mAttachedScrap、mChangedScrap和滑出屏幕外的外部缓存成员mCachedViews二者共同完成ViewHolder的缓存;RecycledViewPool类是用来缓存整体所有的ViewHolder,是对mCachedViews缓存的补充;ViewCacheExtension是扩展内的缓存对象,默认不加载,需实现方法getViewForPositionAndType(Recycler recycler, int position, int type)来实现自己的缓存。接下来对四级缓存一步步介绍。

  • 2019-05-21 12:44:31

    对嵌套RecyclerView的优化

    RecyclerView 是一个更高级的 ListView ,它可以重用view避免额外创建太多的view从而带来流畅的滚动性能。RecyclerView通过叫做 View pool 的东西持有不再可见的 view ,让它可被回收

  • 2019-05-25 14:54:50

    commit your changes or stash them before you can merge

    Your local changes to the following files would be overwritten by merge:         protected/config/main.php Please, commit your changes or stash them before you can merge. --------------------- 作者:陈小峰_iefreer 来源:CSDN 原文:https://blog.csdn.net/iefreer/article/details/7679631 版权声明:本文为博主原创文章,转载请附上博文链接!

  • 2019-05-27 10:43:34

    IntelliJ IDEA中C盘文件过大怎么办

    当我在D:\ 安装完IDEA9.0之后,建立了一个工程,发现C:\Users\Administrator\.IntelliJIdea90 竟然增大到了500+M,并且随着使用在逐渐增大,这样占用系统盘资源是非常让人不爽的,那么如何将其修改到其他路径呢?

  • 2019-05-28 13:33:20

    BRVAH+MTRVA,复杂?不存在的

    言归正传,这样的一个首页,我们需要做怎么样的基础工作呢?或者说,碰到以后更复杂的页面我们应该怎么做?这里小提示下,不要再用什么类似ScrollView的这种东西了,诶,好像说的有点绝对,尽量不要用,这不是谷歌想要看到的,5.0谷歌推出了RecyclerView,从它的整个设计架构来看,简直就是为这而生的。而RecyclerView的视图是通过Adapter来渲染的。原始的Adapter,让人很蛋疼,重复工作太多,我们应该要有封装的思想,把最需要的部分提供出来,其它不用管。

  • 2019-05-29 14:19:19

    解决Git中fatal: refusing to merge unrelated histories

    Git的报错 在使用Git的过程中有时会出现一些问题,那么在解决了每个问题的时候,都需要去总结记录下来,下次不再犯。 一、fatal: refusing to merge unrelated histories 今天在使用Git创建项目的时候,在两个分支合并的时候,出现了下面的这个错误。

  • 2019-05-29 15:47:51

    撤销commit

    在git push的时候,有时候我们会想办法撤销git commit的内容