[英]How to Vertically Align Text Using UILabel and NSAttributedString
我正在使用 UILabel 和 NSAttributedString 为 IOS7 中的标签文本设置行距。 但是当我使用它时,文本似乎没有在标签上居中对齐。 这是我为标签设置文本(归因)的代码。
-(void)setText:(NSString *)text
{
[super setText:text];
if(text)
[self setLineSpace];
}
-(void)setLineSpace
{
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7)
{
NSMutableAttributedString *string=[[NSMutableAttributedString alloc]initWithString:self.text];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.alignment=NSTextAlignmentJustified;
[paragraphStyle setLineSpacing:4] ;
// paragraphStyle.minimumLineHeight =0;
// paragraphStyle.maximumLineHeight=7;
// CTTextAlignment alignment = kCTCenterTextAlignment;
[string addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, string.length)];
self.text=nil;
self.attributedText=string;
[self setBackgroundColor:[UIColor redColor]];
}
}
这是一些截图,顺便说一句,我将 UILabel 子类化为并覆盖 setter 以实现行间距。
实际上我解决了它....:) :) 问题出在我使用的自定义字体上。
进行了一些研发,但现在似乎奏效了
刚刚为标签创建了一个子类并覆盖了一些默认方法。
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
CGRect textRect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
if(([self.font.fontName isEqualToString:@"Gotham"]||[self.font.fontName isEqualToString:@"Gotham-Bold"]||[self.font.fontName isEqualToString:@"Gotham-Medium"])&&((int)[[[UIDevice currentDevice] systemVersion] floatValue])==6&&self.verticalAlignment==AlignMiddle)
{
textRect.origin.y = bounds.origin.y + (bounds.size.height - textRect.size.height) / 2.0;
return [self addToRect:textRect x:0 y:2];
}
return [self addToRect:textRect x:0 y:0.5];
}
-(void)drawTextInRect:(CGRect)requestedRect
{
if(((int)[[[UIDevice currentDevice] systemVersion] floatValue])>=7)
[super drawTextInRect:[self addToRect:requestedRect x:0 y:0.5]];
else
{
CGRect actualRect = [self textRectForBounds:requestedRect limitedToNumberOfLines:self.numberOfLines];
[super drawTextInRect:actualRect];
}
}
-(CGRect)addToRect:(CGRect)rect x:(CGFloat)dx y:(CGFloat) dy
{
rect=CGRectMake(rect.origin.x+dx, rect.origin.y+dy, rect.size.width, rect.size.height);
return rect;
}
-(CGRect)makeRect:(CGRect)rect x:(CGFloat)dx y:(CGFloat) dy
{
rect=CGRectMake(dx,dy, rect.size.width+dx, rect.size.height+dy);
return rect;
}
-(CGRect)makeRects:(CGRect)rect x:(CGFloat)dx y:(CGFloat) dy
{
rect=CGRectMake(rect.origin.x,rect.origin.y, rect.size.width+dx, rect.size.height+dy);
return rect;
}
-(void)truncateToFit
{
if([[[UIDevice currentDevice] systemVersion] floatValue] < 7)
{
[self sizeToFit];
CGRect frame=self.frame;
if(frame.size.height<self.frame.size.height)
self.frame=[self makeRects:frame x:0 y:0.5];
}
else
{
self.frame=[self makeRects:self.frame x:0 y:0.5];
[self sizeToFit];
}
}
-(void)truncatesToFit
{
self.lineBreakMode=NSLineBreakByTruncatingTail;
self.numberOfLines=2;
[self sizeToFit];
self.frame=[self makeRects:self.frame x:0 y:0.5];
}
-(void)truncatesToFit:(NSInteger )linesCount
{
self.numberOfLines=linesCount;
[self sizeToFit];
self.frame=[self makeRects:self.frame x:0 y:0.5];
}
可能您无法以简单的方式使用 UILabel 做到这一点。
如果可能,您可以使用 UITextField 垂直对齐内容。
否则使用 NSAttributedString 和标签文本,您可以调整 Line-Height (不确定)。
可以通过属性字符串完成:
对象:
// shift the text down 10 pixels
[string addAttribute:NSBaselineOffsetAttributeName value:@(-10) range:NSMakeRange(0, string.length)];
斯威夫特:
// shift the text up 10 pixels
string.addAttributes([NSAttributedStringKey.baselineOffset:10], range: range)
您可以使用其他一些解决方法 - 自定义 UILabel
标签文件
#import "NWLabel.h"
@implementation NWLabel
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (!self) return nil;
_verticalAlignment = VerticalAlignmentTop;
return self;
}
-(VerticalAlignment) verticalAlignment
{
return _verticalAlignment;
}
-(void) setVerticalAlignment:(VerticalAlignment)value
{
_verticalAlignment = value;
[self setNeedsDisplay];
}
// align text block according to vertical alignment settings
-(CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
CGRect rect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
CGRect result;
switch (_verticalAlignment)
{
case VerticalAlignmentTop:
result = CGRectMake(bounds.origin.x, bounds.origin.y, rect.size.width, rect.size.height);
break;
case VerticalAlignmentMiddle:
result = CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height) / 2, rect.size.width, rect.size.height);
break;
case VerticalAlignmentBottom:
result = CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height), rect.size.width, rect.size.height);
break;
default:
result = bounds;
break;
}
return result;
}
-(void)drawTextInRect:(CGRect)rect
{
CGRect r = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines];
[super drawTextInRect:r];
}
标签文件
#import <UIKit/UIKit.h>
typedef enum
{
VerticalAlignmentTop = 0, // default
VerticalAlignmentMiddle,
VerticalAlignmentBottom,
} VerticalAlignment;
@interface NWLabel : UILabel
{
@private VerticalAlignment _verticalAlignment;
}
@property (nonatomic, readwrite, assign) VerticalAlignment verticalAlignment;
@end
当您的自定义标签中只显示一行文本时,请不要设置行距。
将 Ivan M 在https://discussions.apple.com/thread/1759957?tstart=0 中提出的解决方案转换为 Swift 5
class VerticallyAlignedUILabel: UILabel {
enum VerticalAlignment {
case top
case bottom
case middle
}
public var verticalAlignment:VerticalAlignment {
didSet {
self.setNeedsDisplay()
}
}
init(frame: CGRect, verticalAlignment:VerticalAlignment = .middle) {
self.verticalAlignment = verticalAlignment
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
var textRect:CGRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
switch self.verticalAlignment {
case .top:
textRect.origin.y = bounds.origin.y
case .bottom:
textRect.origin.y = bounds.origin.y + bounds.size.height - textRect.size.height
case .middle:
textRect.origin.y = bounds.origin.y + (bounds.size.height - textRect.size.height) / 2.0
}
return textRect
}
override func drawText(in rect: CGRect) {
let actualRect = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
super.drawText(in: actualRect)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.