2014-06-11 2 views
3

자동 레이아웃을 사용하여 레이아웃을 시도하는 프로그래밍 방식으로 (즉, NIB/XIB가 아닌) 빌드 된 OSX Cocoa 앱이 있습니다. 하지만 윈도우가 처음 표시 될 때 이상한 행동을하고 있습니다.자동 레이아웃이있는 NSScrollView가 첫 번째 수동 윈도우 크기가 조정될 때까지 크기가 조절되지 않습니다.

내 주요 콘텐츠는 보유하고있는 NSView이며 NSView는 100 개의 NSButton을 하위 뷰로 세로로 배치되어 있습니다. 버튼들은 모두 NSView와 다른 것들에 상대적으로 제한됩니다; NSView와 모든 NSButton에는 모두 translatesAutoresizingMaskIntoConstraints=NO이 설정됩니다. NSView에 기본 창의 contentView를 설정하면 버튼이 예상대로 표시되기 때문에 콘텐츠보기의 코드가 좋다고 생각합니다 (예 : 모호한 레이아웃 등).

그러나 메인 윈도우의 contentView를 NSScrollView로 설정하고 NSView의 NSViewView의 documentView를 NSView로 설정하면 디스플레이 문제가 발생합니다. 첫째 디스플레이에

, 나는 빈 창을받을 - 아니 스크롤 막대를, 아무것도 :

initial window display

NSScrollView이 translatesAutoresizingMaskIntoConstraints=NO 있습니다. 디버그 목적을 위해 NSScrollView의 배경색을 파란색으로 설정 했으므로 어디에 배치되는지 확인할 수 있습니다. 그러나 아무 곳에 나 파란색이 표시되지 않습니다. 예상대로 내가 창 크기를 조정으로

그러나, 곧, 레이아웃에서 개막, 나는 파란색 배경, 메인 윈도우의 전체 크기 NSScrollView를 얻고, 스크롤 :

display after window resize

문제는 NSScrollView의 일부인 clipView에 제약 조건이 없다는 것을 나타내는 몇 가지 참조를 읽었습니다. 그 근거로, 제약 조건을 [NSScrollView contentView]에서 [NSScrollView documentView]으로 수직 및 수평 방향 (상수 0, 배율 1, 왼쪽, 오른쪽, 상단 및 하단)으로 바인딩 설정을 시도했습니다. 이 작업을 수행하면 NSScrollView가 첫 번째 디스플레이에 표시되지만 크기가 잘못되었습니다. 스크롤은 내부 내용의 전체 높이를 스크롤하지 않습니다. 스크롤 가능한 내용은 보이는 창과 크기가 같은 것처럼 스크롤됩니다. 나는 창 크기를 조정 한 빨리, 제약 조건은 (이전 스크린 샷 참조) 내가 예상대로 킥, 및 윈도우 디스플레이,

Initial display, with NSScrollView constraints

다시 : 마지막으로, 내용은 창의 제목 표시 줄을 겹쳐 . 그래서, 나는 여분의 제약으로 인해 상처를 입지는 않지만 아무것도 추가하지 않는 것 같습니다.

더 혼란스러운 문제 - 버튼을 모두 끈 상태에서 컨텐츠 뷰로 서브 뷰가없는 비어있는 NSView를 사용하면 예상대로 파란색으로 시작할 때 파란색 창이 나타납니다.

그래서 - 여기 무슨 일 이니? 버튼에 대한 제약 조건 평가를 강제하는 호출이 누락 된 것처럼 느껴집니다. 그 사건인가, 아니면 다른 일이 여기에 있습니까?

관심있는 사람들을 위해 - 여기 내 샘플 코드가 있습니다. Objective C가 아니라 Python입니다. 그러나 언어 바인딩은 Python 메서드 이름을 Objective C 메시지로 변환 할 수 있습니다. 나는 그것과 완전히 행복하지 않다, 그러나 작동하는 것 같다 - 내가 대답을 근무했습니다

app = NSApplication.sharedApplication() 
app.setActivationPolicy_(NSApplicationActivationPolicyRegular) 

main_window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer_(
    NSMakeRect(100, 100, 640, 480), 
    NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask, 
    NSBackingStoreBuffered, 
    False) 

scrollview = NSScrollView.alloc().init() 
scrollview.setHasVerticalScroller_(True) 
scrollview.setHasHorizontalScroller_(True) 
scrollview.setAutohidesScrollers_(True) 
scrollview.setBorderType_(NSNoBorder) 
scrollview.setTranslatesAutoresizingMaskIntoConstraints_(False) 

scrollview.backgroundColor = NSColor.blueColor() 

container = NSView.alloc().init() 
container.setTranslatesAutoresizingMaskIntoConstraints_(False) 

buttons = [ 
    NSButton.alloc().init() 
    for b in range(0, 100) 
] 

for i, button in enumerate(buttons): 
    button.setBezelStyle_(NSRoundedBezelStyle) 
    button.setButtonType_(NSMomentaryPushInButton) 
    button.setTitle_(get_NSString('Button %s' % i)) 
    button.setTranslatesAutoresizingMaskIntoConstraints_(False) 

    container.addSubview_(button) 

    if i == 0: 
     container.addConstraint_(NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_(
      button, NSLayoutAttributeTop, 
      NSLayoutRelationEqual, 
      container, NSLayoutAttributeTop, 
      1, 50, 
     )) 
    else: 
     container.addConstraint_(NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_(
      button, NSLayoutAttributeBottom, 
      NSLayoutRelationEqual, 
      buttons[i-1], NSLayoutAttributeBottom, 
      1, 50, 
     )) 

    container.addConstraint_(NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_(
     button, NSLayoutAttributeLeft, 
     NSLayoutRelationEqual, 
     container, NSLayoutAttributeLeft, 
     1, 50, 
    )) 

    container.addConstraint_(NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_(
     button, NSLayoutAttributeRight, 
     NSLayoutRelationEqual, 
     container, NSLayoutAttributeRight, 
     1, -50, 
    )) 

container.addConstraint_(NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant_(
    buttons[-1], NSLayoutAttributeBottom, 
    NSLayoutRelationEqual, 
    container, NSLayoutAttributeBottom, 
    1, -50, 
)) 

scrollview.setDocumentView_(container) 

main_window.setContentView_(scrollview) 

main_window.makeKeyAndOrderFront_(None) 

app.activateIgnoringOtherApps_(True) 
app.run() 
+0

문제에 대한 추가 설명이 될 수있는 설명 - 크기 조정 *은 가로 크기 조정이어야합니다. 수직 크기 조정은 구속 조건을 재평가하지 않습니다. 그러나 세로로 크기를 조정 한 다음 가로 크기를 조정하면 모든 것이 화면을 채우도록 조정됩니다. – freakboy3742

+0

두 번째 설명 -이 코드는 Mavericks에서 예상대로 정확하게 작동하지만 Mountain Lion에서는 문제가 발생합니다. – freakboy3742

답변

7

: 기본 오브젝티브 -c API의 매핑은 명백해야한다.

자동 레이아웃을 제대로 처리하지 못하는 특정 코코아 위젯이 있습니다. 특히 최상위 레벨 NSWindowNSTabViewItem과 관련된 문제가 발견되었습니다. 다른 위젯이 영향을받을 수도 있습니다. 본질적으로, 이것들은 설정되어야하는 최상위 "보기"가있는 "컨테이너"위젯입니다. "포함 된"위젯이 NSScrollView (다른 위젯을 포함 함) 인 경우 "컨테이너"위젯은 "포함 된"스크롤 뷰의 크기를 설정하는 데 어려움이 있습니다.

해결 방법은 으로 "포함 된"위젯으로 사용할보기에translatesAutoresizingMaskIntoConstraints을 다시 사용하도록 설정합니다. 제공된 예제에서, 라인 10에서 생성 된 객체 scroll_view은 "포함 된"위젯입니다. 줄 15에있는 setTranslatesAutoresizingMaskIntoConstraints에 대한 호출의 부울 값은 이 아니라 True이되어야합니다.

이러한 문제는 OS/X의 최신 버전에서 더 좋아졌습니다. Mavericks는 NSWindow에 문제가 없지만 여전히 NSTabViewItem에 문제가 있습니다. 그러나 최신 버전의 OS X에서는 translatesAutoresizingMaskIntoConstraints을 켜기 위해 어떤 손상도없는 것 같습니다. 여러분은 100 % 자동 레이아웃 솔루션의 이론적 인 순결을 잃어 버릴 것입니다.

+0

매우 유용합니다! 나는 지난 3 시간 동안 제로 높이 스크롤 뷰 (명시 적 크기 제약 조건 포함)를 유지할 때를 파악하려고 노력 해왔다. ** 적어도 NSTabViewItem의 뷰로 설정된 모든 뷰 **는'translatesAutoresizingMaskIntoConstraints = YES'를 가져야합니다. –

+0

당신은 내 목숨을 구했고 영원히 감사드립니다. 저는 버그라고 생각합니다 ... 텍스트 뷰가 자체적으로 수직으로 크기 조정되는 프로젝트가 하나 있습니다 (https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/TextStorageLayer/Tasks/TrackingSize 참조). html # // apple_ref/doc/uid/20000927-CJBBIAAF), textview가 다른보기 안에있을 때 다른 프로젝트에서는 작동하지 않았습니다. 더 복잡한 프로젝트의 경우, 부모 뷰에 자동 레이아웃이 설정되어 있지 않더라도'translatesAutoresizingMaskIntoConstraints = true'로 설정하면 해결됩니다. –

0

실제 문제는 일부 컨트롤이보기의 크기를 고정 시켜서 창 크기를 고정시키는 것입니다. 당신은 단지 하나의 뷰가있는 경우 예를 들어, 당신의 ViewController의 내부보기 뷰 1 말을하고 :

  • 세트/후행/위/아래 기본보기와
  • view1.height = 300을 선도

이렇게하면 창 크기가 300으로 고정되므로 크기를 조정할 수 없습니다.

관련 문제