如何在iOS 6中使用具有多个子视图的现有自定义视图进行自动布局

时间:2013-03-26 11:46:02

标签: ios constraints frame autolayout addsubview

我正在尝试使用约束来制作布局,但我有许多带有内部嵌套子视图的自定义控件。我将约束添加到顶视图(CustomView),但它没有正确布局子视图。

实施例。我有TextFieldWithLabel类,它在顶部和底部显示了一个UITextField我正在创建TextFieldWithLabel的实例并添加到带有约束的超级视图。

但它未按预期显示结果。 虽然它可见,但没有放在我想要的地方。为此,我不想改变整个TextFieldWithLabel类敌人的自动布局。

请帮助!

usernameTextField = [[TextFieldWithLabel alloc] initWithFrame:CGRectMake(0, 0, 100, 50) name:@"UserName"];
    [usernameTextField setTranslatesAutoresizingMaskIntoConstraints:NO];
    [superview addSubview:usernameTextField];
    NSLayoutConstraint* myConstraint = [NSLayoutConstraint constraintWithItem:usernameTextField
                                                                    attribute:NSLayoutAttributeCenterY
                                                                    relatedBy:NSLayoutRelationEqual
                                                                       toItem:superview
                                                                    attribute:NSLayoutAttributeCenterY
                                                                   multiplier:1
                                                                     constant:0];

    [superview addConstraint:myConstraint];

    myConstraint = [NSLayoutConstraint constraintWithItem:usernameTextField
                                                attribute:NSLayoutAttributeCenterX
                                                relatedBy:NSLayoutRelationEqual
                                                   toItem:superview
                                                attribute:NSLayoutAttributeCenterX
                                               multiplier:1
                                                 constant:0];
    [superview addConstraint:myConstraint];

截屏: 这里没有居中,文本字段(RedColor)也不可点击。标签和文本字段放在TextFieldWithLabel中。 请注意:TextFieldWithLabel是ComponentView的子类,而ComponentView是UIView的子类。所以我怀疑这可能是问题吗?我是否还需要自动布局ComponentsView。 UITextField

3 个答案:

答案 0 :(得分:3)

在自动布局下,您的框架尺寸将被忽略(您在initWithFrame:期间使用的尺寸)。您已指定了定位约束,但与大小无关,因此您的TextFieldWithLabel位于屏幕中央,大小为零。

文本字段和标签仍然可见,因为您说您没有在此控件内部使用自动布局 - 可能是您在那里设置了一些框架和自动调整遮罩。因此,文本字段和标签超出​​TextFieldWithLabel的范围,因此它们是可见的,但可能不响应触摸。

要解决此问题,您有两种选择:

  • 在内部使用自动布局 - 例如,如果您有此约束(在VFL中),则会自动为控件提供高度:"V:|-[label]-[textField]-|"
  • 为您的代码添加大小限制 - 使用您在initWithFrame中执行的相同维度。这是一个设置高度:

    [NSLayoutConstraint constraintWithItem:usernameTextField 
                                 attribute:NSLayoutAttributeHeight 
                                 relatedBy:NSLayoutRelationEqual 
                                    toItem:nil 
                                 attribute:NSLayoutAttributeNotAnAttribute 
                                multiplier:0.0 
                                  constant:50.0];
    

我在UIView上有一个类别来简化常见约束here的创建。使用类别代码,您可以执行centerInView:constrainToSize:

答案 1 :(得分:0)

如果您不希望您的标签(或其他子视图)具有调整大小限制,那么......

    self.YourLabel.translatesAutoresizingMaskIntoConstraints = NO;

答案 2 :(得分:0)

不确定你是如何处理TextFieldWithLabel的,我可能不清楚它实际上是一个UIView子类(我总是命名以View结尾的UIView子类)

在这种情况下,你最终得到了一个偷偷摸摸的视图,它在构建应用程序时介于两者之间。在InterfaceBuilder中,您在View中拖动,并可能将类设置为“TextFieldWithLabel_ View _ ”。你做了通常的“自定义约束”但是,如果“TextFieldWithLabel_ View _ ”类已从UIView中继承,则引入了一个中间层。

在布局标签和文本字段的XIB或代码中,您可能已经设置了与您自己的子类的UIView相对应的正确约束。

问题是,子类UIView的约束没有链接到使用StoryBoard拖入的View。

这就是我所做的:

@interface TextFieldWithLabel__View__ ()
@property (strong, nonatomic) IBOutlet UIView *backgroundView;
@property (weak, nonatomic) IBOutlet UILabel *labelText;
....
....
@end



-(id)initWithCoder:(NSCoder *)decoder{
    if ((self = [super initWithCoder:decoder])){
        [self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"TextFieldWithLabel__View__" owner:self options:nil] objectAtIndex:0]];
    }

    // Set the backgroundView (the one needed for the IB to create a UIView for XIB)
    // Left, Right, Top and Bottom to 0

    _backgroundView.translatesAutoresizingMaskIntoConstraints = NO;
    [self addConstraint:[NSLayoutConstraint constraintWithItem:_backgroundView
                                                     attribute:NSLayoutAttributeLeft
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:self
                                                     attribute:NSLayoutAttributeLeft
                                                    multiplier:0
                                                      constant:0
                         ]
     ];
    [self addConstraint:[NSLayoutConstraint constraintWithItem:_backgroundView
                                                     attribute:NSLayoutAttributeRight
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:self
                                                     attribute:NSLayoutAttributeRight
                                                    multiplier:1
                                                      constant:0
                         ]
     ];
    [self addConstraint:[NSLayoutConstraint constraintWithItem:_backgroundView
                                                     attribute:NSLayoutAttributeTop
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:self
                                                     attribute:NSLayoutAttributeTop
                                                    multiplier:0
                                                      constant:0
                         ]
     ];
    [self addConstraint:[NSLayoutConstraint constraintWithItem:_backgroundView
                                                     attribute:NSLayoutAttributeBottom
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:self
                                                     attribute:NSLayoutAttributeBottom
                                                    multiplier:1
                                                      constant:0
                         ]
     ];
    return self;
}

现在,您想要重新设置CustomView的那一刻,拖动项目,调整分配的区域或其他任何内容,它很好地将通过约束形式将CustomView传递给TextFieldWithLabel_ View _

在故事板中勾选“AutoResize Subviews”

希望有所帮助。

P.S。不要放弃AutoLayout ......掌握它!