NSScrollView com layout automático não redimensionado até que a primeira janela manual seja redimensionada
Eu tenho um aplicativo OSX Cocoa que foi construído de forma programática (ou seja, não com um NIB / XIB), que estou tentando fazer layouts usando o layout automático - mas estou tendo um comportamento estranho quando a janela é exibida pela primeira vez.
Meu conteúdo principal é um NSView que possui uma coleção de 100 NSButtons como sub-visualizações, dispostas verticalmente. Os botões são todos restritos em relação ao NSView e um ao outro; o NSView e todos os NSButtons têmtranslatesAutoresizingMaskIntoConstraints=NO
conjunto. Acredito que o código para a exibição do conteúdo seja bom (ou seja, sem layouts ambíguos etc.), porque se eu definir o contentView da janela principal como o NSView, os botões serão exibidos conforme o esperado.
No entanto, se eu definir o contentView da janela principal como um NSScrollView e definir o documentView do NSScrollView como o NSView, recebo problemas de exibição.
Na primeira exibição, recebo uma janela em branco - sem barras de rolagem, nada:
O NSScrollView possuitranslatesAutoresizingMaskIntoConstraints=NO
. Para fins de depuração, também defini a cor de fundo do NSScrollView como azul, para que eu possa confirmar o que está sendo definido onde - mas não há azul mostrado em qualquer lugar.
Mas, assim que redimensiono a janela, o layout entra em ação e recebo um NSScrollView em tamanho real da janela principal, com fundo azul e barras de rolagem conforme o esperado:
Eu li algumas referências que sugerem que o problema é a falta de restrições no clipView que faz parte do NSScrollView. Nessa base, tentei configurar a ligação de restrições[NSScrollView contentView]
para[NSScrollView documentView]
nas direções vertical e horizontal (com constante 0, multiplicador 1, à esquerda, direita, superior e inferior). Quando faço isso, o NSScrollView agora está visível no primeiro monitor, mas é do tamanho errado. A rolagem não rola a altura total do conteúdo interno - o conteúdo rolável rola como se tivesse o mesmo tamanho da janela visível. Por fim, o conteúdo se sobrepõe à barra de título da janela:
Novamente, assim que redimensiono a janela, as restrições entram em ação e a janela é exibida conforme o esperado (veja a captura de tela anterior). Então, suponho que as restrições extras não machucam, mas também não parecem adicionar nada.
Assuntos ainda mais confusos - se eu deixar os botões totalmente desativados e usar apenas um NSView vazio sem subvisões como a exibição do conteúdo, recebo uma janela cheia de azul na inicialização, como seria de esperar.
Então - o que está acontecendo aqui? Parece que estou perdendo uma chamada para forçar a avaliação de restrições nos botões; é esse o caso ou algo mais está acontecendo aqui?
Para os interessados - aqui está o meu código de exemplo. Não é o Objetivo C - é Python - mas a ligação da linguagem pode converter os nomes dos métodos Python em mensagens do Objetivo C; o mapeamento para a API nativa do ObjectiveC deve ser óbvio:
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()