【问题标题】:How to Auto Layout with existing Custom View with multiple subviews in iOS 6如何在 iOS 6 中使用具有多个子视图的现有自定义视图自动布局
【发布时间】:2013-03-26 11:46:02
【问题描述】:

我正在尝试使用约束来制作布局,但我有许多带有内部嵌套子视图的自定义控件。我正在将约束添加到顶视图(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。

【问题讨论】:

  • 请展示您是如何创建自定义控件的 - 它们是在代码中、在 xib 中、使用自动布局、弹簧和支柱制作的吗?还请附上屏幕截图,指出错误的布局在哪里。目前很难回答这个问题。
  • 感谢回复,我正在代码中创建CustomView。
  • 那么,您可以编辑问题以包含代码吗?
  • 添加的代码请看一下
  • 因此,您尝试将 textFieldWithLabel 置于超级视图的中心。它是什么样子的?是不是在正确的地方,但尺寸不对?

标签: ios constraints frame autolayout addsubview


【解决方案1】:

在自动布局下,您的帧大小将被忽略(您在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:

【讨论】:

  • 感谢您的帮助!!会试试这个,让你知道,还有什么方法可以在设置约束后立即获取 UIVIew 的大小?
  • 您需要等到布局发生 - 视图控制器中的viewDidLayoutSubviews 是一个好地方。
  • 感谢现在工作!!问题在于尺寸设置,我们需要使用约束来设置尺寸。
【解决方案2】:

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

    self.YourLabel.translatesAutoresizingMaskIntoConstraints = NO;

【讨论】:

    【解决方案3】:

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

    在这种情况下,您最终会在构建应用程序时得到一个偷偷摸摸的 View。在 InterfaceBuilder 中,您拖入了一个视图,并且可能将类设置为“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”

    希望对您有所帮助。

    附:不要放弃 AutoLayout...掌握它!

    【讨论】:

      猜你喜欢
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多