Equivalente de iOS para el modo de visibilidad Android View.GONE

79

Estoy desarrollando una aplicación para iOS y estoy usando Storyboard con AutoLayout ON. Uno de mis controladores de vista tiene un conjunto de 4 botones y, en determinadas circunstancias, me gustaría hacer desaparecer el primero.

Si utilizo el setHidden:TRUEmétodo, el UIButton se vuelve invisible pero obviamente todavía ocupa espacio en la vista, y el resultado es un "agujero" que no he podido llenar haciendo que el UIButton restante flote hacia la parte superior de la vista principal.

En Android, simplemente lo hubiera usado en View.GONElugar de View.INVISIBLE, pero en iOS estoy atascado con este comportamiento y no quiero creer que la única solución es mover manualmente (sí, me refiero a programación) los elementos restantes a la parte superior.

Pensé que habría podido hacerlo estableciendo algún tipo de restricción para que todo fuera tan automático como en Android, pero no tuve suerte.

Antes de desactivar el diseño automático, ¿alguien puede indicarme la dirección correcta?

Estoy usando el IB, pero también me siento cómodo con las cosas programáticas.

ACTUALIZAR:

Establecer la altura del componente en 0 tampoco ayuda.

Intenté algo como esto:

UIButton *b;
CGRect frameRect = b.frame;
frameRect.size.height = 0;
b.frame = frameRect;
elbuild
fuente
¿Qué tal poner la altura del botón a cero?
cahn
Intenté algo como esto: UIButton * b; CGRect frameRect = b.frame; frameRect.size.height = 0; b.frame = frameRect; Sin suerte :(
elbuild
Sé que esta es una pregunta muy antigua, pero con respecto a su actualización, configurar el marco en 0 no ayudará si está utilizando el diseño automático.
Debe

Respuestas:

40

Agregar una restricción (NSLayoutAttributeHeight) que establece la altura de la vista en 0 funcionó para mí:

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.captchaView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0]];
Deniz
fuente
11
Versión Swift:self.view.addConstraint(NSLayoutConstraint(item: self.captchaView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0))
iStar
1
Esta debería haber sido la respuesta
Rick Royd Aban
2
¿Qué sucede si no conozco la altura real de la vista deseada (por ejemplo, la vista del contenedor renderizada un poco más tarde)?
A. Petrov
¡Muchas gracias por la increíble respuesta! Porque alguien puede necesitarlo. Tengo un error Unable to simultaneously satisfy constraints. mientras que ya tenía restricciones para la vista. Lo resuelvo
Nevin Chen
@iStar he usado el mismo código pero no funciona ... stackoverflow.com/questions/45454992/…
Sanjay Mangaroliya
20

Todas las respuestas a estas preguntas son ineficientes. La mejor manera de equvailent de Android setVisibility: El método pasado en iOS es queStackView primero seleccione los componentes y luego en el editor, incruste, Stack View,

conecte la nueva vista de pila con IBOutlet, luego:

oculto:

UIView * firstView = self.svViewFontConfigure.arrangedSubviews[0];
        firstView.hidden = YES;

visibilidad:

UIView * firstView = self.svViewFontConfigure.arrangedSubviews[0];
        firstView.hidden = NO;

Al usar la vista de pila, se mantendrán todas las restricciones.

Documento

Ucdemir
fuente
En realidad, parece una solución realmente buena, pero vale la pena señalar que necesita iOS9 +.
user3533716
Usé tu brillante solución (+1 para ti, ¡muchas gracias!) Pero conecté a través de IBOutlet directamente la vista que quería mostrar y ocultar, ¡así que tengo que escribir solo una línea de código! :)
Cristina De Rito
1
Esta respuesta en realidad no es correcta. Android View.GONE elimina la vista en la interfaz de usuario. Por ejemplo, si configura View.GONE un elemento, las vistas debajo de esa vista se desplazarán hacia arriba. Entonces, su sugerencia simplemente oculta la vista que es igual a Ver. OCULTAR. Mire esta respuesta: stackoverflow.com/questions/11556607/…
emin deniz
No busqué en la API de Android ... Pero soy desarrollador móvil, así que sé mecánico ... En Android con la vista de bandera booleana se puede ver o no (Desaparecido, Visible) Si se elimina de la interfaz de usuario, será difícil agregar de nuevo ... pero en ios, está en el diseño pero sin espacios .... Además, hay una propiedad oculta oficial de ios que tiene lugar ... Propiedad oculta de UIStackview como Android View.Gone
Ucdemir
16

agregue una restricción de altura a su vista de la siguiente manera:ingrese la descripción de la imagen aquí

luego haga una salida para la restricción de altura en su archivo viewController de la siguiente manera:ingrese la descripción de la imagen aquí

Y luego, en su método viewDidLoad, cambie la altura de la restricción a 0 de la siguiente manera:

override func viewDidLoad() {
    super.viewDidLoad()
nsLcButtonHeight.constant = 0
}
Ajinkya Patil
fuente
1
altura constante apesta, uso la misma altura y un multiplicador, por ejemplo, para tomar el 25% de la vista de los padres, ¿algún ejemplo para ello?
user924
8

Para lograr la funcionalidad Androids.GONE en iOS es usar un UIStackView. Después de eso, esconde al niño por posición. ( Documentación de manzanas )

SWIFT 4:

let firstView = cell.rootStackView.arrangedSubviews[0]
    firstView.isHidden = true // first view gone

Es un ejemplo de celda de tabla, solo coloque ambos lados Stack viewy obtenga el elemento para GONEel niño.

ingrese la descripción de la imagen aquí

Md Imran Choudhury
fuente
1

1) Si sus botones están colocados verticalmente, debe establecer el valor heighten 0 y, en el caso de los botones colocados horizontalmente, intente establecerlo widthen 0 o puede establecer ambos en 0.

O

2) puede probar este enfoque que se basa button2en button1:

- (void)viewDidLoad
{
[super viewDidLoad];

UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button1 setTitle:@"hello" forState:UIControlStateNormal];

UIButton *button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button2 setTitle:@"world" forState:UIControlStateNormal];

[button1 sizeToFit]; [button2 sizeToFit];
[button2 setFrame:CGRectMake(button1.frame.origin.x, button1.frame.origin.y, button2.frame.size.width, button2.frame.size.height)];

[self.view addSubview:button1];
[self.view addSubview:button2];

}
iphondroid
fuente
1

Esta pregunta es bastante antigua, pero lo que encontré en el armario es establecer restricciones adicionales (para que las vistas alrededor de la vista "desaparecida" sepan qué hacer una vez que falta)

A  which you want to be     A
|  after setting B to gone  |
B                           C
|                               
C                               
  1. Establezca una restricción de menor prioridad (750) de C a A.
  2. Agregue las restricciones superior e inferior de B (o izquierda y derecha si desea que su vista se colapse horizontalmente) a una matriz NSLayoutConstraint bConstraints . Haz esto por:
    1. Control, haga clic y arrastre desde la restricción al ViewController
    2. Cambiar conexión de Outlet a Outlet Collection
    3. Para poner nombre bConstraints.
    4. Presiona conectar. Esto creará un @IBOutlet var bConstraints: [NSLayoutConstraint]!en su ViewController
    5. Para agregar restricciones adicionales: arrastre desde la restricción en Storyboard al nombre de la variable @IBOutlet
  3. Entonces esconde B

    B.hidden = true
    NSLayoutConstraint.deactivateConstraints(bConstraints)
    
  4. Para mostrar

    B.hidden = false
    NSLayoutConstraint.activateConstraints(bConstraints)
    

Obviamente, cuantas más vistas tenga, más complejo se volverá, ya que necesita restricciones adicionales de cada vista.

wyu
fuente
Sería más útil si explicara por qué no pudo implementar
wyu
El segundo punto. Aunque estoy trabajando en Xamarin. Aún no he encontrado una solución para este problema. No sé cómo debería construir una matriz NSLayoutConstraint con restricciones B. Supongo que se hace programáticamente, sería bueno ver el código para eso. Me parece que su método es la forma más razonable de abordar este problema, sin embargo, no es fácil de implementar con solo un pseudocódigo
Gustavo Baiocchi Costa
No he usado Xamarin. La forma en que se hace en XCode es: ctrl-clic y arrastre desde la restricción al ViewController (esto es similar a cómo crearía un IBOutlet en xcode). En la ventana emergente que aparece (similar a i.stack.imgur.com/JegLK.png ) cambia el menú desplegable "Conexión" de Outleta Outlet Collection. Para restricciones adicionales, presione Ctrl y arrastre directamente al nombre de la variable. Puedo subir instantáneas hoy más tarde (en ~ 8 horas)
wyu
así que la matriz NSLayoutConstraint es la colección outlet, me perdí un poco aquí jaja, gracias por tomarse su tiempo para responder mis preguntas :)
Gustavo Baiocchi Costa
sí, actualizaré la respuesta para que sea más clara. ¿Entonces la solución está funcionando para usted?
wyu
0

Como ha demostrado mi investigación, ni siquiera AutoLayout puede ayudarlo. Debe reemplazar manualmente las vistas afectadas por el componente que se muestra opcionalmente (en mi caso, todas las vistas en la parte inferior de la vista opcional, pero estoy seguro de que puede adaptar esto para manejar todos los botones a la derecha de su botón opcional ):

- (IBAction)toggleOptionalView:(id)sender {
    if (!_expanded) {
        self.optionalView.frame = CGRectMake(self.optionalView.frame.origin.x, self.optionalView.frame.origin.y, self.optionalView.frame.size.width, _optionalHeight);
        self.bottomView.frame = CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y+_optionalHeight, self.bottomView.frame.size.width, self.bottomView.frame.size.height);
        _expanded = YES;
    } else {
        self.optionalView.frame = CGRectMake(self.optionalView.frame.origin.x, self.optionalView.frame.origin.y, self.optionalView.frame.size.width, 0);
        self.bottomView.frame = CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y-_optionalHeight, self.bottomView.frame.size.width, self.bottomView.frame.size.height);
        _expanded = NO;

    }
}

Es recomendable no codificar la altura / ancho de los componentes opcionales, de lo contrario, su código se rompe cada vez que edita el XIB / Storyboard. Tengo un campo float _optionalHeight que configuré en viewDidLoad, por lo que siempre está actualizado.

Katlu
fuente
0

También puede borrar la página, o al menos ciertas celdas de la página, y redefinir todo. Es rápido y funciona bien. No escribí el código, pero lo encontré en este proyecto preexistente en el que estoy trabajando. Crea ManagementTableSectiony ManagementTableCellclases para gestionarlo todo. Lo siento, no puedo proporcionar un código mejor definido.

craned
fuente
0

Partiendo de la respuesta proporcionada por Deniz, aquí hay una solución que utiliza restricciones en Swift

Por ejemplo: si tiene 3 vistas, A_view B_view y C_view alineadas verticalmente en ese orden y desea "Ocultar" B y también ajustar la diferencia, agregue una restricción

B_view.removeFromSuperView()
var constr = NSLayoutConstraint(item: C_view, 
                                attribute: NSLayoutAttribute.Top, 
                                relatedBy: NSLayoutRelation.Equal, 
                                toItem: A_view, 
                                attribute: NSLayoutAttribute.Bottom,
                                multiplier: 1,
                                constant: 20)
view.addConstraint(constr)

constante es (en este caso) la cantidad de espacio vertical entre C_view y A_view

The4thIceman
fuente
0

Agregué una nueva propiedad a una implementación personalizada de UIView llamada "visible" que, cuando se establece en falso, agrega una restricción para contraer la vista (solo agregué una restricción de ancho ya que mi lista es horizontal, pero la mejor manera podría ser agregar una restricción de altura de 0 también).

var visible:Bool = true{
        didSet{
            if(visible){
                clipsToBounds = false;
                removeConstraint(hideConstraint!)
            }else{
                clipsToBounds = true
                addConstraint(hideConstraint!)
            }
        }
    }

Debe inicializar la restricción de ancho cero en la vista y agregarla como un campo:

private var hideConstraint:NSLayoutConstraint?


func someInitFunction(){
    hideConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 0.0)
    ...
}
Anthony De Smet
fuente
-3

setHidden: TRUE / FALSE es el equivalente más cercano a Android View.GONE / VISIBLE.

¡La vista no necesariamente ocupa espacio si no es visible!

He creado un ComboBox-Alike con un ListView encima de otras vistas. Solo soy visible al seleccionar:

ingrese la descripción de la imagen aquí

thpitsch
fuente
olvidaste que en android también tenemos view.invisible ... view.gone no es similar a setHidden ... su view.invisible que es similar a setHidden
Nav