Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I by code add a change to UIStackView.Axis on orientation change?

I have a few UIStackView that I add programmatically and I want them to have a other Axis when the app is in say Regular Width and Any Height.

It this even possible, like it is in the interface builder?

All I bump into on Google is willTransitionToTraitCollection, but not what I need.

To make it easier to understand what I need:

for i in numberOfItems {
    let stackView = UIStackView()
    stackView.append... // add views in this new stack view

    // here is where I need help:
    stackView.axis = horizontal
    stackView.addSomething... stackView.axis = vertical if regular width and any height.

    existingStackView.append.... stackView
}

Edit:

I found a other way to do, but I get some strange behaviour on iPhone 6+ when I rotate it around. Git repo: https://github.com/bjaskj/iOSStackViewConstraints

class MyStackView: UIStackView {
    override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)

        if traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Regular {
            axis = UILayoutConstraintAxis.Horizontal
        } else {
            axis = UILayoutConstraintAxis.Vertical
        }
    }
}

ViewController:

@IBOutlet weak var mainStackView: UIStackView!

override func viewDidLoad() {
    super.viewDidLoad()
    addElement("Name", description: "Saint Petersburg")
    addElement("Native name", description: "Санкт-Петербург")
    addElement("Country", description: "Russia")
    addElement("Federal district", description: "Northwestern")
    addElement("Economic region", description: "Northwestern")
    addElement("Established", description: "May 27, 1703")
}

func addElement(title:String, description:String) {

    let labelTitle = UILabel()
    labelTitle.backgroundColor = UIColor.redColor()
    labelTitle.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
    labelTitle.text = title
    labelTitle.textColor = UIColor.whiteColor()

    let labelDescription = UILabel()
    labelDescription.backgroundColor = UIColor.blueColor()
    labelDescription.font = UIFont.preferredFontForTextStyle(UIFontTextStyleBody)
    labelDescription.text = description
    labelDescription.textColor = UIColor.whiteColor()

    let stackHolder = MyStackView()
    stackHolder.axis = .Vertical
    stackHolder.distribution = .FillEqually

    stackHolder.addArrangedSubview(labelTitle)
    stackHolder.addArrangedSubview(labelDescription)
    stackHolder.spacing = 8

    mainStackView.addArrangedSubview(stackHolder)
}

What happens when I rotate iPhone 6+ is this: enter image description here

But what I expect and get if I start the app in rotated position: enter image description here

like image 673
Bjarte Avatar asked Sep 17 '15 12:09

Bjarte


People also ask

Is UIStackView intrinsic content size?

Each of the elements has it's own intrinsicContentSize so it should be possible for the UIStackView to provide its own intrinsicContentSize . The documentation states that the spacing is used as a minimum spacing. The intrinsicContentSize.

What is a Stackview?

Overview. Stack views let you leverage the power of Auto Layout, creating user interfaces that can dynamically adapt to the device's orientation, screen size, and any changes in the available space. The stack view manages the layout of all the views in its arrangedSubviews property.


1 Answers

Update:

Ok, so it seems like you have two questions:

1) How do I add the appropriate stackview.axis depending on the size class when I add my stackviews to the scene:

for i in numberOFItems {
    let stackView = UIStackView()

    if view.traitCollection.verticalSizeClass == .Unspecified && view.traitCollection.horizontalSizeClass == .Regular {
        stackView.axis = .Vertical
    } else {
        stackView.axis = .Horizonal
    }

    stackView.addArrangedSubview(arrayOfViews[i])
}

2) How to make that stackview change from horizontal to vertical axis when the phone orientation is changed:

You'll nee to have a an array of stackviews that you've initialized. Then you'll need to step through the stackviews in the delegate method and change their orientation.

override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
    var axis

    if view.traitCollection.verticalSizeClass == .Compact {
        axis = UILayoutConstraintAxis.Horizontal
    } else {
        axis = UILayoutConstraintAxis.Vertical
    }

    for stackView in stackViewArray {
        stackView.axis = axis
    }
}

The view has a traitCollection that includes verticalSizeClass and horizontalSizeClass. These can have the values of .Compact, .Regular, and .Unspecified.

The method traitCollectionDidChange should tell you whenever a size class is modified (i.e. when the phone is turned).

If this still does not answer your question, please try rewriting your question so it's easier to understand

Also, there is no way that I am aware of to set these properties once and be done with it, you have to take care of both cases.

like image 128
Rob Norback Avatar answered Nov 13 '22 18:11

Rob Norback