Reputation: 437
I have an UIStackview which has two views. I want view1 to have 70 percent of parent when axis is vertical and I want view2 to have 70 percent when axis is horizontal.
I tried to achieve this by playing horizontal hugging and resistance of two views. But nothing works.
FYI: View 1 has an image inside of it and horizontally and vertically centre to the view while width and height both is 50 View 2 is actually a label. It's not view.
Update:
If I activate and deactivate equal width/height constraints it works. But I'm getting below error
2021-02-04 20:07:15.262465+0530 test[10094:159481] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x600003ccedf0 UILabel:0x7fc42ae0b1d0.width == 0.8*UIStackView:0x7fc42ae0d290.width (active)>",
"<NSLayoutConstraint:0x600003cce8a0 UILayoutGuide:0x6000026cc540'UIViewSafeAreaLayoutGuide'.trailing == UIStackView:0x7fc42ac0cca0.trailing (active)>",
"<NSLayoutConstraint:0x600003cce800 UIStackView:0x7fc42ac0cca0.leading == UILayoutGuide:0x6000026cc540'UIViewSafeAreaLayoutGuide'.leading (active)>",
"<NSLayoutConstraint:0x600003cc91d0 'UISV-alignment' UIView:0x7fc42ae05790.leading == UILabel:0x7fc42ae0b1d0.leading (active)>",
"<NSLayoutConstraint:0x600003cc9270 'UISV-alignment' UIView:0x7fc42ae05790.trailing == UILabel:0x7fc42ae0b1d0.trailing (active)>",
"<NSLayoutConstraint:0x600003cc9130 'UISV-canvas-connection' UIStackView:0x7fc42ae0d290.leading == UIView:0x7fc42ae05790.leading (active)>",
"<NSLayoutConstraint:0x600003cc9180 'UISV-canvas-connection' H:[UIView:0x7fc42ae05790]-(0)-| (active, names: '|':UIStackView:0x7fc42ae0d290 )>",
"<NSLayoutConstraint:0x600003cc92c0 'UISV-canvas-connection' UIStackView:0x7fc42ac0cca0.leading == UIStackView:0x7fc42ac0a850.leading (active)>",
"<NSLayoutConstraint:0x600003cc9310 'UISV-canvas-connection' H:[UIStackView:0x7fc42ae0d290]-(0)-| (active, names: '|':UIStackView:0x7fc42ac0cca0 )>",
"<NSLayoutConstraint:0x600003cc93b0 'UISV-fill-equally' UIStackView:0x7fc42ae0d290.width == UIStackView:0x7fc42ac0a850.width (active)>",
"<NSLayoutConstraint:0x600003cc9360 'UISV-spacing' H:[UIStackView:0x7fc42ac0a850]-(0)-[UIStackView:0x7fc42ae0d290] (active)>",
"<NSLayoutConstraint:0x600003cc96d0 'UIView-Encapsulated-Layout-Width' UIView:0x7fc42ac0d030.width == 414 (active)>",
"<NSLayoutConstraint:0x600003cce990 'UIViewSafeAreaLayoutGuide-left' H:|-(0)-[UILayoutGuide:0x6000026cc540'UIViewSafeAreaLayoutGuide'](LTR) (active, names: '|':UIView:0x7fc42ac0d030 )>",
"<NSLayoutConstraint:0x600003cce8f0 'UIViewSafeAreaLayoutGuide-right' H:[UILayoutGuide:0x6000026cc540'UIViewSafeAreaLayoutGuide']-(0)-|(LTR) (active, names: '|':UIView:0x7fc42ac0d030 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600003cc9270 'UISV-alignment' UIView:0x7fc42ae05790.trailing == UILabel:0x7fc42ae0b1d0.trailing (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Upvotes: 1
Views: 2069
Reputation: 17378
Theres no one set of constraints that will do what you want so you need to set up the constraints for both states and set those constraints isActive
state true
or false
depending on whether your stack is in a horizontal or vertical state.
Via Storyboard
You need:
Installed
which is the isActive
property box is checked for the selected constraint. The other constraint is dimmed out as Installed
/isActive
is set to false.When you wish to flip, switch the isActive
flag on those constraints.
class ViewController: UIViewController {
@IBOutlet weak var stack: UIStackView!
@IBOutlet weak var viewOne: UIView!
@IBOutlet weak var viewTwo: UIView!
@IBOutlet weak var vModeHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var hModeWidthContraint: NSLayoutConstraint!
var isVertical = true {
didSet {
UIView.animate(withDuration: 1.0) {
self.toggle()
}
}
}
func toggle() {
vModeHeightConstraint.isActive = false
hModeWidthContraint.isActive = false
stack.axis = isVertical ? .vertical:.horizontal
stack.layoutIfNeeded()
vModeHeightConstraint.isActive = isVertical
hModeWidthContraint.isActive = !isVertical
stack.layoutIfNeeded()
}
@IBAction func toggleModeAction(_ sender: Any) {
isVertical.toggle()
}
}
You can set up the constraints programmatically. How to do this is easy to find on SO.
You will see a bunch of Autolayout errors during the change. Those errors can be filed under "UIKit isn't perfect".
Typically this sort of change is triggered by a device rotation in func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
but you haven't said when you want the change to occur.
Upvotes: 2