UIStackView和子视图大小类

时间:2015-11-04 16:02:53

标签: ios uistackview

我有一个UIStackView,其中中间按钮仅在不同大小的类中可见 storyboard view

旋转设备后,按钮将因大小等级而可见,并且也位于右视图层次结构(图像)中,但UIstackview给出的约束不足以正确定位,它位于左上角角落(标签中间)。

not enough constraints

工作按钮(不受大小类更改影响)有更多限制。

这是一个错误还是我错过了什么。 有人知道解决方法吗?

4 个答案:

答案 0 :(得分:2)

Rob和Uwe提供的解决方案肯定能够解决有条件安装的视图没有被添加到特征集合更改的arrangedSubviews的问题。

我更倾向于解决这个问题,而不必将我希望放在UIStackView内的每个视图子类化,因此我将UIStackView自身子类化为覆盖layoutSubviews()并添加孤立的子视图到arrangedSubviews

class ManagedStackView: UIStackView {

    override func layoutSubviews() {
        super.layoutSubviews()
        let unarrangedSubviews = subviews.filter({ !arrangedSubviews.contains($0) })
        unarrangedSubviews.forEach({ insertArrangedSubview($0, atIndex: $0._arrangedSubviewIndex) })
    }

}


extension UIView {

    private var _arrangedSubviewIndex: Int {
        get {
            return tag
        }
        set {
            tag = newValue
        }
    }

}

答案 1 :(得分:1)

这绝对是iOS中的一个错误。安装中间按钮时,它将被添加为堆栈视图的子视图,但不会添加为排列的子视图。

这是一种解决方法。将中间按钮的自定义类设置为StackViewBugFixButton。然后将中间按钮的(新)priorView插座连接到左侧的下一个按钮。以下是StackViewBugFixButton

的定义

StackViewBugFixButton.h

#import <UIKit/UIKit.h>

@interface StackViewBugFixButton : UIButton

@property (nonatomic, weak) IBOutlet UIView *priorSibling;

@end

StackViewBugFixButton.m

#import "StackViewBugFixButton.h"

@implementation StackViewBugFixButton

- (void)didMoveToSuperview {
    [super didMoveToSuperview];
    [self putIntoArrangedSubviewsIfNeeded];
}

- (void)putIntoArrangedSubviewsIfNeeded {
    if (![self.superview isKindOfClass:[UIStackView class]]) {
        return;
    }

    if (self.priorSibling == nil) {
        NSLog(@"%@ %s You forgot to hook up my priorSibling outlet.", self, __func__);
        return;
    }

    UIStackView *stackView = (UIStackView *)self.superview;
    if ([stackView.arrangedSubviews indexOfObject:self] != NSNotFound) {
        return;
    }

    NSUInteger priorSiblingIndex = [stackView.arrangedSubviews indexOfObject:self.priorSibling];
    if (priorSiblingIndex == NSNotFound) {
        NSLog(@"%@ %s My priorSibling isn't in my superview's arrangedSubviews.", self, __func__);
        return;
    }

    [stackView insertArrangedSubview:self atIndex:priorSiblingIndex + 1];
}

@end

你会得到一个虚假的警告:“你忘了连接我之前的兄弟插座”,因为在连接插座连接之前,视图会被添加为堆栈视图的子视图。

答案 2 :(得分:0)

感谢Rob我使用swift创建了以下解决方案,您必须在用户定义的运行时值中设置controlIndex,但要设置为正确的索引 (see image

import UIKit

class UIButtonFixForStackView: UIButton {

    var controlIndex:Int = 0

    internal override func didMoveToSuperview() {


    if (superview?.isKindOfClass(UIStackView) == false)
    {
        return
    }

    if let stackView = self.superview as? UIStackView
    {
        if stackView.arrangedSubviews.indexOf(self) != nil
        {
            return
        }

        stackView.insertArrangedSubview(self, atIndex: controlIndex)
        }
    }
}

答案 3 :(得分:0)

虽然接受的答案应该以编程方式起作用,但值得注意的是,您可以通过为 Hidden 属性(而不是已安装属性。 iOS可以正确处理此情况,因为arrangedSubviews从未真正更改过,并且UIStackViewbuilt to adapt its layout when (arranged) subviews are hidden

例如,如果您要隐藏一个紧凑宽度的特定视图,则子视图的IB配置将如下所示。请注意,该视图是所有尺寸类中的已安装

varying the "Hidden" property