eme*_*gro 18 nsattributedstring ios autolayout
对齐两个标签时遇到问题.两个例子来说明问题
[leftLabel setText:@"03"];
[rightLabel setText:@"Description3"];
Run Code Online (Sandbox Code Playgroud)

[leftLabel setText:@"03"];
[rightLabel setAttributedText:[[NSAttributedString alloc] initWithString:@"Description3"]];
Run Code Online (Sandbox Code Playgroud)

在这两个示例中,布局约束都是这样
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-bigMargin-[leftLabel]-bigMargin-[rightLabel]-bigMargin-|"
options:NSLayoutFormatAlignAllBaseline
metrics:metrics
views:views];
Run Code Online (Sandbox Code Playgroud)
问题是正确的标签,当文本是属性标签时,它被绘制在下面一点,如图中所示,并且对齐结果错误.
为什么?我能用这UIlabel两种方法解决这个问题吗?
编辑:
我在GitHub上创建了一个项目,并对此进行了测试.这里的问题是即使没有NSAttributdString我也有问题!查看带有数字的标签,与说明和金额没有正确对齐.

我在这里粘贴单元格的代码,但必须在项目中看到整个场景.
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
UIView *contentView = [self contentView];
[contentView setBackgroundColor:[UIColor clearColor]];
dayLabel_ = [[UILabel alloc] initWithFrame:CGRectZero];
[dayLabel_ setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:dayLabel_];
monthLabel_ = [[UILabel alloc] initWithFrame:CGRectZero];
[monthLabel_ setTranslatesAutoresizingMaskIntoConstraints:NO];
[monthLabel_ setFont:[UIFont boldSystemFontOfSize:13.0f]];
[contentView addSubview:monthLabel_];
descriptionLabel_ = [[UILabel alloc] initWithFrame:CGRectZero];
[descriptionLabel_ setTranslatesAutoresizingMaskIntoConstraints:NO];
[descriptionLabel_ setFont:[UIFont systemFontOfSize:20.0f]];
[contentView addSubview:descriptionLabel_];
conceptLabel_ = [[UILabel alloc] initWithFrame:CGRectZero];
[conceptLabel_ setTranslatesAutoresizingMaskIntoConstraints:NO];
[conceptLabel_ setLineBreakMode:NSLineBreakByTruncatingTail];
[conceptLabel_ setFont:[UIFont systemFontOfSize:12.0f]];
[contentView addSubview:conceptLabel_];
amountLabel_ = [[UILabel alloc] initWithFrame:CGRectZero];
[amountLabel_ setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:amountLabel_];
// Constraints
NSDictionary *views = NSDictionaryOfVariableBindings(contentView, dayLabel_, monthLabel_, descriptionLabel_, conceptLabel_, amountLabel_);
NSDictionary *metrics = @{ @"bigMargin" : @12 };
[descriptionLabel_ setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
[conceptLabel_ setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-bigMargin-[dayLabel_][monthLabel_]"
options:NSLayoutFormatAlignAllLeading
metrics:metrics
views:views]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-bigMargin-[descriptionLabel_][conceptLabel_]"
options:NSLayoutFormatAlignAllLeading
metrics:metrics
views:views]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-bigMargin-[dayLabel_]-bigMargin-[descriptionLabel_]-(>=bigMargin)-[amountLabel_]-bigMargin-|"
options:NSLayoutFormatAlignAllBaseline
metrics:metrics
views:views]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-bigMargin-[monthLabel_]-bigMargin-[conceptLabel_]-bigMargin-|"
options:NSLayoutFormatAlignAllBaseline
metrics:metrics
views:views]];
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
Lom*_*baX 12
好的,最后一个例子问题更清楚了.您必须知道的第一件事:默认情况下,UILabel内的文本垂直对齐在标签的中心.
AFAIK您无法更改垂直对齐以使文本与基线对齐.
现在,看看附图.

在第一个示例中,我留下了示例项目的所有默认值.您可以看到日期标签和描述标签完全对齐:Autolayout对齐两个标签的边界(仅仅是视图,其中包含其他私有子视图).
但是,字体大小不同.对于日期标签是默认系统大小(17),对于您指定的描述20.
现在,如果两个标签对齐,则文本在标签中垂直居中,并且字体大小不同,显然是基线两个文本不会对齐.
在第二个示例中,我使用相同的字体大小,您可以看到对齐是正确的.
那么,可能的解决方案有两个:
最后一点可以通过一些计算来完成,你可以在这里找到一些例子:链接
编辑
好的,我发布了一个例子.第一件事:似乎在发布的链接上有一个错误.ascender + descender + 1等于lineHeight,而不是pointSize.我让作者纠正它.
因此,您可以继承UILabel,覆盖viewForBaselineLayout并执行类似的操作.您必须添加一个baselineView实例变量并将其添加为子视图UILabel,因为AutoLayout希望视图对齐为标签的子视图.
// please note: you may need some error checking
- (UIView *)viewForBaselineLayout
{
// create the view if not exists, start with rect zero
if (!self.baselineView)
{
self.baselineView = [[UIView alloc] initWithFrame:CGRectZero];
self.baselineView.backgroundColor = [UIColor clearColor];
[self addSubview:self.baselineView];
}
// this is the total height of the label
float viewHeight = self.bounds.size.height;
// calculate the space that is above the text
float spaceAboveText = (viewHeight - self.font.lineHeight) / 2;
// this is the height of the view we want to align to
float baselineViewHeight = spaceAboveText + self.font.ascender + 1;
// if you have 26.6545 (for example), the view takes 26.0 for the height. This is not good, so we have to round the number correctly (to the upper value if >.5 and to the lower if <.5)
int integerBaseline = (int)(baselineViewHeight + 0.5f);
// update the frame of the view
self.baselineView.frame = CGRectMake(0, 0, self.bounds.size.width, (float)integerBaseline);
return self.baselineView;
}
Run Code Online (Sandbox Code Playgroud)
通过这种方法,您必须处理以下几点:
viewForBaselineLayout,并且其高度在以后不得更改.因此,在布局过程发生之前,您必须使标签符合其内容大小.我附上你的项目的一些更新和颜色用于调试,只有dayLabel和descriptionLabel(我删除了其他)和更新的约束.
| 归档时间: |
|
| 查看次数: |
8567 次 |
| 最近记录: |