cocoa autoresizingmask nssplitview autolayout

cocoa - NSSplitView y autolayout



autoresizingmask (9)

10.8 solucionado ese problema, ver sus notas de lanzamiento.

Aquí está mi solución para 10.7 (una vista dividida personalizada): https://github.com/benuri/HASplitView.git

¿Cómo debo usar las restricciones de diseño automático dentro de la subvista NSSplitView ?

Mi subvista NSSplitView tiene 3 subvistas: topPane , tableContainer y bottomPane y configuro las restricciones de esta manera:

NSDictionary* views = NSDictionaryOfVariableBindings(topPane, tableContainer, bottomPane); for (NSView* view in [views allValues]) { [view setTranslatesAutoresizingMaskIntoConstraints:NO]; } [myView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topPane(34)][tableContainer][bottomPane(24)]|" options:0 metrics:nil views:views]]; [mySplitView addSubview:myView];

Y tengo esto en la consola:

Unable to simultaneously satisfy constraints: ( "<NSLayoutConstraint:0x7fd6c4b1f770 V:[NSScrollView:0x7fd6c4b234c0]-(0)-[CPane:0x7fd6c4b2fd10]>", "<NSLayoutConstraint:0x7fd6c4b30910 V:[CPane:0x7fd6c4b2f870(34)]>", "<NSLayoutConstraint:0x7fd6c4b30770 V:|-(0)-[CPane:0x7fd6c4b2f870] (Names: ''|'':NSView:0x7fd6c4b22e50 )>", "<NSLayoutConstraint:0x7fd6c4b212f0 V:[CPane:0x7fd6c4b2fd10]-(0)-| (Names: ''|'':NSView:0x7fd6c4b22e50 )>", "<NSLayoutConstraint:0x7fd6c4b2f910 V:[CPane:0x7fd6c4b2f870]-(0)-[NSScrollView:0x7fd6c4b234c0]>", "<NSLayoutConstraint:0x7fd6c4b21290 V:[CPane:0x7fd6c4b2fd10(24)]>", "<NSAutoresizingMaskLayoutConstraint:0x7fd6c3630430 h=--& v=--& V:[NSView:0x7fd6c4b22e50(0)]>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7fd6c4b1f770 V:[NSScrollView:0x7fd6c4b234c0]-(0)-[CPane:0x7fd6c4b2fd10]>

Creo que <NSAutoresizingMaskLayoutConstraint:0x7fd6c3630430 h=--& v=--& V:[NSView:0x7fd6c4b22e50(0)]> causa esto, pero no puedo restablecer la máscara automática, porque NSSplitView establece.

¿Cuál es la mejor manera de usar el diseño automático dentro de la vista dividida? ¿Y hay alguna manera de manejar el tamaño mínimo / máximo de la subvista de vista dividida con diseño automático sin NSSplitViewDelegate ?


Descubrí que este error aparece si tengo una barra de herramientas en mi ventana y controlo la vista dividida por cualquiera de estos métodos de delegado:

splitView:constrainMinCoordinate:ofSubviewAt: splitView:constrainMaxCoordinate:ofSubviewAt: splitView:shouldAdjustSizeOfSubview:

Se encontró una solución al adjuntar la barra de herramientas a la ventana en windowDidLoad.


Me tomó algo de tiempo limpiar mi advertencia de reproducción automática, pero sí la manejé en IB (varias vistas divididas y subvistas).

Mi diseño se ve como:

RootView
| - 1st NSSplitView (3 subvistas verticales)
| ---- UIView (izquierda)
| ---- 2do NSSplitView (centro y 2 subvistas horizontales)
| --- UIView (arriba)
| --- 3rd NSSplitView (inferior y 3 subvistas verticales)
| --- UIView (izquierda)
| --- UIView (centro)
| --- UIView (derecha)
| ---- UIView (derecha)

Mi problema era que tenía 19 Advertencias en todas mis subvistas, pero mi diseño se veía bien y funcionaba como debía ser. Después de un tiempo encontré la causa de mis advertencias: las restricciones de las vistas externas en mi primera vista dividida.

Ambas vistas (izquierda y derecha) tenían una restricción de ancho con "ancho> = 200" y la vista central (segunda vista dividida) no tenía restricciones (debido a que su ancho mínimo y su ancho máximo eran manejados por sus subvistas).

Las advertencias me mostraron que el autolayout quiere reducir mi IB-UI-Layout porque los anchos mínimos calculados eran más pequeños que mi diseño pero no quería reducirlos en IB.

Agregué una restricción fija "ancho = 200" a las dos subvistas externas de mi primera vista dividida y verifiqué "eliminar en tiempo de compilación".

Ahora mi diseño está libre de advertencias y todo funciona como debe ser.

Mi conclusión :

Creo que el problema con autolayout y splitviews es que autolayout no puede manejar las restricciones de ancho de las subvistas. La razón por la que deseamos utilizar las vistas divididas es que queremos el ancho dinámico de las vistas y lo queremos en ambas direcciones, reducción y expansión.

Entonces no hay ancho <= xxx && ancho> = xxx. Autolayout solo puede manejar uno de ellos y recibimos advertencias en IB. Puede solucionar este problema con una restricción temporal en IB que se eliminará antes del tiempo de ejecución.

Espero que tenga sentido lo que escribí, pero funcionó bien en mi proyecto.

PD: no pude encontrar ninguna solución hasta hoy donde encontré este hilo ... así que supongo que tus publicaciones me inspiraron :-)


NSSplitView ha sido algo extraño desde el principio y no me sorprendería que se fuera pronto. Después de intentar que NSSplitView trabajara con AutoLayout durante un mes y de hundirme de un ataque desesperado a otro, finalmente me di por vencido.

Mi solución es no usar NSSplitView con AutoLayout en absoluto. Entonces, ya sea NSSplitView sin Autolayout o Autolayout sin NSSplitView: esto no es tan complicado como parece: simplemente coloque sus subvistas uno junto al otro y agregue NSLayoutConstraints como IBOutlets . Las constantes de estas restricciones se pueden configurar y cambiar desde el controlador en el código. Con ese enfoque, puede establecer el origen (desplazamiento negativo para deslizarlo fuera de la ventana), el ancho y las relaciones con otras subvistas, además de que es realmente fácil animar las restricciones con el animador de la vista (¿alguna vez intentó animar un NSSplitView?)

Lo único que falta es el arrastre del mouse sobre los divisores, pero esto se puede implementar con un par de líneas, rastreando los eventos del mouse en su "SplitView" personalizado.

Hay un ejemplo de "vista dividida" de autolayout de Apple (desafortunadamente solo vertical) y últimamente he visto al menos un nuevo proyecto en github. Aunque para mí, pensé que sería más fácil volver a empezar con mi solución personalizada para las necesidades específicas de mi aplicación, en lugar de intentar crear algo muy universal (lo que lo hace demasiado complejo de manejar).

Edición: ahora completé mi splitView personalizado que carga sus subvistas desde puntas separadas. No hay problemas de restricción, no hay advertencias de reproducción automática. En comparación con todo el mes de intentar que funcione con NSSplitView, ahora tengo un splitView personalizado de trabajo basado en restricciones, fácilmente animable, creado en una sola noche. ¡Definitivamente recomiendo tomar esta ruta!


No desea deshabilitar translatesAutoresizingMaskIntoConstraints en absoluto. No debes meterte con las restricciones de las vistas del sistema. NSSplitView controla el tamaño de las vistas individuales y, en esencia, intenta eliminar su control. Sin mencionar, se olvidó de dar cuenta del divisor.

La forma correcta de establecer una anchura / altura mínima o máxima (o constante para el caso) en una vista dividida es establecer esas cosas en las vistas individualmente. En particular, si está haciendo esto en el código, necesitará usar 2 llamadas separadas areststWWVVualualFormat, porque de lo contrario el lenguaje de formato visual creará restricciones entre las vistas.

Puedes hacer todo esto en IB muy bien. Incluso puede establecer la prioridad de cada vista en la vista dividida, lo que hará que una u otra vista cambie de tamaño cuando la ventana lo haga, en lugar de distribuir el tamaño por igual.


Para cualquier persona que se tropiece con esto en el futuro y esté buscando un inicio NSSplitView reemplazos de NSSplitView basados ​​en restricciones, escribí un pequeño proyecto aquí que intenta recrear una parte de las NSSplitView de NSSplitView usando Auto Layout:

https://github.com/jwilling/JWSplitView

Es un poco buggy, pero podría ser una referencia útil para cualquiera que quiera ir por este camino.


Por mucho que odie estar en desacuerdo, pero la respuesta de Auco no debería ser votada como la más alta. No es de ninguna manera útil para resolver el problema con una cantidad adecuada de trabajo. En mi opinión, el NSSplitView solo fue un problema para aquellos que no leyeron la documentación lo suficientemente bien.

La solución real al problema mencionado aquí es bastante simple: Auto Layout introdujo la nueva "API de prioridades de retención" en NSSplitView. Y como dice la documentación: establecer valores más bajos para la prioridad de retención de una subvista hará que sea más probable que tome ancho antes. Todo esto se puede establecer en IB y programáticamente sin ninguna desesperación. La cantidad de trabajo necesario: 20 segundos aprox.


Utilicé esta clase como solución alternativa, no es perfecta (las subvistas tartamudean un poco) pero me desbloquearon. Utilizo esta clase como la clase personalizada dentro de cada panel de vista dividida.

@interface FBSplitPaneView : NSView @end @implementation FBSplitPaneView - (void)setFrame:(NSRect)frame { for (NSView *subview in self.subviews) { subview.frame = self.bounds; } [super setFrame:frame]; } @end


setTranslatesAutoresizingMaskIntoConstraints:NO todo por un archivo nib y setTranslatesAutoresizingMaskIntoConstraints:NO después.

Así que tal vez debería agregar primero por [mySplitView addSubview:myView]; Tus vistas y luego deshabilita la traducción de la máscara de tamaño automático a restricciones y después de esto, agregas tu contraintente a myView .

EDITAR:

Ok, parece que no entiendo el myView. Debe agregar la restricción a las subvistas y no a la vista dividida.

[topPane addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[topPane(34)]" options:0 metrics:nil views:views]]; [bottomPane addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[bottomPane(24)]" options:0 metrics:nil views:views]];

No tiene que agregar restricciones de borde (el "|" en "V: | [topPane (34)]") porque las subvistas en NSSplitView ya están activando el tamaño automático.

Esto condujo a esto, por ejemplo, para la restricción topPane:

NOTA: ignorar el contenido de la subvista, son solo marcadores de posición