15

Anybody know a simple way to hide a label and let the other views of the screen use the place left blank ? And make the opposite when showing back that view. Something like Android setVisibility = GONE for layers.

As far as I know, using setHidden=true only hide the view from the screen but does not rearrange anything around it.

Thank you

Siddharth Shah
  • 382
  • 4
  • 22

4 Answers4

14

The only way to achieve Androids .GONE functionality on iOS is to use a UIStackView

via Apples documentation

Dynamically Changing the Stack View’s Content The stack view automatically updates its layout whenever views are added, removed or inserted into the arrangedSubviews array, or whenever one of the arranged subviews’s hidden property changes.

SWIFT 3:

// Appears to remove the first arranged view from the stack.
// The view is still inside the stack, it's just no longer visible, and no longer contributes to the layout.
let firstView = stackView.arrangedSubviews[0]
firstView.hidden = true

SWIFT 4:

let firstView = stackView.arrangedSubviews[0]
firstView.isHidden = true
Md Imran Choudhury
  • 9,343
  • 4
  • 62
  • 60
Fonix
  • 11,447
  • 3
  • 45
  • 74
2

You can achieve this easily using AutoLayout constraints.

Suppose you have three views like this:

+-----+
|  A  |
+-----+
+-----+
|  B  |
+-----+
+-----+
|  C  |
+-----+

and you want to make view B disappear in some cases.

Set up constraints as follows (these are just example values):

B top space to A:  4
C top space to B:  4
B height: 20

Then create an NSLayoutConstraint outlet in your code for B's height. Do this by dragging and dropping the constraint in IB.

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bHeight;

Finally, to make the view disappear, just do the following:

self.bHeight = 0;

Note that if you are doing this for a tableview cell, you may have cases where you want B to appear in some cells, but not in others.

In this case, you will have to reset the height to its "normal" value for those cells where you want it to be visible.

self.bHeight = 24;
northernman
  • 1,446
  • 16
  • 19
  • if you only set `self.bHeight = 0;` then there will be a double space between A and C, you would need to make one of the top spaces 0 as well, otherwise if there are more than 3 views, it will look uneven – Fonix Dec 30 '16 at 01:19
  • If you are using ARC and have the error : > "Implicit conversion of 'int' to 'NSLayoutConstraint *' is disallowed with ARC" you must use `self.bHeight.constant = 24;` – Bubu Jan 30 '18 at 14:23
2

I was looking for simple solution and found it. I don't have to use UIStackView or create outlet for constraint. Just use this:

class GoneConstraint {
    private var constraint: NSLayoutConstraint
    private let prevConstant: CGFloat

    init(constraint: NSLayoutConstraint) {
        self.constraint = constraint
        self.prevConstant = constraint.constant
    }

    func revert() {
        self.constraint.constant = self.prevConstant
    }
}


fileprivate struct AssociatedKeys {
    static var widthGoneConstraint: UInt8 = 0
    static var heightGoneConstraint: UInt8 = 0
}


@IBDesignable
extension UIView {

    @IBInspectable
    var gone: Bool {
        get {
            return !self.isHidden
        }
        set {
            update(gone: newValue)
        }
    }

    weak var widthConstraint: GoneConstraint? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.heightGoneConstraint) as? GoneConstraint
        }
        set(newValue) {
            objc_setAssociatedObject(self, &AssociatedKeys.widthGoneConstraint, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    weak var heightConstraint: GoneConstraint? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.heightGoneConstraint) as? GoneConstraint
        }
        set(newValue) {
            objc_setAssociatedObject(self, &AssociatedKeys.heightGoneConstraint, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }

    private func update(gone: Bool) {
        isHidden = gone
        if gone {
            for constr in self.constraints {
                if constr.firstAttribute == NSLayoutAttribute.width {
                    self.widthConstraint = GoneConstraint(constraint: constr)
                }
                if constr.firstAttribute == NSLayoutAttribute.height {
                    self.heightConstraint = GoneConstraint(constraint: constr)
                }
                constr.constant = 0
            }
        } else {
            widthConstraint?.revert()
            heightConstraint?.revert()
        }
    }
}

Now, you can call view.gone = true and that's it.

Joe Duemig
  • 15
  • 4
Daniel Kuta
  • 1,634
  • 15
  • 24
1

You can use UIStackView if youe app supports ios 9 and above.

but if your app support ios 8 also than You have to achive it using Autolayout and add Height Constrain for View

So if you want hide than just set height constrain value 0.

Shreyank
  • 1,549
  • 13
  • 24