Siento que es una forma bastante común de paradigma para mostrar/ocultar UIViews, más a menudo UILabels, dependiendo de la lógica de negocio. Mi pregunta es, ¿cuál es la mejor manera de usar el diseño Automático para responder a escondidas vistas como si su marco era 0x0. Aquí está un ejemplo de una lista dinámica de 1-3 características.

Autodiseño con hidden UIViews?

Ahora tengo una 10px superior del espacio desde el botón de la última etiqueta, que obviamente no se deslice hacia arriba cuando la etiqueta está oculto. A partir de ahora he creado una salida a esta restricción y modificación de la constante dependiendo de cuántas etiquetas estoy mostrando. Esta es, obviamente, un poco chapucero ya estoy usando negativo de la constante de valores para presionar el botón hasta el más oculto de los marcos. También es malo porque no se limita a la disposición de los elementos, apenas disimulada de los cálculos estáticos basados en alturas conocidas/relleno de otros elementos, y, obviamente, la lucha en contra de lo que Autodiseño fue construido para.

Podía, evidentemente, crear nuevas limitaciones en función de mi dinámica de etiquetas, pero eso es un montón de microgestión y un montón de verbosidad para intentar simplemente colapsar algunos espacios. Hay mejores enfoques? El cambio de tamaño del marco de 0,0 y dejar Autodiseño de hacer su cosa sin la manipulación de las restricciones? Eliminación de puntos de vista completamente?

Honestamente, sin embargo, sólo la modificación de la constante de contexto oculta de la vista requiere una sola línea de código con un simple cálculo. Recrear nuevas restricciones con constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: parece tan pesado.

Edición de Febrero de 2018: Ver Ben respuesta con UIStackViews

  • Gracias Ryan para esta pregunta . Me estaba volviendo loco ¿qué hacer en los casos a los que ha pedido . Cada vez que echa un vistazo por el tutorial para el diseño automático , la mayoría de ellos dice que se refieren a raywenderlich tutorial sitio que me parece un poco difícil de hacer.

12 Comentarios

  1. 78

    UIStackView es probablemente el camino a seguir para iOS 9+. No sólo manejar el oculto de la vista, también eliminará el espacio adicional y los márgenes de si se ha configurado correctamente.

    • Ten cuidado al usar UIStackView en un UITableViewCell. Para mí, una vez que la vista se puso muy complicado el desplazamiento comenzó a ser entrecortada donde se iba a tartamudear cada vez que una célula se desplaza in/out. Bajo las cubiertas de la StackView es la adición/eliminación de restricciones y no necesariamente será lo suficientemente eficiente para el desplazamiento suave.
    • Sería bueno dar un pequeño ejemplo de cómo la pila de vista se encarga de esto.
    • es este sigue siendo un problema en iOS 10?
    • Cinco años más tarde… debo actualizar y configurar este como el aceptado la respuesta? Se ha estado disponible para los tres ciclos de liberación de ahora.
    • Usted debe, definitivamente esta es la mejor respuesta ahora. Gracias Ben!
    • Estoy usando UIStackView pero no soy capaz de trabajar con mostrar/ocultar campos correctamente. Compruebe por favor mi pregunta y me sugieren algo. Por favor, siga este enlace stackoverflow.com/questions/51720099/…

  2. 231

    Mi preferencia personal para mostrar/ocultar las vistas es crear un IBOutlet con el ancho o la altura de la restricción.

    Yo, a continuación, actualizar el constant valor a 0 para ocultar, o cualquiera que sea el valor que se debe mostrar.

    La gran ventaja de esta técnica es que la relación restricciones se mantendrán. Por ejemplo, digamos que usted tiene ver Una y ver B con un espacio horizontal de x. Cuando la vista de Una anchura constant se establece en 0.f, a continuación, ver B se mueve a la izquierda para llenar ese espacio.

    No hay necesidad de agregar o quitar restricciones, que es un peso pesado de la operación. Simplemente la actualización de la restricción del constant hará el truco.

    • Me gusta mucho esta respuesta. Así que, básicamente, si estoy entendiendo bien, conjunto de altura fija o restricción de peso, crear un IBOutlet de esas restricciones, y si este punto de vista está oculta simplemente cambiar a una constante de 0.f y el resto de los elementos debe caer en su lugar?
    • exactamente. Como el tiempo – en este ejemplo – que la posición de la vista de B a la derecha de la vista mediante el uso de Un espacio horizontal. Yo uso esta técnica todo el tiempo y funciona muy bien
    • ¿Qué pasa si la etiqueta es potencialmente multi-línea? En este caso, una altura de restricción no sería apropiado, ¿verdad?
    • Hola Mark vi tu post en twitter, en realidad. Supongo que en tu caso la etiqueta es variable altura? Esto debería funcionar bien, pero la altura supuesto tendrá que ajustar el contenido utilizando boundingRectWithSize. Me pregunto si tendrás que calcular previamente las alturas para cada celda.
    • Sólo para asegurarse de que: si la brecha entre los dos puntos de vista son x, para que la vista de B para que se inicie desde la vista de Una posición, también debemos cambiar la brecha de la restricción de la constante a 0, también, derecho?
    • sí, si no tendría que ser un espacio horizontal de restricción entre los dos puntos de vista. constante de 0 significa ninguna diferencia. Para ocultar de la vista de Una por establecer la anchura de 0 movería vista de la B a la izquierda para quedar a ras con el contenedor. Por cierto gracias por los votos!
    • Gracias por tu respuesta. He intentado hacer esto con un UIView que contiene otros puntos de vista, pero que a la vista del subvistas no se oculta cuando me puse a su altura restricción a 0. Es esta solución supone trabajar con las vistas que contengan subvistas? Gracias!
    • También agradecería una solución que funciona para una UIView que contiene otros puntos de vista…
    • Creo que tu solución para mi problema. Si es así ¿podría dar un ejemplo de código ya que soy nuevo en el desarrollo de IOS y limitaciones que realmente me confundan. Este es el post stackoverflow.com/questions/27347937/… @MaxMacLeod
    • Así que la pregunta en este, ya que este es verdaderamente el diseño automático, ¿cómo se sabe lo que para establecer la altura? Quieres tener el control de restablecer su altura, y si es así, ¿cómo?
    • gran pregunta. Una etiqueta puede tener dimensiones automáticamente con intrínseco tamaño del contenido. Sin embargo, de que no va a funcionar en este caso como tendrá una explícita la altura de la restricción. Así que usted está o va a tener la altura codificado en el Xib – observó en el controlador de vista o el conjunto completo mediante programación en el controlador de vista.
    • Gracias @Max MacLeod, Pero tengo un pequeño problema. Mi punto de vista ha vertical, márgenes, por lo que incluso si añado un cero a la altura de la restricción con alta o la prioridad requerida, entonces veo un error en la consola, ya que estas restricciones no satisfecho al mismo tiempo.

  3. 95

    La solución de utilizar un constante 0 cuando oculto y otra constante si la vuelva a mostrar es funcional, pero es insuficiente si su contenido tiene un flexible de tamaño. Tendría que medir su contenido flexible y establecer una constante. Esto se siente mal y tiene problemas en el caso de que el contenido cambia el tamaño a causa de servidor o eventos de interfaz de usuario.

    Tengo una mejor solución.

    La idea es establecer un 0 en la altura de la regla para tener una alta prioridad al ocultar el elemento de modo que no toma no autodiseño espacio.

    Aquí es cómo hacerlo:

    1. configurar una anchura (o altura) de 0 en el interface builder con una prioridad baja.

    Autodiseño con hidden UIViews?

    Interface Builder no gritar acerca de los conflictos, porque la prioridad es baja. Prueba de la altura de comportamiento mediante el establecimiento de la prioridad a 999 temporalmente (1000 está prohibido a mutar mediante programación, así que no lo uso). Interface builder, probablemente ahora gritar acerca de conflicto de restricciones. Puede solucionar estos mediante el establecimiento de prioridades en relación con los objetos a 900 o así.

    2. Añadir una toma de corriente de modo que usted puede modificar la prioridad del ancho de restricción en el código:

    Autodiseño con hidden UIViews?

    3. Ajustar la prioridad a la hora de ocultar su elemento:

    cell.alertTimingView.hidden    = place.closingSoon != true
    cell.alertTimingWidth.priority = place.closingSoon == true ? 250 : 999
    • puede usted decirme por favor qué es este lugar.closingSoon?
    • No es parte de la solución general, @Niharika, Es justo lo que la regla de negocio fue en mi caso (mostrar la vista si el restaurante es / no es cerrar pronto).
  4. 11

    En este caso, yo mapa de la altura de la Autora de la etiqueta para una adecuada IBOutlet:

    @property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

    y cuando me puse a la altura de la restricción a 0.0 f, podemos preservar el «relleno», porque el botón de Play de la altura lo permite.

    cell.authorLabelHeight.constant = 0; //Hide 
    cell.authorLabelHeight.constant = 44; //Show

    Autodiseño con hidden UIViews?
    Autodiseño con hidden UIViews?

  5. 5

    Subclase de la vista y reemplazar func intrinsicContentSize() -> CGSize. Acabo de volver de CGSizeZero si la vista está oculta.

    • Esto es genial. Algunos elementos de interfaz de usuario necesita un gatillo para invalidateIntrinsicContentSize aunque. Usted puede hacer eso en una reemplazado setHidden.
  6. 4

    Estoy sorprendido de que no hay un enfoque más elegante proporcionada por UIKit para este comportamiento deseado. Parece una cosa muy comun que quieren ser capaces de hacer.

    Dado que la conexión de las restricciones a IBOutlets y ajuste de las constantes a 0 sentía asqueroso (y causó NSLayoutConstraint advertencias cuando su vista se había subvistas), he decidido crear una extensión que le da un simple, el estado de enfoque para mostrar/ocultar un UIView que tiene Auto restricciones de Diseño

    Simplemente oculta la vista y elimina el exterior de las restricciones. Cuando se muestre la vista de nuevo, se añade a las limitaciones de la espalda. La única salvedad es que usted necesita para especificar flexible de conmutación por error de restricciones a los alrededores vistas.

    Editar
    Esta respuesta está dirigido a iOS 8.4 y abajo. En iOS 9, sólo tiene que utilizar el UIStackView enfoque.

    • Este es mi método preferido también. Es una mejora significativa en otras respuestas aquí, ya que no sólo la calabaza de la vista a tamaño cero. La calabaza enfoque ha repercutirán en problemas por nada pero bastante trivial pagos. Un ejemplo de esto es la gran diferencia, donde el elemento oculto se encuentra en esta otra respuesta. Y usted puede terminar con la restricción de las violaciones mencionadas.
    • Gracias por decírmelo. He actualizado la licencia MIT. Sin embargo, yo no requieren mental de alta cinco cada vez que alguien se implementa esta solución.
  7. 4

    Me acabo de enterar de que para conseguir un UILabel para que no ocupen espacio, usted tiene que ocultar Y establecer su texto a una cadena vacía. (iOS 9)

    Conociendo este hecho/error podría ayudar a algunas personas a simplificar sus diseños, posiblemente, incluso la de la pregunta original, así que pensé en publicarlo.

    • No creo que usted necesita para ocultarlo. Configuración de su texto a una cadena vacía, debería bastar.
  8. 4

    Hay un montón de soluciones de aquí, pero mi enfoque es diferente de nuevo 🙂

    Establecer dos conjuntos de restricciones similares a Jorge Arimany y TMin la respuesta:

    Autodiseño con hidden UIViews?

    Los tres marcadas limitaciones que tienen el mismo valor para la Constante. Las restricciones marcadas A1 y A2 tienen su Prioridad a 500, mientras que la restricción marcada B tiene Prioridad establecido en 250 (o UILayoutProperty.defaultLow en el código).

    Gancho de la restricción de la B a un IBOutlet. Entonces, cuando se oculta el elemento, sólo se necesita para establecer la restricción de prioridad alta (750):

    constraintB.priority = .defaultHigh

    Pero cuando el elemento es visible, establecer la prioridad de la espalda baja (250):

    constraintB.priority = .defaultLow

    El (es cierto que los menores de edad) de las ventajas de este enfoque sobre el cambio de isActive de la restricción B es que usted todavía tiene un trabajo de restricción si el elemento transitorio se elimina de la vista por otros medios.

    • Esto tiene las ventajas de no tener valores duplicados en el Guión gráfico y el código como elemento de altura/anchura. Muy elegante.
    • Gracias!! Me ayudó
    • Gran Enfoque, Gracias
  9. 3

    La mejor práctica es, una vez que todo lo que tiene la correcta restricciones de diseño, añadir una altura o con restricción, dependiendo de cómo desee las vistas de los alrededores para mover y conectar la restricción en un IBOutlet de la propiedad.

    Asegúrese de que sus propiedades están strong

    en el código yo sólo hay que establecer la constante a 0 y activar que, tho ocultar el contenido, o desactivar para mostrar el contenido.
    Esto es mejor que pelee con el valor constante de un ahorro en el de la restauración.
    No te olvides de llamar a layoutIfNeeded después.

    Si el contenido oculto se agrupan, la mejor práctica es poner a todos en una vista y agregar las restricciones a la vista

    @property (strong, nonatomic) IBOutlet UIView *myContainer;
    @property (strong, nonatomic) IBOutlet NSLayoutConstraint *myContainerHeight; //should be strong!!

    -(void) showContainer
    {
        self.myContainerHeight.active = NO;
        self.myContainer.hidden = NO;
        [self.view layoutIfNeeded];
    }
    -(void) hideContainer
    {
        self.myContainerHeight.active = YES;
        self.myContainerHeight.constant = 0.0f;
        self.myContainer.hidden = YES;
        [self.view layoutIfNeeded];
    }

    Una vez que tenga la configuración que usted puede probar en IntefaceBuilder por la configuración de la restricción a 0 y, a continuación, volver al valor original. No te olvides de consultar otras restricciones de prioridades así que cuando oculto no hay ningún conflicto en absoluto. otra forma de probar es ponerlo a 0 y establecer la prioridad a 0, pero, usted no debe olvidar a restaurar la más alta prioridad.

    • Eso es porque la restricción y la vista no siempre va a ser retenido por el punto de vista de la jerarquía, por lo que si se desactiva la restricción y ocultar de la vista que todavía retener a aparecer de nuevo, independientemente de lo que su punto de vista de la jerarquía de decidir conservar o no.
  10. 2

    Mi método preferido es muy similar a la sugerida por Jorge Arimany.

    Prefiero crear varias restricciones. En primer lugar crea tu restricciones para cuando la segunda etiqueta es visible. Crear una salida para la restricción entre el botón y el 2º de la etiqueta (si usted está utilizando objc asegúrese de que su fuerte). Esta restricción se determina la altura entre el botón y la segunda etiqueta cuando es visible.

    A continuación, crear otra restricción que especifica la altura entre el botón y la etiqueta de la parte superior cuando el segundo botón está oculto. Crear una toma de corriente para la segunda restricción y asegúrese de que esta toma tiene una fuerte puntero. A continuación, desmarque la installed casilla de verificación en el interface builder, y asegúrese de que la primera restricción, su prioridad es menor que el de este segundo restricciones de prioridad.

    Finalmente al ocultar la segunda etiqueta, cambiar el .isActive propiedad de estas limitaciones y de la llamada setNeedsDisplay()

    Y que es, sin la Magia de los números, las matemáticas no, si usted tiene varias restricciones para encender y apagar usted puede incluso utilizar la salida de las colecciones para mantenerlos organizados por el estado. (También conocido como mantener todo lo oculto de las restricciones en un OutletCollection y la no-ocultos en la otra y sólo iterar sobre cada colección alternar sus .isActive estado).

    Sé Ryan Romanchuk dijo que él no desea utilizar varias limitaciones, pero siento que esto no es micro-administrar-y, y es más simple de lo que de forma dinámica en la creación de vistas y restricciones de programación (que es lo que yo creo que él fue el deseo de evitar si estoy leyendo la pregunta de la derecha).

    He creado un ejemplo sencillo, espero que sea útil…

    import UIKit
    
    class ViewController: UIViewController {
    
        @IBOutlet var ToBeHiddenLabel: UILabel!
    
    
        @IBOutlet var hiddenConstraint: NSLayoutConstraint!
        @IBOutlet var notHiddenConstraint: NSLayoutConstraint!
    
    
        @IBAction func HideMiddleButton(_ sender: Any) {
    
            ToBeHiddenLabel.isHidden = !ToBeHiddenLabel.isHidden
            notHiddenConstraint.isActive = !notHiddenConstraint.isActive
            hiddenConstraint.isActive = !hiddenConstraint.isActive
    
            self.view.setNeedsDisplay()
        }
    }

    Autodiseño con hidden UIViews?

  11. 0

    Voy a dar mi solución, para ofrecer variedad .) Creo que la creación de una toma de corriente para cada elemento de la anchura/altura de más para que el espacio es simplemente ridículo y sopla por el código, los posibles errores y el número de complicaciones.

    Mi método elimina todos los puntos de vista (en mi caso UIImageView casos), selecciona las que necesitan ser añadido la espalda, y en un bucle, se agrega de nuevo cada uno y crea nuevas restricciones. De hecho, es muy simple, por favor, siga a través de. Aquí está mi rápido y sucio código para hacerlo:

    //remove all views
    [self.twitterImageView removeFromSuperview];
    [self.localQuestionImageView removeFromSuperview];
    
    //self.recipients always has to be present
    NSMutableArray *items;
    items = [@[self.recipients] mutableCopy];
    
    //optionally add the twitter image
    if (self.question.sharedOnTwitter.boolValue) {
        [items addObject:self.twitterImageView];
    }
    
    //optionally add the location image
    if (self.question.isLocal) {
        [items addObject:self.localQuestionImageView];
    }
    
    UIView *previousItem;
    UIView *currentItem;
    
    previousItem = items[0];
    [self.contentView addSubview:previousItem];
    
    //now loop through, add the items and the constraints
    for (int i = 1; i < items.count; i++) {
        previousItem = items[i - 1];
        currentItem = items[i];
    
        [self.contentView addSubview:currentItem];
    
        [currentItem mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.centerY.equalTo(previousItem.mas_centerY);
            make.right.equalTo(previousItem.mas_left).offset(-5);
        }];
    }
    
    
    //here I just connect the left-most UILabel to the last UIView in the list, whichever that was
    previousItem = items.lastObject;
    
    [self.userName mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(previousItem.mas_left);
        make.leading.equalTo(self.text.mas_leading);
        make.centerY.equalTo(self.attachmentIndicator.mas_centerY);;
    }];

    I get clean, diseño consistente y espaciado. Mi código utiliza la Masonería, lo recomiendo: https://github.com/SnapKit/Masonry

Dejar respuesta

Please enter your comment!
Please enter your name here