iOS設(shè)置textView行間距(動態(tài)+靜態(tài)+各種bug的代碼)

前言

好久沒有在簡書上面發(fā)表文章了,至今文集中都還有好幾個未完成的文章,今天決定先發(fā)表一篇簡單好寫的文章,也許我這看似簡單的文章就能省去你幾個小時的時間,來寫更多的代碼。哈哈,我相信基本上有需要這方面的功能,但是在網(wǎng)上搜索來實現(xiàn)的時候肯定遇到過坑,所以這篇文章你不會白看的。

靜態(tài)的textView行間距

當(dāng)我們不需要在textView中輸入,直接顯示文字時,設(shè)置textView的行間距非常簡單,網(wǎng)上也有現(xiàn)成的代碼,非常簡單也不會有什么bug。

 UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(20, 100, 100, 200)];
    
    textView.delegate = self;
    
    textView.text = @"哈哈哈哈哈哈大家好大家好大家好大家好";
    
    [self.view addSubview:textView];
    
    NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
    
    paragraphStyle.lineSpacing = 20;// 字體的行間距
    
    NSDictionary *attributes = @{
                                 NSFontAttributeName:[UIFont systemFontOfSize:17],
                                 NSParagraphStyleAttributeName:paragraphStyle
                                 };
    textView.attributedText = [[NSAttributedString alloc] initWithString:textView.text attributes:attributes];

用到NSMutableParagraphStyle這個類,這是設(shè)置段落風(fēng)格的類,有很多屬性,請自行查看API

動態(tài)設(shè)置textView行間距

大多數(shù)情況下,我們的textView是需要輸入的,我們想要在輸入的時候改變行間距,上面的方法就行不通了。我們一貫的解決方法就是去網(wǎng)上查代碼,基本上解決方案都是一樣的,動態(tài)實現(xiàn)的話需要在textView的代理方法中實現(xiàn)。貼上bug代碼。

- (void)textViewDidChange:(UITextView *)textView {
    
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    
    paragraphStyle.lineSpacing = 20;// 字體的行間距
    
    NSDictionary *attributes = @{
                                 NSFontAttributeName:[UIFont systemFontOfSize:15],
                                 NSParagraphStyleAttributeName:paragraphStyle
                                 };
    textView.attributedText = [[NSAttributedString alloc] initWithString:textView.text attributes:attributes];
}

這樣,輸入的時候間距出來了,但是內(nèi)容就不準(zhǔn)確了,輸入的字符會直接顯示到textView上,再次輸入時前一次輸入的還會顯示上去,輸入一個漢字會帶上很多字符。如果是用模擬器運行就不會有這種bug。關(guān)于attributedText的具體實現(xiàn)沒有深入去研究,如果我們換成另外一個屬性就會顯示正常了。

最終的方案

    UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(20, 100, 100, 200)];
    
    textView.delegate = self;
    
    [self.view addSubview:textView];
    
    NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
    
    paragraphStyle.lineSpacing = 20;// 字體的行間距
    
    NSDictionary *attributes = @{
                                 NSFontAttributeName:[UIFont systemFontOfSize:17],
                                 NSParagraphStyleAttributeName:paragraphStyle
                                 };
    textView.typingAttributes = attributes;

主要的一個屬性 typingAttributes,官方文檔中介紹是,該字典中包含屬性鍵去應(yīng)用于新輸入的文本,當(dāng)選擇變化時字典的內(nèi)容被自動清除,如果文本框不是在編輯模式中,這個屬性為nil。同時你也不能賦值這個屬性,除非文本字段目前處于編輯模式。所以這個屬性不會出現(xiàn)使用attributedText的問題。

后續(xù)遇到的問題

以上的方案能夠動態(tài)的改變UITextView的行間距,但是后來發(fā)現(xiàn)一個問題,當(dāng)UITextView的行間距改變之后,光標(biāo)的高度也跟著變化了,這樣的用戶體驗不好。

image.png

后來查閱UITextView的API,沒有發(fā)現(xiàn)相關(guān)的屬性來設(shè)置光標(biāo)的顯示, 使用系統(tǒng)的UITextView暫時解決不了上述問題(如果有使用UITextView的解決方案,還請告知,謝謝!)。
但是,UITextView遵循了UITextInput協(xié)議,其中有返回光標(biāo)frame的方法 *- (CGRect)caretRectForPosition:(UITextPosition )position,所以我們可以使用自定義的TextView,重寫返回光標(biāo)frame的方法來解決這個問題。

- (CGRect)caretRectForPosition:(UITextPosition *)position {
    CGRect originalRect = [super caretRectForPosition:position];
    
    originalRect.size.height = self.font.lineHeight + 2;
    originalRect.size.width = 3;
    
    return originalRect;
}

END

希望我這篇文章能幫助到閱讀的你!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容