如何在自定义视图中将子视图的框架设置为其父框架

Posted

技术标签:

【中文标题】如何在自定义视图中将子视图的框架设置为其父框架【英文标题】:How to set a subview's frame to be its parent's frame in a custom view 【发布时间】:2014-02-18 05:23:23 【问题描述】:

我想将自定义视图的框架设置为我的子视图的框架,它是一个 UILabel。但 当我使用 self.frame 时,UILabel 显示空文本。我需要硬编码CGRectMake 中的参数才能看到我的UILabel。如何将 UILabel 的框架设置为我的自定义视图的框架?

- (id)initWithFrame:(CGRect)frame withText:(NSString *)text

    self = [super initWithFrame:frame];

    if (self) 
        self.backgroundColor = [UIColor grayColor];
        self.layer.cornerRadius = 3;
        self.layer.borderWidth = 1;
        self.layer.borderColor = [UIColor blackColor].CGColor;
        _text = text;
    

    return self;


- (void)layoutSubviews

    // This works
    // UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 40)];
    // This doesn't work
    UILabel *label = [[UILabel alloc] initWithFrame:self.frame];
    label.text = @"";
    if (![self.text isEqualToString:@"?"]) 
        label.text = self.text;
        label.textAlignment = NSTextAlignmentCenter;
    

    [self addSubview:label];

【问题讨论】:

【参考方案1】:

layoutSubviews 会被多次调用,所以你不应该这样addSubview。更好的风格是设置 UILabel 的属性,比如你的 text 属性:

@property (nonatomic, strong) UILabel * label;

然后更改您的layoutSubviews 代码:

- (void)layoutSubviews

    if(!self.label)
         self.label = [[UILabel alloc] initWithFrame:self.frame]; //Use ARC
         self.label.textAlignment = NSTextAlignmentCenter;
         [self addSubview:self.label];
    

    self.label.frame = self.bounds;
    if (![self.text isEqualToString:@"?"]) 
        self.label.text = self.text;
    

【讨论】:

这是个坏主意。您不想在 layoutSubviews 方法中创建视图。它可以被多次调用,通常在某些情况下,因此每次都检查是否已经创建了标签会影响性能。如果您打算将初始帧设置为 self.frame 而不是 self.bounds ,那么为什么要将其更改为下面几行的边界?此外,在此函数中设置 label.text 属性是一个坏主意。您无法控制何时调用此方法。 当然!将初始化视图放入 initWithFrame: 即可。我的代码是懒加载的风格,把init代码放在view开始使用的地方会更好。因为显示的代码是有限的,所以我只是把它放在 layoutSubviews 中。 @戴夫伍德【参考方案2】:

试试下面的代码。

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 70, 40)]; // set frame as you want
label.backgroundColor = [UIColor yellowColor]; // set color as you want
label.text = @"Hellow";
[yourParentView addSubview:label];

【讨论】:

【参考方案3】:

使用此代码

- (id)initWithFrame:(CGRect)frame withText:(NSString *)text

    self = [super initWithFrame:frame];

    if (self) 
        self.backgroundColor = [UIColor grayColor];
        self.layer.cornerRadius = 3;
        self.layer.borderWidth = 1;
        self.layer.borderColor = [UIColor blackColor].CGColor;
        _text = text;

     [self layoutSubviews:frame];
    

    return self;


- (void)layoutSubviews:(CGRect)myFrame

    // This works
    // UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 40)];
    // This doesn't work
    UILabel *label = [[UILabel alloc] initWithFrame:myFrame];
    label.text = @"";
    if (![self.text isEqualToString:@"?"]) 
        label.text = self.text;
        label.textAlignment = NSTextAlignmentCenter;
    

    [self addSubview:label];

【讨论】:

【参考方案4】:

您不想在layoutSubviews 方法中创建视图。该方法可以被多次调用,并且您将多次创建每个视图(让它们相互重叠)。

改为在initWithFrame 方法中创建您需要的视图。

对于您的实际问题的答案,您可能需要将新标签的框架设置为自定义视图的边界。边界的原点为 0,0,因此无论自定义视图放置在其父视图中的哪个位置,它都将起作用。如果您使用框架,标签将偏移自定义视图的偏移量。

您可能可以完全删除您的 layoutSubviews 方法,因为这也不是设置标签文本的地方。然后添加:

- (instancetype)initWithFrame:(CGRect)frame withText:(NSString *)text

    self = [super initWithFrame:frame];
    if (!self) return nil;

    self.backgroundColor = [UIColor grayColor];
    self.layer.cornerRadius = 3;
    self.layer.borderWidth = 1;
    self.layer.borderColor = [UIColor blackColor].CGColor;
    _text = text;

    UILabel *label = [[UILabel alloc] initWithFrame:self.bounds];
    label.text = @"";
    if (![self.text isEqualToString:@"?"]) 
        label.text = self.text;
        label.textAlignment = NSTextAlignmentCenter;
    

    [self addSubview:label];

    return self;

如果您希望在自定义视图调整大小时调整标签大小,您可以通过设置 label.frame = self.bounds; 在 layoutSubviews 中执行此操作,但最好使用自动调整大小掩码或自动布局。

【讨论】:

以上是关于如何在自定义视图中将子视图的框架设置为其父框架的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式设置子视图的框架以使其适合其父视图?

iOS:在自定义视图中添加新约束依赖于视图的框架

将 UIImagePickerController 添加为子视图

如何使 UIScrollView 在 NSLayoutConstraint 中适合其父框架?

如何在 Swift 中将内容包装为自定义视图

为子视图的子视图设置框架