我正在学习Objective C&在Instagram克隆上进行课堂作业。目前我的自动布局有问题。具体来说,图像&评论相互重叠:
我认为问题出在汽车布局中:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.mediaImageView = [[UIImageView alloc] init];
self.usernameAndCaptionLabel = [[UILabel alloc] init];
self.usernameAndCaptionLabel.numberOfLines = 0;
self.commentLabel = [[UILabel alloc] init];
self.commentLabel.numberOfLines = 0;
for (UIView *view in @[self.mediaImageView, self.usernameAndCaptionLabel, self.commentLabel]) {
[self.contentView addSubview:view];
view.translatesAutoresizingMaskIntoConstraints = NO;
}
NSDictionary *viewDictionary = NSDictionaryOfVariableBindings(_mediaImageView, _usernameAndCaptionLabel, _commentLabel);
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_mediaImageView]|" options:kNilOptions metrics:nil views:viewDictionary]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_usernameAndCaptionLabel]|" options:kNilOptions metrics:nil views:viewDictionary]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_commentLabel]|" options:kNilOptions metrics:nil views:viewDictionary]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_mediaImageView][_usernameAndCaptionLabel][_commentLabel]"
options:kNilOptions
metrics:nil
views:viewDictionary]];
self.imageHeightConstraint = [NSLayoutConstraint constraintWithItem:_mediaImageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:100];
self.usernameAndCaptionLabelHeightConstraint = [NSLayoutConstraint constraintWithItem:_usernameAndCaptionLabel
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:100];
self.commentLabelHeightConstraint = [NSLayoutConstraint constraintWithItem:_commentLabel
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:100];
[self.contentView addConstraints:@[self.imageHeightConstraint, self.usernameAndCaptionLabelHeightConstraint, self.commentLabelHeightConstraint]]; }
return self;
}
我已经完成了几次课程教程,并研究过iOS SDK Table Cell Overlapping,但未能找到合适的答案。
以下是整个代码:
#import "AppDelegate.h"
#import "UITableViewCell+BLCMediaTableViewCell.h"
#import "NSObject+BLCMedia.h"
#import "NSObject+BLCComment.h"
#import "NSObject+BLCUser.h"
//@implementation UITableViewCell (BLCMediaTableViewCell)
@interface BLCMediaTableViewCell() {
BLCMedia* _mediaItem;
}
@property (nonatomic, strong) UIImageView *mediaImageView;
@property (nonatomic, strong) UILabel *usernameAndCaptionLabel;
@property (nonatomic, strong) UILabel *commentLabel;
// Assignment: Added auto layout
@property (nonatomic, strong) NSLayoutConstraint *imageHeightConstraint;
@property (nonatomic, strong) NSLayoutConstraint *usernameAndCaptionLabelHeightConstraint;
@property (nonatomic, strong) NSLayoutConstraint *commentLabelHeightConstraint;
@end
static UIFont *lightFont;
static UIFont *boldFont;
static UIColor *usernameLabelGray;
static UIColor *commentLabelGray;
static UIColor *linkColor;
static NSParagraphStyle *paragraphStyle;
@implementation BLCMediaTableViewCell : UITableViewCell
- (void) layoutSubviews
{
[super layoutSubviews];
// Before layout, calculate the intrinsic size of the labels (the size they "want" to be), and add 20 to the height for some vertical padding.
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
self.imageView.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y, 100, 100);
CGSize maxSize = CGSizeMake(CGRectGetWidth(self.bounds), CGFLOAT_MAX);
CGSize usernameLabelSize = [self.usernameAndCaptionLabel sizeThatFits:maxSize];
CGSize commentLabelSize = [self.commentLabel sizeThatFits:maxSize];
self.usernameAndCaptionLabelHeightConstraint.constant = usernameLabelSize.height + 20;
self.commentLabelHeightConstraint.constant = commentLabelSize.height + 20;
// Hide the line between cells
self.separatorInset = UIEdgeInsetsMake(0, 0, 0, CGRectGetWidth(self.bounds));
}
+ (void)load {
lightFont = [UIFont fontWithName:@"HelveticaNeue-Thin" size:11];
boldFont = [UIFont fontWithName:@"HelveticaNeue-Bold" size:11];
usernameLabelGray = [UIColor colorWithRed:0.933 green:0.933 blue:0.933 alpha:1]; /*#eeeeee*/
commentLabelGray = [UIColor colorWithRed:0.898 green:0.898 blue:0.898 alpha:1]; /*#e5e5e5*/
linkColor = [UIColor colorWithRed:0.345 green:0.314 blue:0.427 alpha:1]; /*#58506d*/
NSMutableParagraphStyle *mutableParagraphStyle = [[NSMutableParagraphStyle alloc] init];
mutableParagraphStyle.headIndent = 20.0;
mutableParagraphStyle.firstLineHeadIndent = 20.0;
mutableParagraphStyle.tailIndent = -20.0;
mutableParagraphStyle.paragraphSpacingBefore = 5;
paragraphStyle = mutableParagraphStyle;
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.mediaImageView = [[UIImageView alloc] init];
self.usernameAndCaptionLabel = [[UILabel alloc] init];
self.usernameAndCaptionLabel.numberOfLines = 0;
self.commentLabel = [[UILabel alloc] init];
self.commentLabel.numberOfLines = 0;
for (UIView *view in @[self.mediaImageView, self.usernameAndCaptionLabel, self.commentLabel]) {
[self.contentView addSubview:view];
view.translatesAutoresizingMaskIntoConstraints = NO;
}
NSDictionary *viewDictionary = NSDictionaryOfVariableBindings(_mediaImageView, _usernameAndCaptionLabel, _commentLabel);
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_mediaImageView]|" options:kNilOptions metrics:nil views:viewDictionary]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_usernameAndCaptionLabel]|" options:kNilOptions metrics:nil views:viewDictionary]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_commentLabel]|" options:kNilOptions metrics:nil views:viewDictionary]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_mediaImageView][_usernameAndCaptionLabel][_commentLabel]"
options:kNilOptions
metrics:nil
views:viewDictionary]];
self.imageHeightConstraint = [NSLayoutConstraint constraintWithItem:_mediaImageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:100];
self.usernameAndCaptionLabelHeightConstraint = [NSLayoutConstraint constraintWithItem:_usernameAndCaptionLabel
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:100];
self.commentLabelHeightConstraint = [NSLayoutConstraint constraintWithItem:_commentLabel
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:100];
[self.contentView addConstraints:@[self.imageHeightConstraint, self.usernameAndCaptionLabelHeightConstraint, self.commentLabelHeightConstraint]]; }
return self;
}
- (NSAttributedString *) usernameAndCaptionString {
CGFloat usernameFontSize = 15;
// Make a string that says "username caption text"
NSString *baseString = [NSString stringWithFormat:@"%@ %@", self.mediaItem.user.userName, self.mediaItem.caption];
// Make an attributed string, with the "username" bold
NSMutableAttributedString *mutableUsernameAndCaptionString = [[NSMutableAttributedString alloc] initWithString:baseString attributes:@{NSFontAttributeName : [lightFont fontWithSize:usernameFontSize], NSParagraphStyleAttributeName : paragraphStyle}];
NSRange usernameRange = [baseString rangeOfString:self.mediaItem.user.userName];
[mutableUsernameAndCaptionString addAttribute:NSFontAttributeName value:[boldFont fontWithSize:usernameFontSize] range:usernameRange];
[mutableUsernameAndCaptionString addAttribute:NSForegroundColorAttributeName value:linkColor range:usernameRange];
return mutableUsernameAndCaptionString;
}
- (void) setMediaItem:(BLCMedia *)mediaItem {
_mediaItem = mediaItem;
self.mediaImageView.image = _mediaItem.image;
self.usernameAndCaptionLabel.attributedText = [self usernameAndCaptionString];
self.commentLabel.attributedText = [self commentString];
self.imageHeightConstraint.constant = self.mediaItem.image.size.height / self.mediaItem.image.size.width * CGRectGetWidth(self.contentView.bounds);
}
//Added
- (CGSize) sizeOfString:(NSAttributedString *)string {
CGSize maxSize = CGSizeMake(CGRectGetWidth(self.contentView.bounds) - 40, 0.0);
CGRect sizeRect = [string boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];
sizeRect.size.height += 20;
sizeRect = CGRectIntegral(sizeRect);
return sizeRect.size;
}
- (NSAttributedString *) commentString {
NSMutableAttributedString *commentString = [[NSMutableAttributedString alloc] init];
for (BLCComment *comment in self.mediaItem.comments) {
// Make a string that says "username comment text" followed by a line break
NSString *baseString = [NSString stringWithFormat:@"%@ %@\n", comment.from.userName, comment.text];
// Make an attributed string, with the "username" bold
NSMutableAttributedString *oneCommentString = [[NSMutableAttributedString alloc] initWithString:baseString attributes:@{NSFontAttributeName : lightFont, NSParagraphStyleAttributeName : paragraphStyle}];
NSRange usernameRange = [baseString rangeOfString:comment.from.userName];
[oneCommentString addAttribute:NSFontAttributeName value:boldFont range:usernameRange];
[oneCommentString addAttribute:NSForegroundColorAttributeName value:linkColor range:usernameRange];
[commentString appendAttributedString:oneCommentString];
}
return commentString;
}
+ (CGFloat) heightForMediaItem:(BLCMedia *)mediaItem width:(CGFloat)width {
// Make a cell
BLCMediaTableViewCell *layoutCell = [[BLCMediaTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"layoutCell"];
[layoutCell setNeedsLayout];
[layoutCell layoutIfNeeded];
// Get the actual height required for the cell
return CGRectGetMaxY(layoutCell.commentLabel.frame);
}
@end
答案 0 :(得分:0)
所以我弄清楚我做错了什么。我的layoutSubViews不正确。我已经收到了坏版本的屏幕截图&我公开的Dropbox中的更正版本。我希望这可以帮助其他人后来。
原始代码是:
- (void) layoutSubviews
{
[super layoutSubviews];
// Before layout, calculate the intrinsic size of the labels (the size they "want" to be), and add 20 to the height for some vertical padding.
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
self.imageView.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y, 100, 100);
CGSize maxSize = CGSizeMake(CGRectGetWidth(self.bounds), CGFLOAT_MAX);
CGSize usernameLabelSize = [self.usernameAndCaptionLabel sizeThatFits:maxSize];
CGSize commentLabelSize = [self.commentLabel sizeThatFits:maxSize];
self.usernameAndCaptionLabelHeightConstraint.constant = usernameLabelSize.height + 20;
self.commentLabelHeightConstraint.constant = commentLabelSize.height + 20;
// Hide the line between cells
self.separatorInset = UIEdgeInsetsMake(0, 0, 0, CGRectGetWidth(self.bounds));
}
它应该是:
- (void) layoutSubviews
{
[super layoutSubviews];
if (self.mediaItem == nil){
return;
}
// Before layout, calculate the intrinsic size of the labels (the size they "want" to be), and add 20 to the height for some vertical padding.
CGSize maxSize = CGSizeMake(CGRectGetWidth(self.bounds), CGFLOAT_MAX);
CGSize usernameLabelSize = [self.usernameAndCaptionLabel sizeThatFits:maxSize];
CGSize commentLabelSize = [self.commentLabel sizeThatFits:maxSize];
self.usernameAndCaptionLabelHeightConstraint.constant = usernameLabelSize.height + 20;
self.commentLabelHeightConstraint.constant = commentLabelSize.height + 20;
if (_mediaItem.image)
{
self.imageHeightConstraint.constant = self.mediaItem.image.size.height / self.mediaItem.image.size.width * CGRectGetWidth(self.contentView.bounds);
}
else
{
self.imageHeightConstraint.constant = 100;
}
//Hide the line between cells
self.separatorInset = UIEdgeInsetsMake(0, 0, 0, CGRectGetWidth(self.bounds));
}