AutoLayout with hidden UIViews?

后端 未结 13 1295
南方客
南方客 2020-11-27 09:27

I feel like it\'s a fairly common paradigm to show/hide UIViews, most often UILabels, depending on business logic. My question is, what is the best

相关标签:
13条回答
  • 2020-11-27 09:54

    UIStackView is probably the way to go for iOS 9+. Not only does it handle the hidden view, it will also remove additional spacing and margins if set up correctly.

    0 讨论(0)
  • 2020-11-27 09:56

    In this case, I map the height of the Author label to an appropriate IBOutlet:

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

    and when I set the height of the constraint to 0.0f, we preserve the "padding", because the Play button's height allows for it.

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

    0 讨论(0)
  • 2020-11-27 09:56

    I'm surprised that there is not a more elegant approach provided by UIKit for this desired behavior. It seems like a very common thing to want to be able to do.

    Since connecting constraints to IBOutlets and setting their constants to 0 felt yucky (and caused NSLayoutConstraint warnings when your view had subviews), I decided to create an extension that gives a simple, stateful approach to hiding/showing a UIView that has Auto Layout constraints

    It merely hides the view and removes exterior constraints. When you show the view again, it adds the constraints back. The only caveat is that you'll need to specify flexible failover constraints to surrounding views.

    Edit This answer is targeted at iOS 8.4 and below. In iOS 9, just use the UIStackView approach.

    0 讨论(0)
  • 2020-11-27 09:57

    My personal preference for showing/hiding views is to create an IBOutlet with the appropriate width or height constraint.

    I then update the constant value to 0 to hide, or whatever the value should be to show.

    The big advantage of this technique is that relative constraints will be maintained. For example let's say you have view A and view B with a horizontal gap of x. When view A width constant is set to 0.f then view B will move left to fill that space.

    There's no need to add or remove constraints, which is a heavyweight operation. Simply updating the constraint's constant will do the trick.

    0 讨论(0)
  • 2020-11-27 09:58

    My preferred method is very similar to that suggested by Jorge Arimany.

    I prefer to create multiple constraints. First create your constraints for when the second label is visible. Create an outlet for the constraint between button and the 2nd label (if you are using objc make sure its strong). This constraint determines the height between the button and the second label when it's visible.

    Then create another constraint that specifies the height between the button and the top label when the second button is hidden. Create an outlet to the second constraint and make sure this outlet has a strong pointer. Then uncheck the installed checkbox in interface builder, and make sure the first constraint's priority is lower than this second constraints priority.

    Finally when you hide the second label, toggle the .isActive property of these constraints and call setNeedsDisplay()

    And that's it, no Magic numbers, no math, if you have multiple constraints to turn on and off you can even use outlet collections to keep them organized by state. (AKA keep all the hidden constraints in one OutletCollection and the non-hidden ones in another and just iterate over each collection toggling their .isActive status).

    I know Ryan Romanchuk said he didn't want to use multiple constraints, but I feel like this isn't micromanage-y, and is simpler that dynamically creating views and constraints programmatically (which is what I think he was wanting to avoid if I'm reading the question right).

    I've created a simple example, I hope it's useful...

    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()
        }
    }
    

    0 讨论(0)
  • 2020-11-27 09:59

    Subclass the view and override func intrinsicContentSize() -> CGSize. Just return CGSizeZero if the view is hidden.

    0 讨论(0)
提交回复
热议问题