回头看UITableView(二)-父视图UIScrollView

题目早早就定下了,现在想填充内容了,踌躇中却不知道从哪里开始了。
窗外突然下起雨来。虽然不愿承认,但夏天确实已经渐去渐远,凉意开始蔓延。索性放空身心,伴着雨声入眠吧。


I'm back!

众所周知,UITableView的父视图就是UIScrollView,UITableView之所以能滚动就是基于UIScrollView的特性,今天咱们就来深入理解一下UIScrollView。

上图:
连续修改bounds属性

打码:

- (IBAction)boundsAction:(UIStepper *)sender {
    self.redView.bounds = CGRectMake(0, sender.value, self.redView.bounds.size.width,   self.redView.bounds.size.height);

    self.boundsLabel.text = [NSString stringWithFormat:@"红色视图bounds%@",NSStringFromCGRect(self.redView.bounds)];
}

我如果说改变bounds的值不用UIStepper实现而是用手势实现,不知道大家有没有种恍然大悟的感觉。

我们再复习一下UIView的frame和bounds是什么。
. frame:当前view在父view坐标体系中的位置和大小
. bounds:当前view的坐标体系,容纳子view的位置和大小
也就说一个view的位置是由当前view的frame和其父view的bounds决定的。

回到上面的红绿视图,你已经看到:改变父view(红色视图)的bounds,子view(绿色视图)的位置就会相应的改变。如果我们给红色视图加一个UIPangestureRecognizer(拖动手势),滑动时根据其代理函数返回的值修改红色视图的bounds就实现了绿色视图的滑动。

再上图:
手势修改bounds
再打码:
- (IBAction)panHandler:(UIPanGestureRecognizer *)sender {
    if(sender.state == UIGestureRecognizerStateChanged){
        CGFloat distance = -[sender translationInView:sender.view].y;
        self.redView.bounds = CGRectMake(0, self.redView.bounds.origin.y+distance, self.redView.bounds.size.width, self.redView.bounds.size.height);
        [sender setTranslation:CGPointZero inView:sender.view];
    }else if(sender.state == UIGestureRecognizerStateEnded){
        self.boundsLabel.text = [NSString stringWithFormat:@"红色视图bounds%@",NSStringFromCGRect(self.redView.bounds)];
    }
}

果然图多可以少说话。那么你是不是可以自己手动写个UIScrollView了,如果你敢回答不能我就敢一星期不吃肉。顺便推荐一个录屏软件,个人感觉很好用,直接生成体积较小的gif。地址是http://www.cockos.com/licecap/

当然,对于这个能滑动的视图的始祖,我们要想有强烈的掌控感,还需要了解几个属性。

  1. contentSize
    😓 又要提到上图了,好吧,如上图,contentSize其实就是绿色视图的大小,就是内容空间的大小。在UIScrollView里,当contentSize大于本身的frame.size的时候就可以滚动,否则不允许。
  2. contentOffset
    还是如上图,contentOffset其实就是红色视图的bounds.origin,所以你是否明白为什么当contentOffset的值是正值的时候视图往上,是负值的时候视图往下了吧。
  3. contentInset
    这个属性很难说清楚,所以,那就更应该说了。如果你设置了这个属性后会对内容视图做一个偏移操作,或者说给内容视图添加了留白,比如说我们设置UIScrollView的contentInset为UIEdgeInsetsMake(64, 0, 0, 0)注意第一个参数是top,然后依次是left,bottom,right。那么添加的subview的位置纵坐标的起点就是subview.frame.origin.y+scrollView.contentInset.top(当然这是在不考虑父视图的bounds的情况下)。你也许注意到了一点,我用了位置一词,因为这其实是相对父视图的位置,它的frame并没有改变。

2DCEB800-BB02-4E2D-A58F-25C2247D2F21.png

啊哈哈,

self.scrollView.contentInset = UIEdgeInsetsMake(50, 0, 0, 0);

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 50, self.scrollView.bounds.size.width, 200)];
    view.backgroundColor = [UIColor greenColor];
    [self.scrollView addSubview:view];

如图,虽然view的起点是50,但是由于contentInset的原因,它相对于父视图的纵坐标位置是100。

好了,先写到这里,办公室就我一个人了,兄弟我先回家了。

预告:根据上边这些东东,咱们稍后谈谈怎么实现一个自定义的下拉刷新控件,我会尽快更新。
最后,诚心求一个Mac上方便作图的软件。如果你有破解版的sketch的话,给兄弟一个吧,先谢过了。


标题:回头看UITableView(二)-父视图UIScrollView
作者:yuyedaidao
地址:http://mooncake.wang/articles/2018/11/09/1573699416463.html