¿Puedo deshabilitar el diseño automático para una subvista específica en tiempo de ejecución?


104

Tengo una vista que necesita manipular su marco mediante programación: es una especie de vista de documento que se ajusta a su contenido, que luego se desplaza y hace zoom alrededor de una supervista manipulando el origen del marco. Autolayout lucha con esto en tiempo de ejecución.

Deshabilitar el diseño automático por completo parece un poco duro porque podría usarse razonablemente para manejar el diseño de las otras vistas. Parece que lo que podría querer es algún tipo de "restricción nula".

Respuestas:


168

Yo tuve el mismo problema. Pero lo he resuelto.
Sí, puede deshabilitar el diseño automático en tiempo de ejecución para un específico UIView, en lugar de deshabilitarlo para todo el xib o el guión gráfico que está configurado de forma predeterminada en Xcode 4.3 y versiones posteriores.

Configure translatesAutoresizingMaskIntoConstraintsen YES, antes de configurar el marco de su subvista:

self.exampleView.translatesAutoresizingMaskIntoConstraints = YES;
self.exampleView.frame = CGRectMake(20, 20, 50, 50);

2
Esto parece excesivo para algunos casos más complicados con muchas vistas. Para algo tan simple como esto, está bien.
esh

@MuhammadAamirALi eliminar la subvista y luego volver a agregarla puede disminuir el rendimiento. ¿Podemos archivar una mejor solución?
Nhat Dinh

2
@DinhNhat Aclaré la respuesta. No es necesario eliminar y volver a agregar la subvista.
Leandros

5
Me muestra una advertencia: "No se pueden satisfacer las restricciones simultáneamente".
NSPratik

1
Me salvaste el día ... traduceAutoresizingMaskIntoConstraints
Tintenklecks

50

Tuve un problema similar en el que Autolayout anulaba parte de la configuración de mi marco en el tiempo de ejecución (tenía una vista dinámica que en algunos casos empujaba un nuevo controlador de vista ... presionar y luego presionar Atrás restablecía la vista inicial).

Lo solucioné colocando mi código de manipulación en viewDidLayoutSubviewsmi View Controller. Esto parece ser llamado después de cualquier restricción que se llame a mojo, pero antes de viewDidAppear, por lo que el usuario no se da cuenta.


1
No funciona para self.navigationItem.titleView. Aún no respeta el cambio de cuadro.
Henrik Erlandsson

1
Si está tratando de modificar el marco de una vista de título, lo colocaría dentro de una vista de contenedor y agregaría la vista de contenedor como una vista personalizada de navigationItem.
jmstone617

2
Esto funcionó para mí también. Había desperdiciado 2h: 22m golpeándome la cabeza contra la pared proverbial antes de descubrir esta solución.
TMc

Gracias hombre. ¡Estoy en mi segundo día luchando con este problema y ahora funciona!
apostolov

28

Quizás solo establecer translatesAutoresizingMaskIntoConstraintsen YES(y no agregar restricciones adicionales que afecten esa vista) le permitirá configurar el marco sin luchar contra el sistema de diseño automático.


17

En iOS 8 puede configurar un NSLayoutConstraint para que esté activo o no. Entonces, si estoy usando el generador de interfaces, agrego todas mis restricciones a un OutletCollection y luego activo o desactivo usando:

NSLayoutConstraint.deactivateConstraints(self.landscapeConstraintsPad)
NSLayoutConstraint.activateConstraints(self.portraitConstraintsPad)

La aplicación particular para la que lo estoy usando aquí tiene diferentes restricciones en el modo vertical y horizontal y activo / desactivo en función de la rotación del dispositivo. Significa que puedo crear algunos cambios de diseño complejos en el generador de interfaces para ambas orientaciones, y aún usar el diseño automático sin el código de diseño automático detallado.

O puede activar / desactivar usando removeConstraints y addConstraints.


Perdón por secuestrar una pregunta tan antigua, pero ¿puedo preguntar cómo se las arregló para agregar restricciones de diseño para diferentes diseños en primer lugar? Parece que no puedo encontrar una opción dentro del generador de interfaces para habilitar / deshabilitar restricciones. ¿O simplemente agregó restricciones para ambos diseños y simplemente ignoró al creador de la interfaz quejándose de restricciones inválidas (anuladas)?
Malte

Bueno, podría hacerlo usando clases de tamaño: developer.apple.com/library/ios/recipes/… , pero no pude hacerlo de esta manera porque también era compatible con iOS 7 y las clases de tamaño no son totalmente compatibles con iOS 7 Lo hice reduciendo la prioridad de la restricción en conflicto. No es ideal, pero evita la advertencia. Creo que así es como lo hice de todos modos ....
bandejapaisa

9

No sé si esto ayudará a alguien más, pero escribí una categoría para que esto sea conveniente porque me encuentro haciendo esto mucho.

UIView + DisableAutolayoutTempontly.h

#import <UIKit/UIKit.h>

@interface UIView (DisableAutolayoutTemporarily)

// the view as a parameter is a convenience so we don't have to always
// guard against strong-reference cycles
- (void)resizeWithBlock:(void (^)(UIView *view))block;

@end

UIView + DisableAutolayoutTempontly.m

#import "UIView+DisableAutoResizeTemporarily.h"
@implementation UIView (DisableAutoResizeTemporarily)

- (void)resizeWithBlock:(void (^)(UIView * view))block
{
    UIView *superview = self.superview;
    [self removeFromSuperview];
    [self setTranslatesAutoresizingMaskIntoConstraints:YES];
    __weak UIView *weakSelf = self;
    block(weakSelf);
    [superview addSubview:self];
}

@end

Lo uso así:

[cell.argumentLabel resizeWithBlock:^(UIView *view) {
    [view setFrame:frame];
}];

Espero eso ayude.


¡Brillante! Usé una versión modificada de su código para escribir una función simple "hideControl" para cualquier UIView. Básicamente, establece la altura de una UIView en 0, pero, fundamentalmente, utiliza su código para hacer que AutoLayout lo maneje correctamente (a diferencia de usar "someView.hidden = TRUE"). Por lo tanto, los controles que aparecían debajo del control oculto y tenían un espacio vertical vinculado a él, ahora se desplazarían hacia arriba en la pantalla para llenar el espacio donde aparecía anteriormente la vista oculta.
Mike Gledhill

6

Puede establecer el translatesAutoresizingMaskIntoConstraintstipo Boolean, Valor Sí en los Atributos de tiempo de ejecución definidos por el usuario de la UIView que desee en el xib / storyboard.


2
  • Proyecto abierto en 4.5
  • Seleccionar guión gráfico
  • Abra el inspector de archivos
  • En Documento de Interface Builder, desmarque 'Usar diseño automático'

Puede dividir en varios guiones gráficos si desea utilizar el diseño automático para algunas vistas.


10
Eso deshabilita el diseño automático para todo el guión gráfico / plumilla. Lo que estaba buscando era una forma (idealmente programática) de tener subvistas particulares dentro de un guión gráfico / plumilla sin usar el diseño automático y dejar el resto haciendo lo que especifique el guión gráfico / plumilla.
terriblememory

Puede usar múltiples guiones gráficos y simplemente invocar los que tienen / sin diseño automático según sea necesario: // Inicialice el controlador de vista detallada y el tablero de almacenamiento para mostrar UIStoryboard * sb = [UIStoryboard storyboardWithName: @ "Storyboard" bundle: [NSBundle mainBundle]]; DetailViewController * dvController = [sb instantiateViewControllerWithIdentifier: entry.viewName];
Mike Bobbitt

1

Para mí, funcionó crear la subvista mediante programación, en mi caso, el diseño automático estaba jugando con una vista que necesitaba rotar alrededor de su centro, pero una vez que creé esta vista mediante programación, funcionó.


1

En mi opinión, tenía una etiqueta y un texto. La etiqueta tenía gesto de pan. La etiqueta se mueve bien durante el arrastre. Pero cuando utilizo el teclado del cuadro de texto, la etiqueta restablece su posición a la ubicación original definida en el diseño automático. El problema se resolvió cuando agregué lo siguiente rápidamente para la etiqueta. Agregué esto en viewWillAppear pero se puede agregar prácticamente en cualquier lugar donde tenga acceso al campo de destino.

self.captionUILabel.translatesAutoresizingMaskIntoConstraints = true

0

Esto me sucedió en un proyecto sin guiones gráficos o archivos xib. Todo el código 100%. Tenía un banner publicitario en la parte inferior y quería que los límites de visualización se detuvieran en el banner publicitario. La vista cambiaría de tamaño automáticamente después de la carga. Probé todas las resoluciones de esta página, pero ninguna funcionó.

Terminé creando una vista secundaria con la altura reducida y la coloqué en la vista principal del controlador. Luego, todo mi contenido entró en la vista secundaria. Eso resolvió el problema muy fácilmente sin hacer nada que pareciera que iba contra la corriente.

Estoy pensando que si desea una vista que no sea del tamaño normal que llena la ventana, entonces debería usar una vista secundaria para eso.


0

Encontré un escenario similar, en el que me uní a un proyecto que se inició con diseño automático, pero necesitaba hacer ajustes dinámicos en varias vistas. Esto es lo que me ha funcionado:

  1. NO tenga vistas o componentes dispuestos en el generador de interfaces.

  2. Agregue sus vistas de forma puramente programática comenzando con alloc / init y configurando sus marcos de manera adecuada.

  3. Hecho.


0

En lugar de deshabilitar el diseño automático, simplemente calcularía la nueva restricción con el marco que está reemplazando. Me parece que ésa es la forma adecuada. Si está ajustando componentes que dependen de restricciones, ajústelos en consecuencia.

Por ejemplo, si tiene una restricción vertical de 0 entre dos vistas (myView y otherView), y tiene un gesto de panorámica o algo que ajusta la altura de myView, puede volver a calcular la restricción con los valores ajustados.

self.verticalConstraint.constant = newMyViewYOriginValue - (self.otherView.frame.origin.y + self.otherView.frame.size.height);
[self.myView needsUpdateConstraints];

0

Para aquellos de ustedes que están usando el diseño automático, por favor revisen mi solución aquí . Debería hacer @IBOutletde las restricciones que desea ajustar y luego cambiar sus constantes.


-16

si es un archivo xib:

  1. seleccione el archivo .xib
  2. seleccione el "Propietario del archivo"
  3. mostrar las utilidades
  4. haga clic en: "Inspector de archivos"
  5. En "Documento de Interface Builder", inhabilita: "Usar diseño automático"

1
No, eso deshabilita el diseño automático para todo el xib. Lo que estaba buscando es una forma de eliminar solo una subvista particular del sistema de diseño automático.
terriblememory
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.