UITableViewCell 子视图不遵守自动布局约束
UITableViewCell subviews are not honoring the Autolayout constraints
我正在绘制一个相当简单的自定义 UITableViewCell-- 左侧是缩略图,右侧是名称和 link 标签。我希望我的名字和 link 标签是单行的,如果文本超过单元格的宽度则在尾部截断。我很确定我添加的约束是正确的,但我的名字和 link 标签不会遵守它们。
这是 iPhone 4S 运行 iOS 8 上的电池的样子:
在我的代码中,我为超级视图(单元格的 contentView
)的名称和 link 标签添加了一个 10 点尾随约束,但是请注意,即使在横向视图中,iOS 似乎不遵守这些限制。
有人可以告诉我我做错了什么吗?这是我的整个单元格的代码。我正在以编程方式创建视图,并且在 table 视图单元格的初始值设定项中有自动布局约束。
#import "PopularWikiCell.h"
// Models
#import "Wiki.h"
// Pods
#import "UIImageView+AFNetworking.h"
// Constants
static const CGFloat kPadding = 10;
static const CGFloat kImageSize = 100;
const CGFloat kPopularWikiCellHeight = kImageSize + kPadding * 2;
@interface PopularWikiCell ()
@property (nonatomic, strong) UIImageView *thumbnailView;
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *linkLabel;
@end
@implementation PopularWikiCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// Initialise the subviews.
_thumbnailView = [[UIImageView alloc] init];
_thumbnailView.contentMode = UIViewContentModeScaleAspectFill;
_thumbnailView.clipsToBounds = YES;
_nameLabel = [[UILabel alloc] init];
_nameLabel.backgroundColor = [UIColor blueColor];
_nameLabel.numberOfLines = 1;
_nameLabel.lineBreakMode = NSLineBreakByTruncatingTail;
_nameLabel.text = @"Name";
_linkLabel = [[UILabel alloc] init];
_linkLabel.backgroundColor = [UIColor redColor];
_linkLabel.text = @"Link";
_linkLabel.numberOfLines = 1;
_linkLabel.lineBreakMode = NSLineBreakByTruncatingTail;
// Add the subviews.
[self.contentView addSubview:_thumbnailView];
[self.contentView addSubview:_nameLabel];
[self.contentView addSubview:_linkLabel];
_thumbnailView.translatesAutoresizingMaskIntoConstraints = NO;
_nameLabel.translatesAutoresizingMaskIntoConstraints = NO;
_linkLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
// Add the layout constraints.
NSDictionary *metrics = @{@"kPadding" : @(kPadding),
@"kImageSize" : @(kImageSize)};
NSDictionary *views = @{@"thumbnailView" : _thumbnailView,
@"nameLabel" : _nameLabel,
@"linkLabel" : _linkLabel};
NSArray *constraints = @[@"H:|-kPadding-[thumbnailView(kImageSize)]-kPadding-[nameLabel]-kPadding-|",
@"H:[thumbnailView]-kPadding-[linkLabel]-kPadding-|",
@"V:|-kPadding-[nameLabel]-0-[linkLabel]",
@"V:|-kPadding-[thumbnailView(kImageSize)]"];
[self.contentView addConstraintsFromVisualFormatStrings:constraints
options:0
metrics:metrics
views:views];
}
return self;
}
- (void)setWiki:(Wiki *)wiki
{
_wiki = wiki;
self.thumbnailView.image = nil;
self.thumbnailView.backgroundColor = [UIColor darkGrayColor];
__weak typeof(self) weakSelf = self;
[self.thumbnailView setImageWithURLRequest:[NSURLRequest requestWithURL:wiki.thumbnailURL]
placeholderImage:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
__strong typeof(self) strongSelf = weakSelf;
strongSelf.thumbnailView.image = image;
strongSelf.thumbnailView.backgroundColor = [UIColor whiteColor];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
}];
self.nameLabel.text = wiki.name;
self.linkLabel.text = wiki.URL;
[self.contentView setNeedsLayout];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Selection removes all background colors so re-set it.
[self resetSubviewBackgroundColors];
[self.contentView setNeedsLayout];
}
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
[super setHighlighted:highlighted animated:animated];
// Highlighing removes all background colors so re-set it.
[self resetSubviewBackgroundColors];
[self.contentView setNeedsLayout];
}
- (void)resetSubviewBackgroundColors
{
if (self.thumbnailView.image) {
self.thumbnailView.backgroundColor = [UIColor whiteColor];
} else {
self.thumbnailView.backgroundColor = [UIColor darkGrayColor];
}
}
@end
首先我强烈推荐使用自动布局,它解决了很多尺寸问题和很多计算
但是,如果您没有设置约束,那么您必须计算字符串的长度以适应您想要的标签的宽度
NSString *string = @"this is a very long string to fit into a UILabel";
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 50, 150, 20)];
UIFont *font = [UIFont fontWithName:@"Helvetica Neue" size:15.0];
label.font = font;
label.text = string;
CGSize stringSize = [string sizeWithAttributes:@{NSFontAttributeName : font}];
// check if the string is wider then the label
if (stringSize.width > label.bounds.size.width) {
NSString *newString = [string substringWithRange:NSMakeRange(0, string.length/2)]; <---- i just divided the string into two -----
// check if the newString fits the label
// if not the divide again
label.text = newString;
}else{
label.text = string;
}
[self.view addSubview:label];
就像我在代码中写的那样,我只是将字符串分成两个字符串。如果字符串很长,这可能不起作用,因此您需要不断检查字符串是否符合标签。
您可以使用:
[NSString stringWithFormat:@"%@...", [string substringToIndex:20]];
在字符串末尾添加“...”
在您的 cellForRow: 方法中确保您正在调用:
cell = [tableView dequeueReusableCellWithReuseIdentifier:@"" forIndexPath:(IndexPath *)
将此 returns 称为大小正确的单元格(对于自动布局很重要)
如果这不能解决问题,请在您的手机内执行:
-(void)layoutSubview{
[super layoutSubviews];
[self layoutIfNeeded];
}
您好,您可以在您的自定义 UITableViewCell 中尝试此操作,设置内容视图或标签的框架或使用这些元素的任何元素:-
在声明中:-
GRect usableSpace;
CGFloat usableWidth, usableHeight;
实施中:-
usableSpace = [[UIScreen mainScreen] applicationFrame];
usableWidth = usableSpace.size.width;
usableHeight = usableSpace.size.height;
然后使用这些宽度和高度设置框架
问题隐藏在
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
删除此代码可解决您的问题。
如果您不想 将自动调整掩码转换为约束条件 - 为 cell.contentView.
设置您想要的约束条件
我无法加载你的图片,所以我不确定你遇到了什么问题。
我看到这段代码了,有错字吗?
NSArray *constraints =
@[
@"H:|-kPadding-[thumbnailView(kImageSize)]-kPadding-[nameLabel]-kPadding-|",
@"H:[thumbnailView]-kPadding-[linkLabel]-kPadding-|", //this line you forgot the left edge
@"V:|-kPadding-[nameLabel]-0-[linkLabel]",
@"V:|-kPadding-[thumbnailView(kImageSize)]"
];
尽管我的视图看起来不错,但我得到的宽度不正确,底层的 CGRect 是错误的。
当使用 CAShapeLayer
为我的单元格添加边框时,它变得很明显。
我通过在 contentView
上调用 layoutIfNeeded()
修复了它
override func layoutSubviews() {
super.layoutSubviews()
contentView.layoutIfNeeded()
}
我正在绘制一个相当简单的自定义 UITableViewCell-- 左侧是缩略图,右侧是名称和 link 标签。我希望我的名字和 link 标签是单行的,如果文本超过单元格的宽度则在尾部截断。我很确定我添加的约束是正确的,但我的名字和 link 标签不会遵守它们。
这是 iPhone 4S 运行 iOS 8 上的电池的样子:
在我的代码中,我为超级视图(单元格的 contentView
)的名称和 link 标签添加了一个 10 点尾随约束,但是请注意,即使在横向视图中,iOS 似乎不遵守这些限制。
有人可以告诉我我做错了什么吗?这是我的整个单元格的代码。我正在以编程方式创建视图,并且在 table 视图单元格的初始值设定项中有自动布局约束。
#import "PopularWikiCell.h"
// Models
#import "Wiki.h"
// Pods
#import "UIImageView+AFNetworking.h"
// Constants
static const CGFloat kPadding = 10;
static const CGFloat kImageSize = 100;
const CGFloat kPopularWikiCellHeight = kImageSize + kPadding * 2;
@interface PopularWikiCell ()
@property (nonatomic, strong) UIImageView *thumbnailView;
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *linkLabel;
@end
@implementation PopularWikiCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// Initialise the subviews.
_thumbnailView = [[UIImageView alloc] init];
_thumbnailView.contentMode = UIViewContentModeScaleAspectFill;
_thumbnailView.clipsToBounds = YES;
_nameLabel = [[UILabel alloc] init];
_nameLabel.backgroundColor = [UIColor blueColor];
_nameLabel.numberOfLines = 1;
_nameLabel.lineBreakMode = NSLineBreakByTruncatingTail;
_nameLabel.text = @"Name";
_linkLabel = [[UILabel alloc] init];
_linkLabel.backgroundColor = [UIColor redColor];
_linkLabel.text = @"Link";
_linkLabel.numberOfLines = 1;
_linkLabel.lineBreakMode = NSLineBreakByTruncatingTail;
// Add the subviews.
[self.contentView addSubview:_thumbnailView];
[self.contentView addSubview:_nameLabel];
[self.contentView addSubview:_linkLabel];
_thumbnailView.translatesAutoresizingMaskIntoConstraints = NO;
_nameLabel.translatesAutoresizingMaskIntoConstraints = NO;
_linkLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
// Add the layout constraints.
NSDictionary *metrics = @{@"kPadding" : @(kPadding),
@"kImageSize" : @(kImageSize)};
NSDictionary *views = @{@"thumbnailView" : _thumbnailView,
@"nameLabel" : _nameLabel,
@"linkLabel" : _linkLabel};
NSArray *constraints = @[@"H:|-kPadding-[thumbnailView(kImageSize)]-kPadding-[nameLabel]-kPadding-|",
@"H:[thumbnailView]-kPadding-[linkLabel]-kPadding-|",
@"V:|-kPadding-[nameLabel]-0-[linkLabel]",
@"V:|-kPadding-[thumbnailView(kImageSize)]"];
[self.contentView addConstraintsFromVisualFormatStrings:constraints
options:0
metrics:metrics
views:views];
}
return self;
}
- (void)setWiki:(Wiki *)wiki
{
_wiki = wiki;
self.thumbnailView.image = nil;
self.thumbnailView.backgroundColor = [UIColor darkGrayColor];
__weak typeof(self) weakSelf = self;
[self.thumbnailView setImageWithURLRequest:[NSURLRequest requestWithURL:wiki.thumbnailURL]
placeholderImage:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
__strong typeof(self) strongSelf = weakSelf;
strongSelf.thumbnailView.image = image;
strongSelf.thumbnailView.backgroundColor = [UIColor whiteColor];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
}];
self.nameLabel.text = wiki.name;
self.linkLabel.text = wiki.URL;
[self.contentView setNeedsLayout];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Selection removes all background colors so re-set it.
[self resetSubviewBackgroundColors];
[self.contentView setNeedsLayout];
}
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
[super setHighlighted:highlighted animated:animated];
// Highlighing removes all background colors so re-set it.
[self resetSubviewBackgroundColors];
[self.contentView setNeedsLayout];
}
- (void)resetSubviewBackgroundColors
{
if (self.thumbnailView.image) {
self.thumbnailView.backgroundColor = [UIColor whiteColor];
} else {
self.thumbnailView.backgroundColor = [UIColor darkGrayColor];
}
}
@end
首先我强烈推荐使用自动布局,它解决了很多尺寸问题和很多计算
但是,如果您没有设置约束,那么您必须计算字符串的长度以适应您想要的标签的宽度
NSString *string = @"this is a very long string to fit into a UILabel";
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 50, 150, 20)];
UIFont *font = [UIFont fontWithName:@"Helvetica Neue" size:15.0];
label.font = font;
label.text = string;
CGSize stringSize = [string sizeWithAttributes:@{NSFontAttributeName : font}];
// check if the string is wider then the label
if (stringSize.width > label.bounds.size.width) {
NSString *newString = [string substringWithRange:NSMakeRange(0, string.length/2)]; <---- i just divided the string into two -----
// check if the newString fits the label
// if not the divide again
label.text = newString;
}else{
label.text = string;
}
[self.view addSubview:label];
就像我在代码中写的那样,我只是将字符串分成两个字符串。如果字符串很长,这可能不起作用,因此您需要不断检查字符串是否符合标签。
您可以使用:
[NSString stringWithFormat:@"%@...", [string substringToIndex:20]];
在字符串末尾添加“...”
在您的 cellForRow: 方法中确保您正在调用:
cell = [tableView dequeueReusableCellWithReuseIdentifier:@"" forIndexPath:(IndexPath *)
将此 returns 称为大小正确的单元格(对于自动布局很重要)
如果这不能解决问题,请在您的手机内执行:
-(void)layoutSubview{
[super layoutSubviews];
[self layoutIfNeeded];
}
您好,您可以在您的自定义 UITableViewCell 中尝试此操作,设置内容视图或标签的框架或使用这些元素的任何元素:-
在声明中:-
GRect usableSpace;
CGFloat usableWidth, usableHeight;
实施中:-
usableSpace = [[UIScreen mainScreen] applicationFrame];
usableWidth = usableSpace.size.width;
usableHeight = usableSpace.size.height;
然后使用这些宽度和高度设置框架
问题隐藏在
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
删除此代码可解决您的问题。
如果您不想 将自动调整掩码转换为约束条件 - 为 cell.contentView.
设置您想要的约束条件我无法加载你的图片,所以我不确定你遇到了什么问题。
我看到这段代码了,有错字吗?
NSArray *constraints =
@[
@"H:|-kPadding-[thumbnailView(kImageSize)]-kPadding-[nameLabel]-kPadding-|",
@"H:[thumbnailView]-kPadding-[linkLabel]-kPadding-|", //this line you forgot the left edge
@"V:|-kPadding-[nameLabel]-0-[linkLabel]",
@"V:|-kPadding-[thumbnailView(kImageSize)]"
];
尽管我的视图看起来不错,但我得到的宽度不正确,底层的 CGRect 是错误的。
当使用 CAShapeLayer
为我的单元格添加边框时,它变得很明显。
我通过在 contentView
layoutIfNeeded()
修复了它
override func layoutSubviews() {
super.layoutSubviews()
contentView.layoutIfNeeded()
}