[Swift4/Cocoa] NSScrollViewによるNSViewの表示と座標系の変更

2018年6月28日(更新: 2018年6月28日)

大きな NSView を限られた範囲で表示するには NSScrollView を利用します。

以下のように、NSScrollView の中身が大きければ、スクロールバーによる表示領域の変更ができます。

NSScrollViewによるスクロールとスクロールバーの表示

今回は NSScrollView の基本的な表示方法と、中身の初期表示位置と座標系を変更するための処理について紹介します。

サンプルのソースコード

Xcode で Cocoa Application によるプロジェクトを新規作成した際に生成される ViewController.swift を以下のように変更します。

また Storyboard のプロパティで、ウィンドウの大きさを 600×600 に変更しておきます。

import Cocoa

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let contentWidth: CGFloat = 600
        let contentHeight: CGFloat = 600
        let margin: CGFloat = 50
        
        // scrollContentView の中身
        let viewForContent = FlippedView(frame:
            NSRect(x: 0, y: 0, width: contentWidth, height: contentHeight))
        
        // 中身に追加するラベル(左上)
        let topLeftLabel = getTextLabel("Top-Left")
        topLeftLabel.frame.origin = CGPoint(x: margin, y: margin)
        viewForContent.addSubview(topLeftLabel)
        
        // 中身に追加するラベル(右下)
        let bottomRightLabel = getTextLabel("Bottom-Right")
        bottomRightLabel.frame.origin = CGPoint(
            x: contentWidth - bottomRightLabel.frame.width - margin,
            y: contentHeight - bottomRightLabel.frame.height - margin
        )
        viewForContent.addSubview(bottomRightLabel)
        
        // NSScrollView 内の領域
        let scrollContentView = NSClipView(frame:
            NSRect(x: 0, y: 0, width: contentWidth, height: contentHeight))
        scrollContentView.documentView = viewForContent
        
        // NSScrollView の本体
        let scrollView = NSScrollView(frame: NSRect(x: 100, y: 100, width: 400, height: 400))
        scrollView.contentView = scrollContentView
        scrollView.hasVerticalScroller = true
        scrollView.hasHorizontalScroller = true
        scrollView.autohidesScrollers = false
        self.view.addSubview(scrollView)
    }
    
    // ラベルの作成
    func getTextLabel(_ text: String) -> NSTextField {
        
        let label = NSTextField(string: text)
        label.sizeToFit()
        label.isEditable = false
        label.isSelectable = false
        label.isBordered = false
        label.drawsBackground = false
        
        return label
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }
}

// ScrollView用に座標系を変更したNSView
class FlippedView : NSView {
    override var isFlipped: Bool {
        return true
    }
}

NSScrollView の中に表示するコンテンツは、クラス NSClipView のプロパティ documentView に設定したものになります。

通常の NSView やそのサブクラスを documentView に設定すると、NSScrollView の初期表示位置がその左下になり、原点 (0, 0) も左下の端となります。

中身の表示される位置を左上にし、中身の原点も左上にしたい場合は NSView のサブクラスを作り、プロパティ isFlipped をオーバーライドして true となるように変更します。上記のサンプルコードでは、このクラスが FlippedView です。

これによって、冒頭のサンプルのように左上からスクロールできるようになります。

コメントを残す

メールアドレスが公開されることはありません。