Erstellen Sie programmgesteuert NSScrollView in einem NSView - Cocoa

Ich habe eine NSView-Klasse, die sich um eine benutzerdefinierte Ansicht kümmert, die in der NIB-Datei erstellt wurde.

Jetzt möchte ich der benutzerdefinierten Ansicht eine NSScrollView hinzufügen, muss diese jedoch programmgesteuert ausführen und darf nicht den Interface Builder (In Bildlaufansicht einbetten) verwenden.

Ich habe diesen Code gefunden:

<code>NSView *windowContentView = [mainWindow contentView];
NSRect windowContentBounds = [windowContentView bounds];
scrollView = [[NSScrollView alloc] init];
[scrollView setBorderType:NSNoBorder];
[scrollView setHasVerticalScroller:YES];
[scrollView setBounds: windowContentBounds];
[windowContentView addSubview:scrollView];
</code>

Angenommen, ich deklariere oben die Variablen 'mainWindow' und 'scrollView' als IBOutlets. Wie würde ich vorgehen, um sie mit den richtigen Komponenten in Interface Builder zu verbinden? Ist es sinnvoll, dies so zu tun?

Oder gibt es eine bessere Möglichkeit, eine Bildlaufansicht programmgesteuert hinzuzufügen?

P.S. Ich kann sie nicht auf die übliche Weise verbinden, da ich in Interface Builder kein NSObject-Objekt erstellen oder den Dateieigentümer nicht verwenden kann.

 ctpenrose05. Apr. 2012, 07:23
Was? Natürlich können Sie programmatische Ansichten mit vom Interface Builder generierten Ansichten in Beziehung setzen.
 Otium04. Apr. 2012, 20:22
Wenn Sie Ansichten programmgesteuert erstellen, "verbinden" sie sich nicht mit dem Interface Builder

Antworten auf die Frage(3)

Ich habe ein schwer zu schaffenNSScrollView mitAutoLayout programmatisch, aber endlich hat es funktioniert. Das istSwift Ausführung.

<code>    // Initial scrollview
    let scrollView = NSScrollView()
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.borderType = .noBorder
    scrollView.backgroundColor = NSColor.gray
    scrollView.hasVerticalScroller = true

    window.contentView?.addSubview(scrollView)
    window.contentView?.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[scrollView]|", options: [], metrics: nil, views: ["scrollView": scrollView]))
    window.contentView?.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[scrollView]|", options: [], metrics: nil, views: ["scrollView": scrollView]))

    // Initial clip view
    let clipView = NSClipView()
    clipView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.contentView = clipView
    scrollView.addConstraint(NSLayoutConstraint(item: clipView, attribute: .left, relatedBy: .equal, toItem: scrollView, attribute: .left, multiplier: 1.0, constant: 0))
    scrollView.addConstraint(NSLayoutConstraint(item: clipView, attribute: .top, relatedBy: .equal, toItem: scrollView, attribute: .top, multiplier: 1.0, constant: 0))
    scrollView.addConstraint(NSLayoutConstraint(item: clipView, attribute: .right, relatedBy: .equal, toItem: scrollView, attribute: .right, multiplier: 1.0, constant: 0))
    scrollView.addConstraint(NSLayoutConstraint(item: clipView, attribute: .bottom, relatedBy: .equal, toItem: scrollView, attribute: .bottom, multiplier: 1.0, constant: 0))

    // Initial document view
    let documentView = NSView()
    documentView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.documentView = documentView
    clipView.addConstraint(NSLayoutConstraint(item: clipView, attribute: .left, relatedBy: .equal, toItem: documentView, attribute: .left, multiplier: 1.0, constant: 0))
    clipView.addConstraint(NSLayoutConstraint(item: clipView, attribute: .top, relatedBy: .equal, toItem: documentView, attribute: .top, multiplier: 1.0, constant: 0))
    clipView.addConstraint(NSLayoutConstraint(item: clipView, attribute: .right, relatedBy: .equal, toItem: documentView, attribute: .right, multiplier: 1.0, constant: 0))

    // Subview1
    let view1 = NSView()
    view1.translatesAutoresizingMaskIntoConstraints = false
    view1.wantsLayer = true
    view1.layer?.backgroundColor = NSColor.red.cgColor
    documentView.addSubview(view1)
    documentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view1]|", options: [], metrics: nil, views: ["view1": view1]))

    // Subview2
    let view2 = NSView()
    view2.translatesAutoresizingMaskIntoConstraints = false
    view2.wantsLayer = true
    view2.layer?.backgroundColor = NSColor.green.cgColor
    documentView.addSubview(view2)
    documentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view2]|", options: [], metrics: nil, views: ["view2": view2]))

    // Subview3
    let view3 = NSView()
    view3.translatesAutoresizingMaskIntoConstraints = false
    view3.wantsLayer = true
    view3.layer?.backgroundColor = NSColor.blue.cgColor
    documentView.addSubview(view3)
    documentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view3]|", options: [], metrics: nil, views: ["view3": view3]))

    // Vertical autolayout
    documentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[view1(==100)][view2(==200)][view3(==300)]", options: [], metrics: nil, views: ["view1": view1, "view2": view2, "view3": view3]))
    documentView.addConstraint(NSLayoutConstraint(item: documentView, attribute: .bottom, relatedBy: .equal, toItem: view3, attribute: .bottom, multiplier: 1.0, constant: 0))
</code>

 chl22. Jan. 2018, 12:27
Ich habe so lange danach gesucht! Vielen Dank für die Bereitstellung, es war genau das, wonach ich gesucht und mir Stunden gespart habe!
Lösung für das Problem

wie ein NSScrollView programmgesteuert erstellt und zum Anzeigen einer beliebigen Ansicht verwendet wird, unabhängig davon, ob es sich um eine Schreibfeder oder einen Code handelt. Im Fall einer von einer NIB generierten Ansicht müssen Sie lediglich die NIB-Datei in Ihre benutzerdefinierte Ansicht laden und einen Ausgang für Ihre benutzerdefinierte Ansicht (outletToCustomViewLoadedFromNib) für den Besitzer der Datei erstellen.

<code>NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:[[mainWindow contentView] frame]];

// configure the scroll view
[scrollView setBorderType:NSNoBorder];
[scrollView setHasVerticalScroller:YES];

// embed your custom view in the scroll view
[scrollView setDocumentView:outletToCustomViewLoadedFromNib];

// set the scroll view as the content view of your window
[mainWindow setContentView:scrollView];
</code>

Apple hat eine Anleitung zu diesem Thema, auf die ich keinen Link verweise, da Apple Developer Connection-Zugriff erforderlich ist und deren Links häufig unterbrochen werden. Es trägt den Titel "Erstellen und Konfigurieren einer Bildlaufansicht" und kann derzeit über Google nach dem Titel gesucht werden.

wie Sie sie erstellenNSStackView InnerhalbNSScrollView in Swift 4.2

Möglicherweise müssen Sie umdrehenNSClipView

<code>final class FlippedClipView: NSClipView {
  override var isFlipped: Bool {
    return true
  }
}


private func setup() {
  setupScrollView()
  setupStackView()
}

private func setupScrollView() {
  view.addSubview(scrollView)
  scrollView.translatesAutoresizingMaskIntoConstraints = false
  scrollView.hasVerticalScroller = true
  scrollView.drawsBackground = false

  NSLayoutConstraint.activate([
    scrollView.leftAnchor.constraint(equalTo: view.leftAnchor),
    scrollView.rightAnchor.constraint(equalTo: view.rightAnchor),
    scrollView.topAnchor.constraint(equalTo: view.topAnchor),
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -30),

    scrollView.heightAnchor.constraint(equalToConstant: 400)
  ])

  let clipView = FlippedClipView()
  clipView.drawsBackground = false
  scrollView.contentView = clipView
  clipView.translatesAutoresizingMaskIntoConstraints = false
  NSLayoutConstraint.activate([
    clipView.leftAnchor.constraint(equalTo: scrollView.leftAnchor),
    clipView.rightAnchor.constraint(equalTo: scrollView.rightAnchor),
    clipView.topAnchor.constraint(equalTo: scrollView.topAnchor),
    clipView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor)
  ]
  scrollView.documentView = stackView

  stackView.translatesAutoresizingMaskIntoConstraints = false
  NSLayoutConstraint.activate([
    stackView.leftAnchor.constraint(equalTo: clipView.leftAnchor),
    stackView.topAnchor.constraint(equalTo: clipView.topAnchor),
    stackView.rightAnchor.constraint(equalTo: clipView.rightAnchor),
    // NOTE: No need for bottomAnchor
  ])
}

private func setupStackView() {
  stackView.orientation = .vertical
  stackView.edgeInsets = NSEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)

  NSLayoutConstraint.activate([
    myRowView.heightAnchor.constraint(equalToConstant: 40)
  ])

  myRowView.onPress = { [weak self] in
    self?.doSomething()
  }

  stackView.addArrangedSubview(myRowView)
}
</code>

Ihre Antwort auf die Frage