如何在 iOS 6 中使用具有多个子视图的现有自定义视图自动布局
Posted
技术标签:
【中文标题】如何在 iOS 6 中使用具有多个子视图的现有自定义视图自动布局【英文标题】:How to Auto Layout with existing Custom View with multiple subviews in 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 置于超级视图的中心。它是什么样子的?是不是在正确的地方,但尺寸不对? 【参考方案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...掌握它!
【讨论】:
以上是关于如何在 iOS 6 中使用具有多个子视图的现有自定义视图自动布局的主要内容,如果未能解决你的问题,请参考以下文章
如何在 iOS SDK 中禁用 UIView/UIViewController 的“突出显示子视图”消息?