以编程方式从 XIB 调整自定义 UIView 的大小
Programmatically resize custom UIView from XIB
我有以下问题:我在 XIB
文件中创建了自定义 UIView
class 及其布局。假设我在 XIB 中的自定义视图的大小是 150 x 50。我启用了 sizeClasses
(wAny hAny) 和 AutoLayout
。在模拟指标中,我设置了 Size = Freeform
、Status Bar = None
、全部 other = Inferred
.
我的自定义代码 UIView
class 如下所示:
#import "CustomView.h"
@implementation CustomView
#pragma mark - Object lifecycle
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self setup];
}
return self;
}
#pragma mark - Private & helper methods
- (void)setup {
if (self.subviews.count == 0) {
[[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil];
self.bounds = self.view.bounds;
[self addSubview:self.view];
}
}
@end
在我想要添加此自定义 UIView
的 UIViewController
中,我制作了虚拟 UIView(我在 Interface Builder 中设置的大小),我想在其中添加我的 CustomView
和 我希望我的 CustomView
符合容器视图的范围 。
我正在尝试这样做:
_vCustomView = [[CustomView alloc] init];
_vCustomView.translatesAutoresizingMaskIntoConstraints = NO;
[_vContainer addSubview:_vCustomView];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
但运气不好。假设我的容器视图是 300 x 100,当我向其中添加自定义 UIView
时,我的自定义视图仍然是 150 x 50。
我尝试在没有容器视图的情况下工作 - 将我的自定义 UIView
对象直接添加到我的 UIViewController
的 self.view 并设置它的宽度和高度:
autoLayout
约束条件
- 在初始化我的自定义
UIView
时使用 initWithFrame
但又一次 - 运气不好。自定义视图始终为 150 x 50。
有人可以向我解释一下如何 以编程方式添加在 XIB
中制作的自定义 UIView
并使用 autoLayout
约束 调整它的大小吗?
非常感谢。
编辑 #1:尝试在我的 CustomView 上 运行 Andrea 的代码时出现错误
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)
(
"<NSLayoutConstraint:0x17489b760 V:[UIView:0x17418d820(91)]>",
"<NSLayoutConstraint:0x170c9bf80 V:|-(0)-[CustomView:0x1741da7c0] (Names: '|':CustomView:0x1741da8b0 )>",
"<NSLayoutConstraint:0x170c9bfd0 V:[CustomView:0x1741da7c0]-(0)-| (Names: '|':CustomView:0x1741da8b0 )>",
"<NSLayoutConstraint:0x170c9be90 V:|-(0)-[CustomView:0x1741da8b0] (Names: '|':UIView:0x17418d820 )>",
"<NSLayoutConstraint:0x170c9bee0 CustomView:0x1741da8b0.bottom == UIView:0x17418d820.bottom>",
"<NSAutoresizingMaskLayoutConstraint:0x170c9dba0 h=--& v=--& CustomView:0x1741da7c0.midY == + 25.0>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x170c9bfd0 V:[CustomView:0x1741da7c0]-(0)-| (Names: '|':CustomView:0x1741da8b0 )>
编辑#2:有效!
@Andrea 添加后:
view.translatesAutoresizingMaskIntoConstraints = NO;
在他的:
- (void) stretchToSuperView:(UIView*) view;
方法,一切如我所料。
感谢@Andrea。
我想主要问题是当您将 xib 添加到内容视图时没有使用自动布局。
在初始化方法中添加子视图后,请调用该方法,传递 xib 的视图:
- (void) stretchToSuperView:(UIView*) view {
view.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *bindings = NSDictionaryOfVariableBindings(view);
NSString *formatTemplate = @"%@:|[view]|";
for (NSString * axis in @[@"H",@"V"]) {
NSString * format = [NSString stringWithFormat:formatTemplate,axis];
NSArray * constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:bindings];
[view.superview addConstraints:constraints];
}
}
[编辑]
您的设置代码应如下所示:
- (void)setup {
if (self.subviews.count == 0) {
[[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil];
self.bounds = self.view.bounds;
[self addSubview:self.view];
[self stretchToSuperView:self.view];
}
}
注意我添加的内部拉伸视图 view.translatesAutoresizingMaskIntoConstraints = NO;
[编辑 2]
我将尝试根据要求详细说明我的答案。使用自动布局,当你添加一个没有设置约束的视图时,自动布局会自动将自动调整大小的掩码转换为约束,其中默认的 属性 是 UIViewAutoresizingNone
,这意味着不自动调整大小。
您的 XIB 视图已无限制地添加到其父级,并且无法自动调整大小,从而保持其原始大小。由于您希望视图根据您的视图调整大小,因此您有两个选择:
- 将 xib 视图的自动调整大小掩码更改为灵活的宽度和高度,但它们需要匹配父级大小,否则您将无法完全覆盖
- 添加一些约束,约束两个视图根据父视图的变化进行相应的变化。你实现了 XIB 视图和它的父视图之间的说法 trailing/leading 和 top/botton 之间的 space 是 0。就像你在它们的边界上涂了一些胶水。为此,您需要将 autotranslate resizing mask into constraint 设置为 NO,否则您在日志中发布时可能会发生一些冲突。
您稍后要做的是向其父视图的视图(承载 XIB 视图)添加约束,但是 XIB 与其父视图之间没有约束,因此自动布局不知道如何调整 XIB 的大小看法。
视图层次结构中的每个视图都应该有自己的约束。
希望这有助于更好地理解。
在你的代码中你应该有这样的东西:
首先,在 viewController 或 CustomView
中对您想要更改的宽度约束进行 IBOutlet
(我真的不知道您有什么逻辑来计算约束值)。
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *widthConstraint;
然后,在您想要更新常量值的方法中,您将得到如下内容:
-(void)updateWidth {
[self.widthConstraint setConstant:newConstant];
[self.view layoutIfNeeded]; // self.view must be an ancestor of the view
//If you need the changes animated, call layoutIfNeeded in an animation block
}
希望这对你有用。祝你好运!
Swift 4.0函数拉伸到超级视图:
代码段:
static public func stretchToSuperView(view:UIView)
{
view.translatesAutoresizingMaskIntoConstraints = false
var d = Dictionary<String,UIView>()
d["view"] = view
for axis in ["H","V"] {
let format = "\(axis):|[view]|"
let constraints = NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(rawValue: 0), metrics: [:], views: d)
view.superview?.addConstraints(constraints)
}
}
注意:只需将参数作为子视图调用函数即可。
这有助于我解决 swift 4.0 中的 .xib resing 问题。
我有以下问题:我在 XIB
文件中创建了自定义 UIView
class 及其布局。假设我在 XIB 中的自定义视图的大小是 150 x 50。我启用了 sizeClasses
(wAny hAny) 和 AutoLayout
。在模拟指标中,我设置了 Size = Freeform
、Status Bar = None
、全部 other = Inferred
.
我的自定义代码 UIView
class 如下所示:
#import "CustomView.h"
@implementation CustomView
#pragma mark - Object lifecycle
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self setup];
}
return self;
}
#pragma mark - Private & helper methods
- (void)setup {
if (self.subviews.count == 0) {
[[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil];
self.bounds = self.view.bounds;
[self addSubview:self.view];
}
}
@end
在我想要添加此自定义 UIView
的 UIViewController
中,我制作了虚拟 UIView(我在 Interface Builder 中设置的大小),我想在其中添加我的 CustomView
和 我希望我的 CustomView
符合容器视图的范围 。
我正在尝试这样做:
_vCustomView = [[CustomView alloc] init];
_vCustomView.translatesAutoresizingMaskIntoConstraints = NO;
[_vContainer addSubview:_vCustomView];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]];
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
但运气不好。假设我的容器视图是 300 x 100,当我向其中添加自定义 UIView
时,我的自定义视图仍然是 150 x 50。
我尝试在没有容器视图的情况下工作 - 将我的自定义 UIView
对象直接添加到我的 UIViewController
的 self.view 并设置它的宽度和高度:
autoLayout
约束条件- 在初始化我的自定义
UIView
时使用
initWithFrame
但又一次 - 运气不好。自定义视图始终为 150 x 50。
有人可以向我解释一下如何 以编程方式添加在 XIB
中制作的自定义 UIView
并使用 autoLayout
约束 调整它的大小吗?
非常感谢。
编辑 #1:尝试在我的 CustomView 上 运行 Andrea 的代码时出现错误
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)
(
"<NSLayoutConstraint:0x17489b760 V:[UIView:0x17418d820(91)]>",
"<NSLayoutConstraint:0x170c9bf80 V:|-(0)-[CustomView:0x1741da7c0] (Names: '|':CustomView:0x1741da8b0 )>",
"<NSLayoutConstraint:0x170c9bfd0 V:[CustomView:0x1741da7c0]-(0)-| (Names: '|':CustomView:0x1741da8b0 )>",
"<NSLayoutConstraint:0x170c9be90 V:|-(0)-[CustomView:0x1741da8b0] (Names: '|':UIView:0x17418d820 )>",
"<NSLayoutConstraint:0x170c9bee0 CustomView:0x1741da8b0.bottom == UIView:0x17418d820.bottom>",
"<NSAutoresizingMaskLayoutConstraint:0x170c9dba0 h=--& v=--& CustomView:0x1741da7c0.midY == + 25.0>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x170c9bfd0 V:[CustomView:0x1741da7c0]-(0)-| (Names: '|':CustomView:0x1741da8b0 )>
编辑#2:有效!
@Andrea 添加后:
view.translatesAutoresizingMaskIntoConstraints = NO;
在他的:
- (void) stretchToSuperView:(UIView*) view;
方法,一切如我所料。
感谢@Andrea。
我想主要问题是当您将 xib 添加到内容视图时没有使用自动布局。
在初始化方法中添加子视图后,请调用该方法,传递 xib 的视图:
- (void) stretchToSuperView:(UIView*) view {
view.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *bindings = NSDictionaryOfVariableBindings(view);
NSString *formatTemplate = @"%@:|[view]|";
for (NSString * axis in @[@"H",@"V"]) {
NSString * format = [NSString stringWithFormat:formatTemplate,axis];
NSArray * constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:bindings];
[view.superview addConstraints:constraints];
}
}
[编辑]
您的设置代码应如下所示:
- (void)setup {
if (self.subviews.count == 0) {
[[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil];
self.bounds = self.view.bounds;
[self addSubview:self.view];
[self stretchToSuperView:self.view];
}
}
注意我添加的内部拉伸视图 view.translatesAutoresizingMaskIntoConstraints = NO;
[编辑 2]
我将尝试根据要求详细说明我的答案。使用自动布局,当你添加一个没有设置约束的视图时,自动布局会自动将自动调整大小的掩码转换为约束,其中默认的 属性 是 UIViewAutoresizingNone
,这意味着不自动调整大小。
您的 XIB 视图已无限制地添加到其父级,并且无法自动调整大小,从而保持其原始大小。由于您希望视图根据您的视图调整大小,因此您有两个选择:
- 将 xib 视图的自动调整大小掩码更改为灵活的宽度和高度,但它们需要匹配父级大小,否则您将无法完全覆盖
- 添加一些约束,约束两个视图根据父视图的变化进行相应的变化。你实现了 XIB 视图和它的父视图之间的说法 trailing/leading 和 top/botton 之间的 space 是 0。就像你在它们的边界上涂了一些胶水。为此,您需要将 autotranslate resizing mask into constraint 设置为 NO,否则您在日志中发布时可能会发生一些冲突。
您稍后要做的是向其父视图的视图(承载 XIB 视图)添加约束,但是 XIB 与其父视图之间没有约束,因此自动布局不知道如何调整 XIB 的大小看法。
视图层次结构中的每个视图都应该有自己的约束。
希望这有助于更好地理解。
在你的代码中你应该有这样的东西:
首先,在 viewController 或 CustomView
中对您想要更改的宽度约束进行 IBOutlet
(我真的不知道您有什么逻辑来计算约束值)。
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *widthConstraint;
然后,在您想要更新常量值的方法中,您将得到如下内容:
-(void)updateWidth {
[self.widthConstraint setConstant:newConstant];
[self.view layoutIfNeeded]; // self.view must be an ancestor of the view
//If you need the changes animated, call layoutIfNeeded in an animation block
}
希望这对你有用。祝你好运!
Swift 4.0函数拉伸到超级视图:
代码段:
static public func stretchToSuperView(view:UIView)
{
view.translatesAutoresizingMaskIntoConstraints = false
var d = Dictionary<String,UIView>()
d["view"] = view
for axis in ["H","V"] {
let format = "\(axis):|[view]|"
let constraints = NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(rawValue: 0), metrics: [:], views: d)
view.superview?.addConstraints(constraints)
}
}
注意:只需将参数作为子视图调用函数即可。
这有助于我解决 swift 4.0 中的 .xib resing 问题。