18

I want to hide an element (data picker in my case) and also hide its space. So I tried this with an animation:

@IBAction func showQnt(sender: AnyObject) {
    if (self.pickerQnt.alpha == 0.0) {
        UIView.animateWithDuration(0.2, delay: 0.0, options: UIViewAnimationOptions.ShowHideTransitionViews, animations: {
            self.pickerQnt.alpha = 1.0
            
            
            }, completion: {
                (finished: Bool) -> Void in
                //var constH = NSLayoutConstraint(item: self.pickerQnt, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 162)
                //self.pickerQnt.addConstraint(constH)
        })
    } else {
        UIView.animateWithDuration(0.2, delay: 0.0, options: UIViewAnimationOptions.ShowHideTransitionViews, animations: {
            self.pickerQnt.alpha = 0.0
            
            
            }, completion: {
            (finished: Bool) -> Void in
                // CHECK: ?!? constrain to set view height to 0 run time
                //var constH = NSLayoutConstraint(item: self.pickerQnt, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 0)
                //self.pickerQnt.addConstraint(constH)
        })
    }
}

I've also tried something like

self.pickerQnt.hidden = true

but it wont work.

Thanks in advance.

Marco Rossini
  • 469
  • 2
  • 6
  • 19

4 Answers4

14

Using the "hidden" property on views in Objective-C/Swift does as a matter of fact not "collapse" the space the view is taking (as opposed to "View.GONE" in Android).

Instead you should use Autolayout and a Height constraint.

Create a Height constraint in your Xib/Storyboard file. Giving it the wished height. Make an IBOutlet to that constraint (ctrl-drag from the Constraint in the Constraints list to your source file), and then you can write this method

Swift solution

var pickerHeightVisible: CGFloat!
...
...
func togglePickerViewVisibility(animated: Bool = true) {
    if pickerHeightConstraint.constant != 0 {
        pickerHeightVisible = pickerHeightConstraint.constant
        pickerHeightConstraint.constant = 0
    } else {
        pickerHeightConstraint.constant = pickerHeightVisible
    }
    if animated {
         UIView.animateWithDuration(0.2, animations: {
              () -> Void in
               self.view.layoutIfNeeded()
         }, completion: nil)
    } else {
         view.layoutIfNeeded()
    }
}

Objective-C solution:

@property (nonatomic, strong) CGFloat pickerHeightVisible;
...
...
- (void)togglePickerViewVisibility:(BOOL)animated {
    if(pickerHeightConstraint.constant != 0) {
        pickerHeightVisible = pickerHeightConstraint.constant;
        pickerHeightConstraint.constant = 0;
    } else {
        pickerHeightConstraint.constant = pickerHeightVisible;
    }
    if(animated) {
         [UIView animateWithDuration:0.2
             animations:(void (^)(void))animations:^(void) {
                  [self.view layoutIfNeeded];
             }];
    } else {
          [self.view layoutIfNeeded];
    }
}

DISCLAIMER: I have not tested nor compiled the code above, but it will give you an idea of how to achieve it.

IMPORTANT: The code above assumes that you give the height constraint of the picker view a value greater than 0 in the storyboard/nib.

Sajjon
  • 8,938
  • 5
  • 60
  • 94
  • 2
    5 year old answer, I know but I learned so much from your comment. I love Swift but I absolutely hate the UI aspect. NEVER EVER understood how to use "View.Gone" in iOS. I seriously appreciate your answer – Zun Oct 05 '20 at 14:15
  • 1
    @Zun thanks a lot! I've always hated UIKit... Have you tried SwiftUI yet? Much nicer UI framework! But difficult in other aspects, navigation is kind of tricky. – Sajjon Oct 05 '20 at 15:14
11

This is an old question but there is another option that became available for newer iOS versions:

If your layout allows it, and if you are targeting iOS9 or later you can arrange your view in a UIStackView as the container. Children of stack views collapse when hidden, i.e. no longer take any space.

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 isHidden property changes.

(https://developer.apple.com/documentation/uikit/uistackview#overview)

3

Best way is to add views in stack and upon hiding one view height of the stack view will be automatically adjusted. But if views are not in stack view then just do the following.

1- Hide the view.
2- Assign height constraint to view, make height constraint outlet of the view

@IBOutlet weak var myView: UIView!
@IBOutlet weak var myViewHeightConstraint: NSLayoutConstraint!
myView.isHidden = true
viewHeightConstraint.constant = 0
Asad Jamil
  • 198
  • 9
2

One simple method is to set the height to zero when hiding the view (that too without making IBOutlet of height constraint).

myView.isHidden = true
myView.heightAnchor.constraint(equalToConstant: CGFloat(0)).isActive = true

And set height again when unhiding

myView.isHidden = false
myView.heightAnchor.constraint(equalToConstant: CGFloat(40)).isActive = true

To achieve the above functionality with animation, simply put heightAnchor code in UIView.animate() block

If you have to do this many times, then you can reduce your two-line code into one line by making a function in extension.

Abhishek Maurya
  • 697
  • 7
  • 19