1. 程式人生 > >老司機帶你探究NSScrollView的滾動原理

老司機帶你探究NSScrollView的滾動原理

本文主要講述如何實現可以控制NSScrollView滾動的Slider,藉此來探究、深入理解NSScrollView滾動的原理,最終實現的Demo如下:

Demo

接下來,我將通過以下四部分來由淺入深的探究NSScrollView。

一、NSScrollView的結構。

當我們通過Interface Builder將一個NSScrollView拖拽至某個ViewController時,整個NSScrollView的結構如下:

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:表示本身座標系中的位置和大小。 看下圖就明白了(還不明白的,仔細看下圖,好好琢磨琢磨):

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. 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原始碼