3

Note: I'm pretty new working with iOS UI.

I want to create a custom view that stacks a custom view inside.

So I created the custom UIStackView

class CustomStackView: UIStackView {

    func addItem(color:UIColor){
        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: "RowView", bundle: bundle)
        let rowView = RowView();
        let view = nib.instantiate(withOwner: rowView, options: nil).first as! UIView
        rowView.addSubview(view)
        rowView.view.backgroundColor = color;
        addArrangedSubview(rowView)
    }

}

class RowView :UIView{

    @IBOutlet var view: UIView!

    override public var intrinsicContentSize: CGSize {
        return CGSize(width: view.frame.width,height:view.frame.height)
    }
}

in the RowView.xib I created a simple layout for testing:

Simulated Metrics = Freeform
Height = 100

enter image description here

And the ViewController.swift:

class ViewController: UIViewController {

    @IBOutlet weak var customStackView: CustomStackView!
    @IBOutlet weak var constraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()
        customStackView.addItem(color: UIColor.red)
        customStackView.addItem(color: UIColor.blue)
        customStackView.addItem(color: UIColor.green)
    }

    @IBAction func click(_ sender: Any) {
        constraint.constant = -customStackView.frame.height
        UIView.animate(withDuration: 4, animations: {
            self.view.layoutIfNeeded();
        },completion:nil)
    }

}

The result:

enter image description here

The first and second item are displayed correctly but the third is higher than expected.

In addition if I click the button (which should hide the Stackview) keep the "extra" height visible:

enter image description here

How can I fix that?

Edit: Tried the @KristijanDelivuk solution adding a trailing view. And didn't work. Adding cyan color to the view I got this result:

override func viewDidLoad() {
    super.viewDidLoad()
    customStackView.addItem(color: UIColor.red)
    customStackView.addItem(color: UIColor.blue)
    customStackView.addItem(color: UIColor.green)
    let view = UIView();
    view.heightAnchor.constraint(equalToConstant: 50).isActive = true;
    view.backgroundColor = UIColor.cyan;
    customStackView.addArrangedSubview(view)
}

enter image description here

Addev
  • 31,819
  • 51
  • 183
  • 302

1 Answers1

0

You can try adding an empty UIView as your last element of UIStackView:

So your hierarchy should look something like this:

- STACKVIEW
-- 1ST ADDED CUSTOM VIEW 
-- 2ND ADDED CUSTOM VIEW
-- 3RD ADDED CUSTOM VIEW
-- EMPTY UIVIEW

Empty UIView will take all unallocated space from 3rd view and all should be displayed correctly.

For repositioning button after hiding/showing stackview you can create for example "top constraint" and then on tap change top constraint height to (-) stackview.height or (+) stackview.height - This shouldn't be any problem.

Kristijan Delivuk
  • 1,253
  • 13
  • 24
  • Because stack view needs to allocate all of its defined space, and if element size is smaller than space defined for stack view it will give priority to the last element added on that stack (or to some other if defined that way). Hiding/showing stack view should work in theory, but sometimes autolayout breaks for some wierd reason view when isHidden property is changed and transition doesn't happen. There is cool article from NatashaTheRobot in which she describes how really it should work: https://www.natashatherobot.com/button-animation-stackview/ But, like i said ... – Kristijan Delivuk Jun 29 '17 at 12:26
  • Tried it but didn't work. Check the edit at the answer for the result – Addev Jun 29 '17 at 12:28
  • here mate, i created test project -> change signing team to personal so you can build it: https://ufile.io/u9uof – Kristijan Delivuk Jun 29 '17 at 12:57