使用 AutoLayout 调整 UICollectionViewCell 及其内容的大小

Posted

技术标签:

【中文标题】使用 AutoLayout 调整 UICollectionViewCell 及其内容的大小【英文标题】:Resizing UICollectionViewCell and it's contents using AutoLayout 【发布时间】:2015-02-05 17:08:49 【问题描述】:

我正在尝试将 custom button 添加到 custom UICollectionViewCell

因为我无法在 Interface Builder 中添加自定义按钮(需要使用特定方法分配它),所以我添加了一个 UIView 作为它的占位符,它具有清晰的背景(黑色用于本问题的演示) .

看起来是这样的:

然后在 UICollectonViewCell 的自定义类中的代码中:

- (void)awakeFromNib 
// Initialization code
self.btnAddOrRemove = [[HTPressableButton alloc] initWithFrame:self.btnContainerView.bounds buttonStyle:HTPressableButtonStyleRounded];
self.btnAddOrRemove.center = CGPointMake(self.center.x, self.btnAddOrRemove.center.y);
//self.btnContainerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;


- (void)layoutSubviews

[super layoutSubviews];

CGRect bounds = self.bounds;
if (self.shadowWidth != bounds.size.width)

    if (self.shadowWidth == 0)
    
        [self.layer setMasksToBounds:NO ];
        [self.layer setShadowColor:[[UIColor blackColor ] CGColor ] ];
        [self.layer setShadowOpacity:0.5 ];
        [self.layer setShadowRadius:5.0 ];
        [self.layer setShadowOffset:CGSizeMake( 0 , 0 ) ];
        self.layer.cornerRadius = 5.0;
    
    [self.layer setShadowPath:[[UIBezierPath bezierPathWithRect:bounds ] CGPath ] ];

    if ([ChosenCategory getInstance].doesExist) 
        if ([ChosenCategory getInstance].category == self.ingredientCategory) 
            [self.btnAddOrRemove setTitle:NSLocalizedString(@"Edit profile", nil) forState:UIControlStateNormal];
            [self.btnAddOrRemove setButtonColor:[UIColor ht_mediumColor]];
            [self.btnAddOrRemove setShadowColor:[UIColor ht_mediumDarkColor]];
            [self.btnAddOrRemove setTitleColor:[UIColor ht_ashColor] forState:UIControlStateNormal];
            [self.btnAddOrRemove setTitleColor:[UIColor ht_ashColor] forState:UIControlStateHighlighted];
            [self.btnAddOrRemove addTarget:self action:@selector(toDetail:) forControlEvents:UIControlEventTouchUpInside];
        
        else 
            [self.btnAddOrRemove setTitle:NSLocalizedString(@"Choose Profile", nil) forState:UIControlStateNormal];
            [self.btnAddOrRemove setButtonColor:[UIColor ht_bitterSweetColor]];
            [self.btnAddOrRemove setShadowColor:[UIColor ht_bitterSweetDarkColor]];
            [self.btnAddOrRemove setTitleColor:[UIColor ht_ashColor] forState:UIControlStateNormal];
            [self.btnAddOrRemove setTitleColor:[UIColor ht_ashColor] forState:UIControlStateHighlighted];
            [self.btnAddOrRemove addTarget:self action:@selector(chosenProfile:) forControlEvents:UIControlEventTouchUpInside];
        
    
    else 
        [self.btnAddOrRemove setTitle:NSLocalizedString(@"Choose profile", nil) forState:UIControlStateNormal];
        [self.btnAddOrRemove setButtonColor:[UIColor ht_mediumColor]];
        [self.btnAddOrRemove setShadowColor:[UIColor ht_mediumDarkColor]];
        [self.btnAddOrRemove setTitleColor:[UIColor ht_ashColor] forState:UIControlStateNormal];
        [self.btnAddOrRemove setTitleColor:[UIColor ht_ashColor] forState:UIControlStateHighlighted];
        [self.btnAddOrRemove addTarget:self action:@selector(chosenProfile:) forControlEvents:UIControlEventTouchUpInside];
    

    [self.btnContainerView addSubview:self.btnAddOrRemove];

    self.shadowWidth = bounds.size.width;
    self.lblSummary.preferredMaxLayoutWidth = self.lblSummary.frame.size.width;


但正如您所见,自定义按钮没有获得 containerView 的全部宽度。它也没有正确居中。

所以我有两个问题:

1) 如何在使用 AutoLayout 时将自定义按钮添加到使用容器 UIView 的全宽的视图中。

2) 有没有办法在卡片的左右添加空格?

【问题讨论】:

您在第一个问题中说“使用自动布局时”,但您没有在按钮及其容器之间使用自动布局。不要设置按钮的框架,而是使用约束将其固定到容器视图的所有四个侧面。 @rdelmar 感谢您的回答。我怎么能这样做? 【参考方案1】:

因为您对所有其他视图都使用了约束,所以我建议您对按钮执行相同的操作。您可以尝试使用一些视觉布局约束来设置按钮上的框架,而不是使用静态框架

- (void)awakeFromNib


    self.btnAddOrRemove = [[HTPressableButton alloc] initWithFrame:self.btnContainerView.bounds buttonStyle:HTPressableButtonStyleRounded];
    [self.btnContainerView addSubView:self.btnAddOrRemove];
    [self.btnAddOrRemove setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self.btnAddOrRemove addConstraintsToFillParentHorizontally:self.btnContainerView]
    [self.btnAddOrRemove addConstraintsToFillParentVertically:self.btnContainerView]


- (void)addConstraintsToFillParentHorizontally:(UIView *)parentView

    [parentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:@ @"view": self ]];


- (void)addConstraintsToFillParentVertically:(UIView *)parentView

    [parentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|" options:0 metrics:nil views:@ @"view": self ]];

这应该使按钮的框架与容器视图之一匹配。然后你还需要做的就是在 layoutSubviews 方法中应用圆角

- (void)layoutSubviews

    [super layoutSubviews];
    if (self.shadowWidth == 0)
    
        [self.layer setMasksToBounds:NO ];
        [self.layer setShadowColor:[[UIColor blackColor] CGColor]];
        [self.layer setShadowOpacity:0.5 ];
        [self.layer setShadowRadius:5.0 ];
        [self.layer setShadowOffset:CGSizeMake(0, 0)];
        self.layer.cornerRadius = 5.0;
    
    [self.layer setShadowPath:[[UIBezierPath bezierPathWithRect:bounds ] CGPath ] ];

希望它有效!

【讨论】:

感谢您的回答,但我选择实现一个不同的库,使我能够在 Interface Builder 中声明自定义按钮,这样问题就不再存在了。我的第二个问题仍然存在(如何减小自定义“卡片”的宽度)【参考方案2】:

实际上,如果您只想将占位符视图背景颜色设置为透明,则可以保留按钮原样

UIColor.clearcolor()

并将底部居中放置UIButton rect 相同大小的占位符视图,然后设置按钮的内容模式以在里面输入背景图像!!!

contentMode = UIViewContentMode.Center

【讨论】:

以上是关于使用 AutoLayout 调整 UICollectionViewCell 及其内容的大小的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Autolayout 调整 UITableView 的大小?

使用 AutoLayout 调整 UIStackView 的大小

如何防止 UIImageView 使用 Autolayout 调整大小

UIStackView 内的视图未使用 AutoLayout 调整大小

如何使用 Cocoa Autolayout 根据优先级调整两个子视图的大小?

使用 AutoLayout 将 UIView 调整为离散值