1. 程式人生 > >使用NSMutableAttributedString新增下劃線、刪除線、陰影、填充、不同字型顏色等

使用NSMutableAttributedString新增下劃線、刪除線、陰影、填充、不同字型顏色等

在iOS開發中,有時會遇到需要新增下劃線,或者設定字串中某幾個字的顏色的情況,最常見的栗子就是註冊頁面,如圖所示:


幾乎所有註冊頁面中都會出現這麼一句話 “點選下一步表示您已同意《使用者服務協議》”,而且可以看到,“《使用者服務協議》”幾個字是橙色的,並且它們下面還有下劃線。這是怎麼實現的呢?

有的同學可能會說:“不同顏色就設定兩個label,讓左邊的label顯示前半句並設定為黑色,讓右邊的label顯示後半句並設定為橙色就行了。” 這樣也許是一個辦法,但是感覺有些麻煩,而且如果有很多種顏色呢?難道要設定一大堆label嗎。。。

NSMutableAttributedString 就可以完美的解決這些問題。我們先說一下和 attributes 有關的四個方法:

為某一範圍內文字設定多個屬性

- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range;

為某一範圍內文字新增某個屬性

- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;

為某一範圍內文字新增多個屬性

- (void)addAttributes:(NSDictionary *)attrs range:(NSRange)range;

移除某一範圍內的某個屬性

- (void)removeAttribute:(NSString

 *)name range:(NSRange)range;

我們來舉個栗子吧:

- (void)viewDidLoad {
    [super viewDidLoad];

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, ScreenWidth, 40)];
    label.font = [UIFont systemFontOfSize:18]; // 字型大小
    label.textAlignment = NSTextAlignmentCenter; // 文字對齊方式
    
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:
        @"點選下一步表示您已同意《使用者服務協議》"];
    [str addAttribute:NSForegroundColorAttributeName value:
        [UIColor colorWithRed:100/255.0 green:100/255.0 blue:100/255.0 alpha:1] range:NSMakeRange(0,11)];
    [str addAttribute:NSForegroundColorAttributeName value:
        [UIColor colorWithRed:255/255.0 green:110/255.0 blue:17/255.0 alpha:1] range:NSMakeRange(11,8)];

    label.attributedText = str;
    [self.view addSubview:label];
}

我們建立一個 NSMutableAttributedString 的物件 str,然後為它新增一個屬性,這個屬性的名字叫做 NSForegroundColorAttributeName,就是文字的顏色,它的值是 UIColor 型別的,預設是黑色,我們給它自定義一個顏色。然後我們來設定它的範圍,NSMakeRange(0, 11) 的意思就是說,從第0個字開始,一共11個字。這個範圍其實就是 “點選下一步表示您已同意” 這11個字。(事實上,第一幅圖中的這11個字並不是黑色,但是和黑色比較接近,這不重要~)

然後我們又給這個字串添加了一個屬性,這個屬性還是 NSForegroundColorAttributedName,但是顏色是橙色,並且範圍是從第11(別忘了編號從0開始)個字開始,一共8個字。這個範圍其實就是 “《使用者服務協議》“(書名號也算)

現在我們執行程式來看看效果:



文字顏色已經搞定了,接下來我們來加下劃線。我們在原來程式碼的基礎上再加一句話:

- (void)viewDidLoad {
    [super viewDidLoad];

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, ScreenWidth, 40)];
    label.font = [UIFont systemFontOfSize:18]; // 字型大小
    label.textAlignment = NSTextAlignmentCenter; // 文字對齊方式
    
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:
        @"點選下一步表示您已同意《使用者服務協議》"];
    [str addAttribute:NSForegroundColorAttributeName value:
        [UIColor colorWithRed:100/255.0 green:100/255.0 blue:100/255.0 alpha:1] range:NSMakeRange(0,11)];
    [str addAttribute:NSForegroundColorAttributeName value:
        [UIColor colorWithRed:255/255.0 green:110/255.0 blue:17/255.0 alpha:1] range:NSMakeRange(11,8)];
    [str addAttribute:NSUnderlineStyleAttributeName value:
        [NSNumber numberWithInteger:NSUnderlineStyleSingle] range:NSMakeRange(12, 6)]; // 下劃線
    
    label.attributedText = str;
    [self.view addSubview:label];
}
這句話的意思就是說,給 str 新增一個屬性,這個屬性的名字是 NSUnderlineStyleAttributeName,也就是下劃線的型別。它的值是 NSInteger 型別的,預設是0,也就是沒有下劃線。範圍是從第12個字開始,一共6個字。也就是 “使用者服務條款”。

這裡要注意。我們再來看一遍新增屬性的方法原型:

- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;

注意,引數 value 是 id 型別的。看到這句話,你知道我想說什麼了嗎?

id 是 Objective-C 物件。而 NSInteger 是基本資料型別,不是物件。所以必須寫成 [NSNumber numberWithInteger:123] 的形式。

在設定這個值的時候,我不知道具體應該設為幾,我嘗試了好多數,但是發現竟然有的不對。後來百度了一下,才知道原來它的值有一個列舉:

typedef NS_ENUM(NSInteger, NSUnderlineStyle) {
    NSUnderlineStyleNone                                    = 0x00,
    NSUnderlineStyleSingle                                  = 0x01,
    NSUnderlineStyleThick NS_ENUM_AVAILABLE(10_0, 7_0)      = 0x02,
    NSUnderlineStyleDouble NS_ENUM_AVAILABLE(10_0, 7_0)     = 0x09,

    NSUnderlinePatternSolid NS_ENUM_AVAILABLE(10_0, 7_0)      = 0x0000,
    NSUnderlinePatternDot NS_ENUM_AVAILABLE(10_0, 7_0)        = 0x0100,
    NSUnderlinePatternDash NS_ENUM_AVAILABLE(10_0, 7_0)       = 0x0200,
    NSUnderlinePatternDashDot NS_ENUM_AVAILABLE(10_0, 7_0)    = 0x0300,
    NSUnderlinePatternDashDotDot NS_ENUM_AVAILABLE(10_0, 7_0) = 0x0400,

    NSUnderlineByWord NS_ENUM_AVAILABLE(10_0, 7_0)            = 0x8000
} NS_ENUM_AVAILABLE(10_0, 6_0);

實際上,設定刪除線 NSStrikethroughColorAttributeName 的時候,值也是這個列舉。

// NSUnderlineStyleNone 不設定下劃線/刪除線

// NSUnderlineStyleSingle 設定下劃線/刪除線為細的單線

// NSUnderlineStyleThick 設定下劃線/刪除線為粗的單線

// NSUnderlineStyleDouble 設定下劃線/刪除線為細的雙線

// NSUnderlinePatternSolid 設定下劃線/刪除線樣式為連續的實線

// NSUnderlinePatternDot 設定下劃線/刪除線樣式為點,也就是虛線,比如這樣:------

// NSUnderlinePatterDash 設定下劃線/刪除線樣式為破折號,比如這樣:—— —— ——

// NSUnderlinePatternDashDot 設定下劃線/刪除線樣式為連續的破折號和點,比如這樣:——-——-——-

// NSUnderlinePatternDashDotDot 設定下劃線/刪除線樣式為連續的破折號、點、點,比如:——--——--——--

// NSUnderlineByWord 在有空格的地方不設定下劃線/刪除線

我為什麼要把它們分成三段來說呢?因為它們屬於三種,設定的時候不一定只有一種,可以同時設定其中的某兩種或三種都設定。比如這樣:

[str addAttribute:NSUnderlineStyleAttributeName value:
        [NSNumber numberWithInteger:NSUnderlineStyleDouble | NSUnderlinePatternDot] range:NSMakeRange(12, 6)];
這行程式碼就是給 “使用者服務協議“ 加一個下劃線,但是這回的下劃線是兩行的,並且是虛線。(注意:同時滿足多項,是用 ‘|’ 運算子連線)

實際上下劃線的顏色也是可以設定的。如果沒有設定的話,預設和文字顏色一樣,也就是橙色。我們來嘗試把下劃線換成藍色看看:

- (void)viewDidLoad {
    [super viewDidLoad];

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, ScreenWidth, 40)];
    label.font = [UIFont systemFontOfSize:18]; // 字型大小
    label.textAlignment = NSTextAlignmentCenter; // 文字對齊方式
    
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:
        @"點選下一步表示您已同意《使用者服務協議》"];
    [str addAttribute:NSForegroundColorAttributeName value:
        [UIColor colorWithRed:100/255.0 green:100/255.0 blue:100/255.0 alpha:1] range:NSMakeRange(0,11)];
    [str addAttribute:NSForegroundColorAttributeName value:
        [UIColor colorWithRed:255/255.0 green:110/255.0 blue:17/255.0 alpha:1] range:NSMakeRange(11,8)];
    [str addAttribute:NSUnderlineStyleAttributeName value:
        [NSNumber numberWithInteger:NSUnderlineStyleSingle] range:NSMakeRange(12, 6)]; // 下劃線型別
    [str addAttribute:NSUnderlineColorAttributeName value:
        [UIColor blueColor] range:NSMakeRange(12, 6)]; // 下劃線顏色
    
    label.attributedText = str;
    [self.view addSubview:label];
}
執行一下,結果如下圖所示:




我們再舉個栗子,新增一個加粗版的刪除線,設定刪除線的顏色為黑色(如果不設定顏色,也預設和文字顏色一樣)

- (void)viewDidLoad {
    [super viewDidLoad];

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, ScreenWidth, 40)];
    label.font = [UIFont systemFontOfSize:18]; // 字型大小
    label.textAlignment = NSTextAlignmentCenter; // 文字對齊方式
    
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:
        @"點選下一步表示您已同意《使用者服務協議》"];
    [str addAttribute:NSForegroundColorAttributeName value:
        [UIColor colorWithRed:100/255.0 green:100/255.0 blue:100/255.0 alpha:1] range:NSMakeRange(0,11)];
    [str addAttribute:NSForegroundColorAttributeName value:
        [UIColor colorWithRed:255/255.0 green:110/255.0 blue:17/255.0 alpha:1] range:NSMakeRange(11,8)];
    [str addAttribute:NSUnderlineStyleAttributeName value:
        [NSNumber numberWithInteger:NSUnderlineStyleSingle] range:NSMakeRange(12, 6)]; // 下劃線型別
    [str addAttribute:NSUnderlineColorAttributeName value:
        [UIColor blueColor] range:NSMakeRange(12, 6)]; // 下劃線顏色
    [str addAttribute:NSStrikethroughStyleAttributeName value:
        [NSNumber numberWithInteger:NSUnderlineStyleThick] range:NSMakeRange(12, 6)]; // 刪除線型別
    [str addAttribute:NSStrikethroughColorAttributeName value:
        [UIColor blackColor] range:NSMakeRange(12, 6)]; // 刪除線顏色
    
    label.attributedText = str;
    [self.view addSubview:label];
}

然後執行一下來看看效果:


我們再舉最後一個栗子栗子說:能不能別舉我了~),設定填充:

- (void)viewDidLoad {
    [super viewDidLoad];

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, ScreenWidth, 40)];
    label.font = [UIFont systemFontOfSize:18]; // 字型大小
    label.textAlignment = NSTextAlignmentCenter; // 文字對齊方式
    
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:
        @"點選下一步表示您已同意《使用者服務協議》"];
    [str addAttribute:NSForegroundColorAttributeName value:
        [UIColor colorWithRed:100/255.0 green:100/255.0 blue:100/255.0 alpha:1] range:NSMakeRange(0,11)];
    [str addAttribute:NSForegroundColorAttributeName value:
        [UIColor colorWithRed:255/255.0 green:110/255.0 blue:17/255.0 alpha:1] range:NSMakeRange(11,8)];
    [str addAttribute:NSStrokeWidthAttributeName value:
        [NSNumber numberWithFloat:3.0] range:NSMakeRange(11, 8)]; // 設定填充
    
    
    label.attributedText = str;
    [self.view addSubview:label];
}

然後執行一下來看看效果:


同理,填充也可以設定顏色,如果不設定的話,預設和文字顏色一樣。

NSMutableAttributedString 還能設定很多其它屬性,比如段落格式、陰影等等(還有很多哦)

想要完整的學習它請參考蘋果的官方文件:傳送門

最後想說一下它的缺點,也許有的同學已經發現了,下劃線離文字太近了!不能設定下劃線和文字的距離,這是它美中不足的地方。