【问题标题】:Layout Constraint Messages in iOS app when using layoutSubviews使用 layoutSubviews 时 iOS 应用程序中的布局约束消息
【发布时间】:2015-12-18 23:40:52
【问题描述】:

这有点像我之前发布的问题的后续:

Using NSLayoutConstraint on a subview in conjuction with an affine transform

我正在使用所描述的方法将要旋转的视图放置到另一个 UIView 中,并在 layoutSubviews 方法中进行仿射变换以旋转。

虽然这适用于只有一个 UISlider 可旋转的应用程序,但我现在希望在整个 UIViews 上使用这种旋转方法,每个 UIViews 由几个子视图组成,这些子视图也有子视图,所有子视图都使用自动布局约束来定位元素。

@implementation MMXRotateChannel

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        self.cstrip = [[MMXChannelStripView alloc] init];
        [self addSubview:self.cstrip];

        return self;
    }
    return nil;
}

// this works for any size of this view.  the slider will always be as tall as this view is wide
- (void)layoutSubviews {
    [super layoutSubviews];

    // size it to be as wide as this view's height, center it in this view
    self.cstrip.bounds = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.width);

    self.cstrip.center = [self convertPoint:self.center fromView:self.superview];

    // rotate it
    self.cstrip.transform = CGAffineTransformMakeRotation(M_PI * .5);

}

@end

这实际上为我产生了正确的视觉结果,但由于某种原因,它给了我约束错误消息,如下所示:

 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. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x7ff932e8dae0 h=--& v=--& V:[MMXChannelStripView:0x7ff932e800d0(0)]>",
    "<NSLayoutConstraint:0x7ff932e16ce0 MMXFaderView:0x7ff932e7e4d0.bottom == MMXChannelStripView:0x7ff932e800d0.bottom>",
    "<NSLayoutConstraint:0x7ff932e6c150 V:|-(0)-[MMXChannelControlView:0x7ff932e1ac50]   (Names: '|':MMXChannelStripView:0x7ff932e800d0 )>",
    "<NSLayoutConstraint:0x7ff932e6d530 V:[MMXChannelControlView:0x7ff932e1ac50]-(0)-[MMXFaderView:0x7ff932e7e4d0]>",
    "<NSLayoutConstraint:0x7ff932e6d5d0 V:[MMXFaderView:0x7ff932e7e4d0(>=500)]>",
    "<NSLayoutConstraint:0x7ff932e07400 MMXChannelControlView:0x7ff932e1ac50.height >= 0.5*MMXFaderView:0x7ff932e7e4d0.height>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7ff932e6d530 V:[MMXChannelControlView:0x7ff932e1ac50]-(0)-[MMXFaderView:0x7ff932e7e4d0]>

它列出的第一个约束对我来说很有趣,因为它似乎认为我希望 MMXChannelStripView 为 0 像素,而我不这样做。

请注意,即使我不旋转视图,但仍使用 layoutSubviews 将其作为子视图包含在内,也会出现此错误消息。为什么我在 layoutSubviews 中所做的与我在更多嵌入式视图中所做的自动布局不兼容,是否有某些原因?

我已经附上了一个屏幕截图来显示我的目标。灰色视图是旋转视图,蓝色视图是未旋转且未包含在另一个视图中的视图,因此不会给出错误消息。

【问题讨论】:

  • 视图上translatesAutoresizingMaskIntoConstraints的值是多少?

标签: objective-c uiview autolayout rotatetransform


【解决方案1】:

我认为这里的问题是您设置MMXChannelStripView 的中心和边界为时已晚。到-[MMXRotateChannel layoutSubviews]运行时,自动布局已经解决了约束系统,解决时会产生错误信息。

无论如何,试试这个来初始化条带:

self.cstrip = [[MMXChannelStripView alloc] init];
self.cstrip.translatesAutoresizingMaskIntoConstraints = NO;
self.cstrip.transform = CGAffineTransformMakeRotation(M_PI_2);
[self addSubview:self.cstrip];
[NSLayoutConstraint activateConstraints:@[
    [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.cstrip attribute:NSLayoutAttributeWidth multiplier:1 constant:0],
    [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.cstrip attribute:NSLayoutAttributeCenterX multiplier:1 constant:0],
    [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.cstrip attribute:NSLayoutAttributeCenterY multiplier:1 constant:0],
]];

你不应该在layoutSubviews 中需要任何东西。这在我的测试中有效(使用UISlider)。

【讨论】:

  • 谢谢,这似乎有效。很有趣,我以为我以前为滑块尝试过这个,但它没有用。我一定是做错了什么。
  • 这个唯一的问题是(一个非常小的问题)当我将它用于 UISlider 时,它会从父视图的底部伸出,只是一点点。不过,这并不是真正的问题。
  • 将高度约束的常数设置为 -3 应该可以解决这个问题。
  • 啊,我记得我现在做错了什么!我以前尝试使用对齐,而不是设置宽度和高度。所以,我是说“cstrip 的右边应该与自己的顶部对齐”而不是说 cstrip 的高度应该等于自己的宽度
【解决方案2】:

改用这个:

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        self.cstrip = [[MMXChannelStripView alloc] init];
        self.cstrip.translatesAutoresizingMaskIntoConstraints = NO;
        [self addSubview:self.cstrip];

        return self;
    }
    return nil;
}

以编程方式实例化视图时,请务必将它们的 translatesAutoresizingMaskIntoConstraints 属性设置为 NO。默认情况下,系统会根据视图的框架及其自动调整大小掩码自动创建一组约束。当您添加自己的约束时,它们不可避免地会与自动生成的约束发生冲突。这会创建一个无法满足的布局,因此您会在控制台中收到这些消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 2021-04-29
    相关资源
    最近更新 更多