12

nibファイルで作成されたカスタムビューを処理するNSViewクラスがあります。

ここで、NSScrollViewをカスタムビューに追加したいのですが、Interface Builder(Embed Into Scroll View)を使用せずに、プログラムで追加する必要があります。

私はこのコードを見つけました:

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

上記の変数「mainWindow」と「scrollView」をIBOutletsとして宣言したとすると、Interface Builderの適切なコンポーネントにそれらを接続するにはどうすればよいですか?このようにするのは意味がありますか?

または、プログラムでスクロールビューを追加するためのより良い方法はありますか?

PS Interface BuilderからNSObjectオブジェクトを作成できないため、またはファイル所有者を使用できないため、通常の方法で接続できません。

4

4 に答える 4

16

プログラムで作成するのは困難でしたが、ようやく機能するようになりましNSScrollViewた。AutoLayoutこれはSwiftバージョンです。

// 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))

ここに画像の説明を入力してください

于 2017-09-26T16:27:37.247 に答える
9

このコードフラグメントは、NSScrollViewをプログラムで作成し、それを使用して、ペン先からでもコードからでも、任意のビューを表示する方法を示す必要があります。ペン先で生成されたビューの場合は、事前にペン先ファイルをカスタムビューにロードし、ファイルの所有者に対してカスタムビューへのアウトレット(outletToCustomViewLoadedFromNib)を作成する必要があります。

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];

Appleにはこのテーマに関するガイドがありますが、Apple Developer Connectionにアクセスする必要があり、リンクが頻繁に壊れるので、リンクしません。「スクロールビューの作成と構成」というタイトルで、現在Googleを使用してタイトルを検索すると見つかります。

于 2012-04-05T05:57:19.990 に答える
6

ブライアンの答えは正解です。Swift4.2で内部を作成する方法は次のとおりですNSStackViewNSScrollView

https://github.com/onmyway133/blog/issues/173を参照してください

あなたはひっくり返す必要があるかもしれませんNSClipView

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)
}
于 2019-03-18T10:23:26.500 に答える
2

NSStackViewにプログラム的に追加された例を次に示しNSScrollViewます。次のソリューションを使用して任意のビューを追加できますが、例としてNSStackViewを取り上げています。

自動レイアウトコードを簡潔に保つためにSnapKitを使用していますが、サードパーティの依存関係なしにアンカーを使用して制約を追加できます

// Create NSScrollView and add it as a subview in the desired location
let scrollView = NSScrollView()
scrollView.borderType = .noBorder
scrollView.verticalScrollElasticity = .none
addSubview(scrollView)
scrollView.snp.makeConstraints { $0.edges.equalToSuperview() } //match edges to superview

// Assign an instance of NSClipView to `contentView` property of `NSScrollView`
let clipView = NSClipView()
scrollView.contentView = clipView
clipView.snp.makeConstraints { $0.edges.equalTo(scrollView) }

// Assign whatever view you want to put inside scroll view to the `documentView` property.
// Also note I have added just 3 constraints; top bottom and left. That way stackview can freely expand on the right
scrollView.documentView = stackView
stackView.snp.makeConstraints { $0.top.bottom.left.equalTo(clipView) }

translatesAutoresizingMaskIntoConstraintsSnapKitはサブビューを内部で処理するため、サブビューを追加した後は使用していないことに注意してください。アンカーを使用して制約を追加する場合はtranslatesAutoresizingMaskIntoConstraints、プログラムで追加されるすべてのサブビューでfalseに設定されていることを確認してください。

于 2020-04-05T08:23:25.620 に答える