如何使用UILabel和NSAttributedString垂直对齐文本

时间:2013-12-09 06:52:59

标签: ios objective-c uilabel nsattributedstring

我正在使用UILabel和NSAttributedString为IOS7中的标签文本设置行间距。但是当我使用它时,文本似乎没有在Label上集中对齐。这是我的代码,用于将文本(属性)设置为标签。

-(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]];

    }

}

以下是一些截图,BTW将UILabel子类化并覆盖setter以实现行间距。

enter image description here

6 个答案:

答案 0 :(得分:2)

其实我解决了它.... :) :)。问题出在我使用的自定义字体上。

采取了一些R& D但现在似乎正在运作

刚刚为label创建了一个子类并覆盖了一些默认方法。

- (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];

}

答案 1 :(得分:1)

可能你不能用简单的方式用UILabel来做。

如果可能,您可以使用UITextField垂直对齐内容。

否则使用NSAttributedString和标签文本,您可以调整Line-Height(不确定)。

答案 2 :(得分:0)

您可以使用其他一些解决方法 - 自定义UILabel

NWLabel.m

#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];
}

NWLabel.h

#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

答案 3 :(得分:0)

如果自定义标签中只显示一行文字,请不要设置行间距。

答案 4 :(得分:0)

可以通过属性字符串完成:

ObjC:

// 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)

答案 5 :(得分:0)

将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)
    }

}