Cómo agregar relleno principal para ver agregado dentro de un UIStackView

125

Esta es mi configuración: tengo un UIScrollViewcon borde de prueba superior, superior establecido en 0. Dentro de esto agrego un UIStackViewcon estas restricciones:

stackView.centerYAnchor.constraintEqualToAnchor(selectedContactsScrollView.centerYAnchor).active = true  
stackView.leadingAnchor.constraintEqualToAnchor(selectedContactsScrollView.leadingAnchor).active = true

Dentro de la vista de pila agrego algunas vistas.
Mi problema es que, debido a las restricciones, la primera vista agregada a la vista de pila también tendrá borde de ataque = 0.

¿De qué maneras podría agregar algo de relleno a la primera vista? Sin ajustar las restricciones de la vista de desplazamiento.

Adrian
fuente
2
¿quieres cambiar la respuesta aceptada? La respuesta de Tolga parece mucho mejor.
Miel el

Respuestas:

26

La solución que ha proporcionado no agrega un relleno para sus vistas dentro de su UIStackView (como quería en la pregunta), pero agrega una ventaja para UIStackView.

Una solución podría ser agregar otro UIStackView dentro de su UIStackView original y dar el liderazgo a este nuevo UIStackVIew. Luego, agregue sus puntos de vista a este nuevo UIStackView.

Sugerencia, puede hacerlo completamente usando Interface Builder. En otras palabras, no es necesario escribir código para ello.

William Kinaan
fuente
373

Cuando la isLayoutMarginsRelativeArrangementpropiedad es verdadera, la vista de pila distribuirá sus vistas organizadas en relación con sus márgenes de diseño.

stackView.layoutMargins = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
stackView.isLayoutMarginsRelativeArrangement = true

Pero afecta a todas las vistas organizadas dentro de la vista de pila. Si desea este relleno para una sola vista organizada, debe usar anidadoUIStackView

Tolga Okur
fuente
2
isLayoutMarginsRelativeArrangementes un getter, setter es layoutMarginsRelativeArrangement. No puedo editar la respuesta
cruzada el
55
@maross no hay diferencia entre la función getter y setter en Swift. Pero tienes razón, las personas que se desarrollan con Objective-C deberían usar layoutMarginsRelativeArrangementen su lugar. Documentación oficial: developer.apple.com/reference/uikit/uistackview/…
Tolga Okur
3
Para Objective-C:stackView.layoutMargins = UIEdgeInsetsMake(0, 20, 0, 20); [stackView setLayoutMarginsRelativeArrangement:YES];
Snouto el
44
Febrero de 2019, a la medianoche sentado en la oficina : respuestas como estas me dan la fuerza para seguir adelante. Gracias @tolpp
nefarianblack
155

He descubierto que las restricciones no funcionan dentro de una Vista de pila, o parecen algo extrañas.

(Por ejemplo, si agrego la restricción de inicio / finalización a la seleccionada en la vista de pila de imágenes, eso también agrega la inicialización a la vista de colección, pero no agrega el final; y seguramente será un conflicto).

stackview dentro de stackview

Para establecer márgenes de diseño para todas las vistas dentro de la vista de pila, seleccione:

Stack View > Size Inspector > Layout Margins > Fixed

Nota: la "Fixed"opción se llamaba anteriormente "Explicit", como se ve en las capturas de pantalla.

Luego agrega tu relleno:

guión gráfico

Zaporozhchenko Oleksandr
fuente
23
Una de las cosas que Apple esconde. Odio que Xcode sea lo opuesto a bueno, amigable y fácil. Gracias
Duck
Xcode sigue fallando cuando cambio esos márgenes de diseño explícitos. Archivó un error pero respondieron que era un duplicado.
mvandillen
Eso es lo que no pude encontrar en la interfaz de usuario. Cambie Márgenes de diseño a Explícito para ver los campos de los márgenes de Vista de pila.
pkamb
13
FYI XCode 9 ahora llama a esto "Fijo" en lugar de "Explícito".
Mel
También en Xcode 9, desmarque "Usar guías de diseño de área segura" en el inspector de archivos, que al momento de escribir aún causa muchos problemas en IB, y siga las guías de diseño normales para sus restricciones.
PJ_Finnegan
16

Lo que funcionó para mí es agregar a la vista de pila otra UIView que es solo un espaciador (funciona al menos con stackView.distribution = .Fill):

let spacerView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
stackView.addArrangedSubview(spacerView)
stackView.addArrangedSubview(viewThatNeedsSpaceBeforeIt)
stackView.addArrangedSubview(NextView)...
dorsz
fuente
6

Swift 3: solo necesita establecer el desplazamiento mediante:

firstView.leadingAnchor.constraint(equalTo: parentView.leadingAnchor, constant: 200).isActive = true

Asegúrese de que esta restricción se establezca después de usted parentView.addArrangdSubView(firstView)

William Hu
fuente
4

Si solo necesita relleno inicial, puede establecer la Alineación de la vista de pila en "Trailing" y luego podrá especificar restricciones iniciales únicas en cada una de sus subvistas contenidas.

Como beneficio adicional, también puede establecer la alineación de la vista de la pila en "Centro" y luego puede usar las restricciones iniciales y / o finales para dar a cada elemento su propio relleno en ambos lados.

Jonathan Parham
fuente
1

Esta pregunta ya tiene buenas respuestas. Sin embargo, una sugerencia es usar la spacingpropiedad para establecer el espacio entre las vistas. Para la primera y la última vista, puede haber dos opciones: establecer inserciones como @tolpp sugirió o agregar restricciones adjuntas al padre (stackview) con constante para agregar relleno.

Bucle infinito
fuente
0

Lo que hicimos fue agregar componentes transparentes (por ejemplo, UIButton / UIView) como el primer y último hijo de UIStackView. Luego establezca restringir el ancho de estos niños invisibles para ajustar el relleno.

Crashalot
fuente
0

La solución sería tener una vista regular en la vista de la pila para contener las vistas a las que desee agregar restricciones, y luego puede agregar restricciones para sus elementos que sean relativas a las vistas en la vista de la pila. De esa manera, sus vistas originales pueden tener restricciones iniciales y finales dentro de la vista de pila.

Esto se puede hacer en el generador de interfaces y programáticamente.

Aiden Dixon
fuente
-3

Parece que la solución fue bastante simple. En vez de:

stackView.leadingAnchor.constraintEqualToAnchor(selectedContactsScrollView.leadingAnchor).active = true

Acabo de escribir:

stackView.leadingAnchor.constraintEqualToAnchor(selectedContactsScrollView.leadingAnchor, constant: 15).active = true
Adrian
fuente
1
en realidad, su código agrega un encabezado para uistackview dentro de urscrollview, no agrega un relleno para sus vistas dentro de su uistackview, (como dice la pregunta)
William Kinaan
Sí, pero no sé si puedes agregar relleno, así que esto funcionará para mí.
Adrian
como primer pensamiento, puede otra vista de uistackview dentro de su vista de uistackview original y darle el relleno. luego agregue sus puntos de vista a esta nueva uistackview (puede hacerlo completamente por medio del creador de interfaces, no es necesario escribir código)
William Kinaan
Sí, eso funcionará. Puedes agregarlo como respuesta y lo aceptaré.
Adrian