Diseñé mi celda personalizada en IB, la subclasifiqué y conecté mis salidas a mi clase personalizada. Tengo tres subvistas en el contenido de la celda que son: UIView (cdView) y dos etiquetas (titleLabel y emailLabel). Dependiendo de los datos disponibles para cada fila, a veces quiero que se muestren UIView y dos etiquetas en mi celda y, a veces, solo dos etiquetas. Lo que estoy tratando de hacer es establecer restricciones de esa manera si configuro la propiedad UIView como oculta o la eliminaré de la vista general, las dos etiquetas se moverán hacia la izquierda. Traté de establecer la restricción principal de UIView en Superview (contenido de celda) para 10px y las restricciones principales de UILabels para 10 px en la siguiente vista (UIView). Más tarde en mi código
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(IndexPath *)indexPath {
...
Record *record = [self.records objectAtIndex:indexPath.row];
if ([record.imageURL is equalToString:@""]) {
cell.cdView.hidden = YES;
}
Estoy ocultando mi cell.cdView y me gustaría que las etiquetas se muevan hacia la izquierda, sin embargo, se mantienen en la misma posición en Cell. Traté de eliminar cell.cdView de la supervista pero tampoco funcionó. He adjuntado una imagen para aclarar de qué se trata.
Sé cómo hacer esto programáticamente y no estoy buscando esa solución. Lo que quiero es establecer restricciones en IB y espero que mis subvistas se muevan dinámicamente si se eliminan u ocultan otras vistas. ¿Es posible hacer esto en IB con diseño automático?
.....
Respuestas:
Es posible, pero tendrás que hacer un poco de trabajo extra. Primero hay un par de cosas conceptuales que debes resolver:
En su caso, esto probablemente significa:
Lo que debe hacer es restringir juiciosamente sus etiquetas. Deje sus restricciones existentes (10 puntos de espacio para la otra vista) solo, pero agregue otra restricción: haga que los bordes izquierdos de sus etiquetas estén a 10 puntos del borde izquierdo de su supervista con una prioridad no requerida (la alta prioridad predeterminada probablemente funcionará bien).
Luego, cuando desee que se muevan hacia la izquierda, elimine la vista izquierda por completo. La restricción obligatoria de 10 puntos para la vista izquierda desaparecerá junto con la vista con la que se relaciona, y solo tendrá una restricción de alta prioridad para que las etiquetas estén a 10 puntos de distancia de su supervista. En la próxima pasada de diseño, esto debería hacer que se expandan a la izquierda hasta que llenen el ancho de la supervista, pero para su espacio alrededor de los bordes.
Una advertencia importante: si alguna vez desea que su vista izquierda vuelva a aparecer en la imagen, no solo tiene que volver a agregarla a la jerarquía de vistas, sino que también debe restablecer todas sus restricciones al mismo tiempo. Esto significa que necesita una forma de volver a colocar la restricción de espacio de 10 puntos entre la vista y sus etiquetas cada vez que se vuelve a mostrar esa vista.
fuente
|-(space)-[hidden(0)]-(space)-[visible]
es efectivo|-(2*space)-[visible]
. En segundo lugar, esa vista podría comenzar a generar infracciones de restricciones dependiendo de su propio subárbol de vista y restricciones: no puede garantizar que pueda restringir arbitrariamente una vista con un ancho de 0 y que siga funcionando.|-[otherViews]-[eitherThis][orThis]-|
, pero eventualmente me encontré con ese problema.Agregar o eliminar restricciones durante el tiempo de ejecución es una operación pesada que puede afectar el rendimiento. Sin embargo, hay una alternativa más simple.
Para la vista que desea ocultar, configure una restricción de ancho. Restrinja las otras vistas con un espacio horizontal principal para esa vista.
Para ocultar, actualice la
.constant
restricción de ancho a 0.f. Las otras vistas se moverán automáticamente a la izquierda para asumir la posición.Vea mi otra respuesta aquí para más detalles:
¿Cómo cambiar las restricciones de etiqueta durante el tiempo de ejecución?
fuente
Para aquellos que solo admiten iOS 8+ , hay una nueva propiedad booleana activa . Ayudará a habilitar solo las restricciones necesarias dinámicamente
La salida de restricción PS debe ser fuerte , no débil
Ejemplo:
Además, para corregir un error en el guión gráfico, deberá desmarcar la
Installed
casilla de verificación de una de estas restricciones.UIStackView (iOS 9+)
Una opción más es ajustar sus vistas
UIStackView
. Una vez que la vista esté oculta,UIStackView
se actualizará el diseño automáticamentefuente
UIStackView
reposiciona sus vistas automáticamente cuandohidden
se cambia la propiedad en cualquiera de sus subvistas (iOS 9+).Pase a las 11:48 en este video de WWDC para una demostración:
Misterios del diseño automático, parte 1
fuente
Mi proyecto utiliza una
@IBDesignable
subclase personalizada deUILabel
(para garantizar la coherencia en color, fuente, inserciones, etc.) y he implementado algo como lo siguiente:Esto permite que la subclase de etiquetas participe en el diseño automático, pero no ocupa espacio cuando está oculto.
fuente
Para los Googlers: basándose en la respuesta de Max, para resolver el problema del relleno que muchos han notado, simplemente aumenté la altura de la etiqueta y usé esa altura como separador en lugar del relleno real. Esta idea podría ampliarse para cualquier escenario con vistas que contengan.
Aquí hay un ejemplo simple:
En este caso, asigno la altura de la etiqueta Autor a un apropiado
IBOutlet
:y cuando establezco la altura de la restricción en
0.0f
, conservamos el "relleno", porque la altura del botón Reproducir lo permite.fuente
NSLayoutConstraint
Creo que desea actualizar laconstant
propiedad de suauthorLabelHeight
.conecte la restricción entre uiview y las etiquetas como IBOutlet y establezca el miembro de prioridad en un valor menor cuando se configura oculto = SÍ
fuente
Lo que terminé haciendo fue crear 2 xibs. Uno con la vista izquierda y otro sin ella. Registré ambos en el controlador y luego decidí cuál usar durante cellForRowAtIndexPath.
Usan la misma clase UITableViewCell. La desventaja es que hay cierta duplicación del contenido entre los xibs, pero estas celdas son bastante básicas. Lo bueno es que no tengo un montón de código para gestionar manualmente la eliminación de la vista, la actualización de restricciones, etc.
En general, esta es probablemente una mejor solución ya que son diseños técnicamente diferentes y, por lo tanto, deberían tener diferentes xibs.
fuente
En este caso, asigno la altura de la etiqueta Autor a un IBOutlet apropiado:
y cuando configuro la altura de la restricción a 0.0f, conservamos el "relleno", porque la altura del botón Reproducir lo permite.
fuente
Use dos UIStackView Horizontal y Vertical, cuando se oculta alguna vista de subvista en la pila, se moverán otras subvistas de pila, use Distribución -> Rellenar proporcionalmente para la pila Vertical con dos UILabels y necesita establecer constantes de ancho y alto para la primera UIView
fuente
Prueba esto, he implementado el siguiente código,
Tengo una Vista en ViewController que agregó otras tres vistas. Cuando cualquier vista esté oculta, se moverán otras dos vistas, siga los pasos a continuación. ,
1.ViewController.h File
2.ViewController.m
Espero que esta lógica ayude a alguien.
fuente
En mi caso establecí la constante de la restricción de altura en
0.0f
y también configuré lahidden
propiedad enYES
.Para mostrar la vista (con las subvistas) nuevamente hice lo contrario: establecí la altura constante en un valor distinto de cero y establecí la
hidden
propiedad enNO
.fuente
Usaré stackview horizontal. Puede eliminar el marco cuando la subvista está oculta.
En la imagen a continuación, la vista roja es el contenedor real de su contenido y tiene un espacio final de 10 puntos a la supervista naranja (MostrarOcultarVer), luego simplemente conecte MostrarOcultar a IBOutlet y muéstrelo / oculte / elimínelo programáticamente.
fuente
Esta es mi otra solución usando restricción de prioridad. La idea es establecer el ancho en 0.
crear vista de contenedor (naranja) y establecer el ancho.
cree una vista de contenido (rojo) y establezca el espacio final 10pt en supervista (naranja) Observe las restricciones de espacio final, hay 2 restricciones finales con diferente prioridad. Bajo (= 10) y Alto (<= 10). Esto es importante para evitar la ambigüedad.
Establezca el ancho de la vista naranja en 0 para ocultar la vista.
fuente
Como sugirió no_scene, definitivamente puede hacer esto cambiando la prioridad de la restricción en tiempo de ejecución. Esto fue mucho más fácil para mí porque tenía más de una vista de bloqueo que debía eliminarse.
Aquí hay un fragmento con ReactiveCocoa:
fuente
En caso de que esto ayude a alguien, construí una clase auxiliar para usar restricciones de formato visual . Lo estoy usando en mi aplicación actual.
AutolayoutHelper
Puede que esté un poco adaptado a mis necesidades, pero puede que le resulte útil o que desee modificarlo y crear su propio ayudante.
Tengo que agradecer a Tim por su respuesta anterior , esta respuesta sobre UIScrollView y también este tutorial .
fuente
Así es como realinearía mis uiviews para obtener su solución:
Creé una regla de oro propia. Siempre que tenga que ocultar / mostrar cualquier uiview cuyas restricciones puedan verse afectadas, agregue todas las subvistas afectadas / dependientes dentro de una uiview y actualice su restricción inicial / final / superior / inferior constante mediante programación.
fuente
Esta es una vieja pregunta, pero aun así espero que ayude. Procedente de Android, en esta plataforma tiene un método útil
isVisible
para ocultarlo de la vista, pero tampoco tiene el marco considerado cuando la distribución automática dibuja la vista.usando extension y "extend" uiview, podría hacer una función similar en ios (no estoy seguro de por qué no está en UIKit ya) aquí una implementación en swift 3:
fuente
la forma correcta de hacerlo es deshabilitar las restricciones con isActive = false. Sin embargo, tenga en cuenta que la desactivación de una restricción la elimina y la libera, por lo que debe tener salidas fuertes para ellos.
fuente
La solución más fácil es usar UIStackView (horizontal). Agregar a la vista de pila: primera vista y segunda vista con etiquetas. Luego establezca la propiedad isHidden de la primera vista en falso. Se calcularán todas las restricciones y se actualizarán automáticamente.
fuente
Creo que esta es la respuesta más simple. Por favor verifique que funcione:
mira aquí https://www.youtube.com/watch?v=EBulMWMoFuw
fuente