iOS: UILabel 實現(xiàn) Markdown 代碼框

實現(xiàn)這個我真的花了很長的時間憋肖,效果和簡書的代碼框差不多寿酌,因為簡書也是采用了 Markdown 的代碼框胰苏,就像下面這樣。

特別喜歡孫燕姿的這張專輯醇疼。
克卜勒是以天文學家Johannes Kepler命名的一顆超新星。
是四百年來第一次在白天可以用肉眼看到的星星秧荆。
我不太懂那些宇宙的事埃仪,因為自己的不夠聰明卵蛉,反而對這個世界格外放心傻丝。
太陽每天都會升起來葡缰,潮水每天都會退去,“藏在眾多孤星之中滤愕,還是找得到你”间影。

—— [來自網(wǎng)易云評論] (http://music.163.com/#/song?id=28196001)

要實現(xiàn)這個效果魂贬,相當于要解決下面這幾個問題随橘。

一、UILabel 添加邊框和背景色

這個是最簡單的蒲祈,沒什么好說萝嘁,直接貼代碼,顏色都幫你取好了酸钦。

UILabel *label = [[UILabel alloc] init];
label.layer.borderWidth= 1.0f;
label.layer.cornerRadius=5.0f;
label.layer.borderColor = [[UIColor colorWithRed:204/255.0 green:204/255.0 blue:204/255.0 alpha:1] CGColor];

二咱枉、UILabel 設置文本的行高

NSString *text = @"藏在眾多孤星之中\(zhòng)n還是找得到你";

NSMutableAttributedString* attrString = [[NSMutableAttributedString  alloc] initWithString:text];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];

[style setLineSpacing:lineSpacing];

[attrString addAttribute:NSParagraphStyleAttributeName
                       value:style
                       range:NSMakeRange(0, text.length)];
    
label.attributedText = attrString;

三蚕断、UILabel 支持多行文本和動態(tài)高度

這里需要設置 label 的相關屬性和加上自動布局的水平限制亿乳。

[self.view addSubview:label];

label.numberOfLines = 0;
label.translatesAutoresizingMaskIntoConstraints = NO;

NSArray *labelConstraints = nil;
NSDictionary *views = @{
    @"label": label,
};
labelConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[label]-10-|" options:0 metrics:nil views:views];
[self.view addConstraints:labelConstraints];

注:上面都是偽代碼葛假,只提供一個大概思路聊训。

四魔眨、UILabel 設置 Padding

這個是最難的地方遏暴,我在 Stackoverflow 找到下面兩個解決方案朋凉。

  1. subclass UILabel 并重寫 drawTextInRect 和 intrinsicContentSize 方法
  2. 如果只是添加左右 Padding,可以使用 NSAttributedString

很顯然我們是需要添加4個方向的 Padding墓毒,但當我采用第一種方法時吓揪,發(fā)現(xiàn)如果文本太長所计,出現(xiàn)換行的情況下柠辞,高度的計算會有問題主胧,部分文本顯示不出來叭首。第一種方法只適用于添加上下兩個方向的 Padding踪栋,不能用于添加左右方向的 Padding焙格。

所以這里必須結(jié)合兩種方案,才能順利實現(xiàn)4個方向的 Padding 添加夷都。最后我就直接貼實現(xiàn)的代碼好了。

// CodeBlockLabel.h

#import <UIKit/UIKit.h>

@interface CodeBlockLabel : UILabel

- (void)setBlockText:(NSString*)text;
- (void)setBlockText:(NSString*)text fontSize:(NSInteger)fontSize lineSpacing:(NSInteger)lineSpacing;

@end
// CodeBlockLabel.m

#import "CodeBlockLabel.h"

@implementation CodeBlockLabel

float topInset, leftInset, bottomInset, rightInset;

- (instancetype)init {
    if (self = [super init]) {
        [self setContentEdgeInsets:UIEdgeInsetsMake(20, 0, 20, 0)];
        
        self.numberOfLines = 0;
        self.backgroundColor = [UIColor colorWithRed:247/255.0 green:247/255.0 blue:247/255.0 alpha:1];
        self.translatesAutoresizingMaskIntoConstraints = NO;
        
        self.layer.cornerRadius=5.0f;
        self.layer.borderColor = [[UIColor colorWithRed:204/255.0 green:204/255.0 blue:204/255.0 alpha:1] CGColor];
        self.layer.borderWidth= 1.0f;
    }
    
    return self;
}

- (void)drawTextInRect:(CGRect)uiLabelRect {
    [super drawTextInRect:UIEdgeInsetsInsetRect(uiLabelRect, UIEdgeInsetsMake(topInset,leftInset,bottomInset,rightInset))];
}

- (CGSize)intrinsicContentSize {
    CGSize intrinsicSuperViewContentSize = [super intrinsicContentSize] ;
    intrinsicSuperViewContentSize.height += topInset + bottomInset;
    intrinsicSuperViewContentSize.width += leftInset + rightInset;
    return intrinsicSuperViewContentSize;
}

- (void)setContentEdgeInsets:(UIEdgeInsets)edgeInsets {
    topInset = edgeInsets.top;
    leftInset = edgeInsets.left;
    rightInset = edgeInsets.right;
    bottomInset = edgeInsets.bottom;
    [self invalidateIntrinsicContentSize] ;
}

- (void)setBlockText:(NSString*)text {
    NSInteger lineSpacing;
    NSString *trimmedString = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    
    // 處理一行的情況
    if ([trimmedString rangeOfString:@"\n"].location == NSNotFound) {
        lineSpacing = 0;
    } else {
        lineSpacing = 7;
    }
    
    [self setBlockText:trimmedString fontSize:15 lineSpacing:lineSpacing];
}

- (void)setBlockText:(NSString*)text fontSize:(NSInteger)fontSize lineSpacing:(NSInteger)lineSpacing {
    [self setFont:[UIFont systemFontOfSize:fontSize]];
    
    NSMutableAttributedString* attrString = [[NSMutableAttributedString  alloc] initWithString:text];
    NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
    
    [style setLineSpacing:lineSpacing];
    
    // 是的寫死了,不要在意哈哈哈
    style.firstLineHeadIndent = 20.0;
    style.headIndent = 20.0;
    style.tailIndent = -20.0;
    
    [attrString addAttribute:NSParagraphStyleAttributeName
                       value:style
                       range:NSMakeRange(0, text.length)];
    
    self.attributedText = attrString;
}

@end
// ViewController.m

#import "ViewController.h"
#import "CodeBlockLabel.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 添加 UIScrollView
    UIScrollView *scrollView = [[UIScrollView alloc] init];
    scrollView.translatesAutoresizingMaskIntoConstraints = NO;
    
    [self.view addSubview:scrollView];
    
    // 這里添加更多的文本,就能看到滾動條了
    NSString *text = @"藏在眾多孤星之中\(zhòng)n還是找得到你";
    CodeBlockLabel *codeBlock = [[CodeBlockLabel alloc] init];
    [codeBlock setBlockText:text];
    
    // 這個 spongeBob 去掉會有 bug
    UILabel *spongeBob = [[UILabel alloc] init];
    spongeBob.numberOfLines = 0;
    spongeBob.translatesAutoresizingMaskIntoConstraints = NO;
    
    [scrollView addSubview:spongeBob];
    [scrollView addSubview:codeBlock];
    
    NSDictionary *views = @{
                            @"scrollView": scrollView,
                            @"codeBlock": codeBlock,
                            @"spongeBob": spongeBob,
                            };
    
    // 添加約束
    NSArray *constraints = nil;
    
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[codeBlock]-10-|" options:0 metrics:nil views:views];
    
    [scrollView addConstraints:constraints];
    
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[spongeBob(scrollView)]|" options:0 metrics:nil views:views];
    [scrollView addConstraints:constraints];
    
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-15-[codeBlock]-15-[spongeBob]-5-|" options:0 metrics:nil views:views];
    
    [scrollView addConstraints:constraints];
    
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics:nil views:views];
    
    [self.view addConstraints:constraints];
    
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-30-[scrollView]-44-|" options:0 metrics:nil views:views];
    
    [self.view addConstraints:constraints];
}

@end

這就是全部了嚷掠,上面還添加了一個 UIScrollView贯城,這樣就算文本太長,你也能滑到下面去看了霹娄,你的更好的辦法嗎能犯?有的話一定要告訴我!

參考文章

UILabel + UIScrollView + Auto Layout

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末犬耻,一起剝皮案震驚了整個濱河市踩晶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌枕磁,老刑警劉巖渡蜻,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡茸苇,警方通過查閱死者的電腦和手機排苍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來学密,“玉大人淘衙,你說我怎么就攤上這事∧迥海” “怎么了彤守?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長西壮。 經(jīng)常有香客問我遗增,道長,這世上最難降的妖魔是什么款青? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任做修,我火速辦了婚禮,結(jié)果婚禮上抡草,老公的妹妹穿的比我還像新娘饰及。我一直安慰自己,他們只是感情好康震,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布燎含。 她就那樣靜靜地躺著,像睡著了一般腿短。 火紅的嫁衣襯著肌膚如雪屏箍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天橘忱,我揣著相機與錄音赴魁,去河邊找鬼。 笑死钝诚,一個胖子當著我的面吹牛颖御,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凝颇,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼潘拱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拧略?” 一聲冷哼從身側(cè)響起芦岂,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辑鲤,沒想到半個月后盔腔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年弛随,在試婚紗的時候發(fā)現(xiàn)自己被綠了瓢喉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡舀透,死狀恐怖栓票,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情愕够,我是刑警寧澤走贪,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站惑芭,受9級特大地震影響坠狡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜遂跟,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一逃沿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧幻锁,春花似錦凯亮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至岭接,卻和暖如春富拗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鸣戴。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工媒峡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人葵擎。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像半哟,于是被迫代替她去往敵國和親酬滤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案寓涨? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標簽默認的外補...
    _Yfling閱讀 13,759評論 1 92
  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫盯串、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,120評論 4 61
  • 拜縣被譽為泰北小瑞士戒良,像童話鎮(zhèn)一般安靜悠閑体捏。如果你是小清新,那一定不要錯過拜縣,粉色房子几缭,黃色小屋河泳,大樹秋...
    lapuil閱讀 886評論 3 3
  • 中國第一家心理學網(wǎng)校誕生了! 人人學得起年栓,人人學得會拆挥,人人學得方便。 歡迎朋友們轉(zhuǎn)發(fā)支持某抓,讓心理學走進社會大眾纸兔,為...
    佳芮閱讀 403評論 1 0
  • 當你留在我身邊的印記一點一點地消失备禀,你是不是也將在我的心里消失了痕跡洲拇? 明媚的春天帶給我活力,也帶來了你痹届,如今凜冽...
    瘋狂素閱讀 519評論 0 0