老司机带你探究NSScrollView的滚动原理

本文主要讲述如何实现可以控制NSScrollView滚动的Slider,借此来探究、深入理解NSScrollView滚动的原理,最终实现的Demo如下:

老司机带你探究NSScrollView的滚动原理_第1张图片
Demo

接下来,我将通过以下四部分来由浅入深的探究NSScrollView。

一、NSScrollView的结构。

当我们通过Interface Builder将一个NSScrollView拖拽至某个ViewController时,整个NSScrollView的结构如下:

老司机带你探究NSScrollView的滚动原理_第2张图片
NSScrollView的结构
  • Bordered Scroll View:NSScrollView的整体结构,由一个Clip View和两个Scroller构成。
  • Clip View:非常重要的一部分,通过改变自身的bounds属性,可以使subview滚动。
  • Child View:整个NSScrollView中最核心的部分,也是整个NSScrollView中展示的部分。
  • Scroller:如图所示,在NSScrollView中有两个Scroller,一个是垂直滚动的滚动条,一个是水平滚动的滚动条。

二、frame与bounds的区别

在每个View中,都有frame与bounds属性,frame与bounds都是用来描述View的位置、大小信息的,但是存在些许差别,在此我只简单的总结一下。
frame:表示在superview坐标系中的位置与大小。
bounds:表示本身坐标系中的位置和大小。
看下图就明白了(还不明白的,仔细看下图,好好琢磨琢磨):

老司机带你探究NSScrollView的滚动原理_第3张图片
image.png

三、NSScrollView的滚动原理

通过上节,我知道了frame与bounds的区别之后,我们来思考一个问题:如果保持自身frame不变,改变了superview的bounds之后,会发生什么?

frame代表superview坐标系中的位置,若superview的bounds改变,意味着superview的坐标系发生了改变,如果此时frame没有改变的话,那么就意味着,本地坐标系的原点随着superview坐标系的偏移发生了变化。

简而言之:改变superview的bounds就可以使当前view的显示位置发生变化。

我们结合第一部分的图来看,如果我们需要让Child View向右滚动10像素,那么我们需要将其superview也就是Clip View的bounds的x坐标的基础上加10即可,这样就实现了Child View的水平滚动。(啥?你问我向左滚动怎么办?要不你猜猜看???)

可如果我们需要让Child View向上滚动10像素呢?很简单,使Clip View的bounds的y坐标减10即可。

四、通过slider实现滚动NSScrollView

slider设置Contiuous.


老司机带你探究NSScrollView的滚动原理_第4张图片
image.png

核心代码如下:

__weak IBOutlet NSSlider *slider;

slider.minValue = 0;
slider.maxValue = NSWidth(childView.frame);

- (IBAction)changed:(NSSlider *)sender {
    NSRect bounds = NSMakeRect(sender.doubleValue,
                               NSMinY(clipView.bounds),
                               NSWidth(clipView.bounds),
                               NSHeight(clipView.bounds));
    [clipView setValue:@(bounds) forKey:@"bounds"];
}

五、完整Demo源代码

https://github.com/gaoxiaodiao/mac_sample/tree/master/NSScrollView

你可能感兴趣的:(老司机带你探究NSScrollView的滚动原理)