Kivak Wolf Kivak Wolf - 6 months ago 22
iOS Question

Nested Stack View won't respond to changing axis based on size class

SO,

I have 4 simple views that I want to lay out either vertically 4x1 (if horizontally compact) or horizontally 2x2 (if in any other combination) on iPhones. I also added wC+vC as horizontal 2x2 because iPhone landscape is wC+vC.

My interface builder layout looks like this:

enter image description here

When display a preview of an iPhone 4s in landscape and portrait in Assistant, I get what I expect:

enter image description here

However! When I use the simulator for any iPhone and put it into landscape, I get this:

enter image description here

No matter what I try, I can never make both TopStack and BottomStack display as horizontal. IF I delete the bottom stack, the top becomes horizontal. But as soon as the bottom stack comes into play, the top stack doesn't respond.

I have even tried this in code for just wC+vC:

-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
if( self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact && self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact ) {
[self.TopStack setAxis:UILayoutConstraintAxisHorizontal];
[self.BottomStack setAxis:UILayoutConstraintAxisHorizontal];
} else {
[self.TopStack setAxis:UILayoutConstraintAxisVertical];
[self.BottomStack setAxis:UILayoutConstraintAxisVertical];
}


}

When I debug, I can verify that the top stack is in fact in
UILayoutConstraintAxisHorizontal
but does not correctly display.

Does anyone have an idea on what is wrong??

Thanks!

Answer

This may be an ongoing bug with UIStackView. It appears there were similar issues in beta versions of iOS 9.0 and there may still be some lingering issues with regards to embedded UIStackViews:

http://useyourloaf.com/blog/adapting-stack-views-with-size-classes/

Adding the following code as indicated in the above article does resolve this issue, but at the cost of being screen size agnostic and losing some of what makes Size Classes useful:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    if (size.width > size.height)
    {
        [self.topStack setAxis:UILayoutConstraintAxisHorizontal];
        [self.bottomStack setAxis:UILayoutConstraintAxisHorizontal];
    }
    else
    {
        [self.topStack setAxis:UILayoutConstraintAxisVertical];
        [self.bottomStack setAxis:UILayoutConstraintAxisVertical];
    }
}

Demonstration Xcode Project can be downloaded from here.