【IOS】將字體大小不同的文字底部對齊


從WP轉IOS了,還是放不下......

 

在項目中,要實現如圖多個不同大小的文字   底部對齊的效果   像下面這樣:

(想要的效果)

以為用三個UIFont不同的UILabel  之后讓他們底部對齊就可以了,但是效果是下面這樣的:

 (不想要的效果)

底部完全不對齊呀,為什么"1314"比兩邊高出了那么多呀!!!!強迫症不能忍呀!!!

--------------------------------------------------------------------------------

對比:

1.在Windows Phone中 控件是相對布局

Windows Phone里面TextBlock需要設置一個固定的 寬度  和 高度 (至少我是這樣做的)

TextBlock不但可以將文字設置為水平居中、偏左、偏右,還能通過屬性 

text.VerticalContentAlignment=Top/Center/Bottom將文字置於頂部/居中/底部。(WP中發現也只能水平方向的)

2.在IOS中 控件是絕對布局: 對於一個控件  需要設置它的frame(包括起始位置、高和寬)

可以通過以下方法直接獲取一個字符串的自適應的高度和寬度:(這點覺得比WindowsPhone好)

CGSize labelSize = [@"1314" sizeWithAttributes:@{NSFontAttributeName:kLabelFont}];

而原生的UIlabel只能設置textAlignment文字的水平偏移屬性,而無法直接更改豎直方向的偏移。

 

WindowsPhone中要實現上面的效果,只需將三個TextBlock置底,TextBlock內容居下,即可對齊。

(這一點我突然的不確定了,好像很多時候我都是直接設置margin來手動對齊的,有空回WindowsPhone看看再修改。)

[2016.5.25修改] WP中TextBlock也沒有VerticalContentAlignment屬性...

 

彎路:

所以在IOS處理這個問題的時候,我想着既然三個控件的底部都是對齊了的,只是高度不一樣,能否仿照着WindowsPhone那樣,

將較高UILabel的內容("1314")豎直偏移到最底下呢?

經過查閱  UILabel找到了這些:  

不能直接調用  只能通過繼承來重寫

// override points. can adjust rect before calling super. (在調用父類前  可以調整文本內容的位置TextRect)

// label has default content mode of UIViewContentModeRedraw

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines;  //重寫來重繪文字區域

- (void)drawTextInRect:(CGRect)rect;  //重寫來重繪文本  重寫時調用super可以按默認圖形屬性繪制

所以為了改變text的位置, 我們只需要改變textRectForBounds的返回值rect,並且根據這個rect重繪文本就可以了

1、關於contentMode,該模式為視圖提供了多種模式用以適用框架矩形。如果對除UIVewContentModeRedraw之外的模式(如UIViewContentModeScaleToFill)都不滿足需求,或者說有特定需要自定義繪制視圖,可以設置為此值。那么將在視圖適應框架矩形變化時缺省自動調用setNeedsDispllay或setNeedsDisplayInRect:,從而重繪視圖。
2、而向視圖發送setNeedsDisplay(或setNeedsDisplayInRect:)消息時,無論此時contentMode為何種模式,都將強制調用drawRect:  

主要代碼:(這個代碼網上一大把,自己找去) 

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{          //方法里的形參bounds指的是UILabel的bounds 
    CGRect rc = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];  //text的bounds switch (_verticalAlignment) {
        case VerticalAlignmentTop:
            rc.origin.y = bounds.origin.y;  
            break;
        case VerticalAlignmentBottom:
            rc.origin.y = bounds.origin.y + bounds.size.height - rc.size.height;
            break;
        case VerticalAlignmentMiddle:
        default:
            rc.origin.y = bounds.origin.y + (bounds.size.height - rc.size.height) / 2;
            break;
    } 
    return rc;
}
- (void)drawTextInRect:(CGRect)rect
{
    CGRect rc = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines];
    [super drawTextInRect:rc];
}

然而發現:對於自適應寬高(CGSize)的Label, 設置了verticalAlignment屬性基本上沒多大區別

origin.x  origin.y 均為零   並且SIZE區別幾乎沒有  所有也不會有多大區別。

這里我進行了一個對比:對於字符串@"1314",設置不同的UIFont 觀察UILabel和內部的textRect的大小差別

UIFont                                 1                                         50                                          100

rc(text)                1.000000,2.333333        105.666667,61.000000          208.666667,120.666667

bounds(label)      1.000000,2.193359        105.541992,60.667969          208.349609,120.335938

相差                                    0,0.139974             0.124675,0.332031                0.317058, 0.330729

rc居然還要比bounds大那么一點點,我認為為了文字不被截取,文字大小還是比其文字邊框還要小的,

並且針對不同大小的UIFont或字體類型,這種小的程度還是不一樣的。

所以就算設置verticalAlignment屬性也發現不了什么區別。

如果只將文字大小設置更大,導致rc比bounds大,那么文字部分就可能會被截取;

如果只增加UILabel的大小,導致rc比bounds小,那么就會看到除了文字外多余的空白區域;

對於后兩者,設置verticalAlignment屬性,就能夠明顯的看到上下偏移了。

所以這種方案對於實現所需效果無效。

 

終點: 

找呀找呀  又找到了另外一種方法,可以通過attributedText屬性讓UILabel顯示富文本

實現一個字符串中包含不同顏色、字號等。

我封裝了一個方法:

// 獲取帶有不同樣式的文字內容
//stringArray 字符串數組
//attributeAttay 樣式數組
- (NSAttributedString *)attributedText:(NSArray*)stringArray attributeAttay:(NSArray *)attributeAttay{
  // 定義要顯示的文字內容
    NSString * string = [stringArray componentsJoinedByString:@""];  //拼接傳入的字符串數組   // 通過要顯示的文字內容來創建一個帶屬性樣式的字符串對象
    NSMutableAttributedString * result = [[NSMutableAttributedString alloc] initWithString:string];
        for(NSInteger i = 0; i < stringArray.count; i++){
     // 將某一范圍內的字符串設置樣式 [result setAttributes:attributeAttay[i] range:[
string rangeOfString:stringArray[i]]]; } // 返回已經設置好了的帶有樣式的文字 return [[NSAttributedString alloc] initWithAttributedString:result]; }

 以及其使用

   NSDictionary *attributesExtra = @{NSFontAttributeName:kLabelFont,//字號12
                                              NSForegroundColorAttributeName: [UIColor orangeColor]};
  NSDictionary *attributesPrice = @{NSFontAttributeName:kPriceFont,//字號18
                                               NSForegroundColorAttributeName: [UIColor orangeColor]};
  NSAttributedString *attributedString = [self attributedText:@[@"", @"1314", @""]
                                                 attributeAttay:@[attributesExtra,attributesPrice,attributesExtra]];
   UILabel *price = [[UILabel alloc]init]; 
  price.attributedText
= attributedString;    CGRect rect = [attributedString boundingRectWithSize:CGSizeMake(self.width / 2, 100) options:NSStringDrawingUsesLineFragme ntOrigin context:nil];  //此方法獲取到的是自適應的Rect,而不是CGSize 最大Size值為CGSizeMake(self.width / 2, 100)
price.frame = CGRectMake(0,0,rect.size.width, rect.size.height);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM