1. 程式人生 > >高度自定義TextView 絕對滿足你

高度自定義TextView 絕對滿足你

我們知道iOS自帶的UITextView基本很難滿足我們的日常使用。我專案中textView是繼承與UITextview的,自定義了一個TextView,主要實現的以下功能。

  1. 新增placeHolder
  2. 高度自適應
  3. 可以設定行間距
  4. 支援xib
其實實現起來也是很簡單,但是非常的實用。
一. 先看一下標頭檔案
@interface STTextView : UITextView
/** 佔位文字 */
@property (nonatomic, copy) NSString *placeholder;
/** 佔位文字顏色 */
@property (nonatomic, strong) UIColor *placeholderColor;
//行間距 
@property (nonatomic, assign) CGFloat verticalSpacing; /**設定最大高度*/ @property (nonatomic, assign) CGFloat maxHeight; /**設定最小高度*/ @property (nonatomic, assign) CGFloat minHeight; /**是不是自適應高度,預設為YES*/ @property (nonatomic, assign) BOOL isAutoHeight; @property (nonatomic, copy) void(^textDidChangedBlock)(NSString * text); @property
(nonatomic, copy) void (^textViewAutoHeight)(CGFloat textHeight); @end

應該是一目瞭然的吧。

二. 看一下實現過程
  1. 這裡我是用的是一個UILabel來充當佔位符,控制其隱藏和顯示達到效果。其實還可以通過重寫draw方法,進行繪製placeHolder。這裡考慮到實際使用過程中,會出現佔位符很長,出現換行的情況,使用一個Label可能會更加方便,如下圖這種情況:

相容佔位符很長的情況

2.佔位Label的座標其實還是很講究的
我們知道預設的UITextView會有一個預設的邊距為textContainerInset =UIEdgeInsetsMake (8, 0, 8, 0)

,所以設定placeHolder座標應該考慮到這一點,否則像我這種有點強迫症的人看著很不舒服。我解決方案是新增@property (nonatomic, assign) UIEdgeInsets placeHolderLabelInsets;屬性,重寫textContainerInset屬性,程式碼如下:

#pragma mark ---setter
- (void)setTextContainerInset:(UIEdgeInsets)textContainerInset{
    //調整text內容邊距
    [super setTextContainerInset:textContainerInset];
    self.placeHolderLabelInsets = UIEdgeInsetsMake(textContainerInset.top, textContainerInset.left + 2, textContainerInset.bottom, textContainerInset.right + 2);
    [self setNeedsLayout];
}

這樣我們就可以自由設定文字邊距,而不用再特意去調整placeHoler的座標了,看一下實際效果圖:
1. tv.textContainerInset = UIEdgeInsetsZero
1.邊距都為零時候.png
2. textContainerInset預設值
邊距為預設值時候
3. 設定間距tv.textContainerInset = UIEdgeInsetsMake(15, 10, 15, 10);
UIEdgeInsetsMake(15, 10, 15, 10)
這樣使用起來就簡單多了吧。
3.有一點需要注意的是 使用系統預設鍵盤時候,應處理一下待選字型,否則會出現輸入時候自動把待選字型帶進輸入框,體驗很差,因為待選文字時候也會進入監聽方法,這時候我們需要判斷有沒有待選文字,

if(self.markedTextRange == nil){
        //沒有候選字元
        [self st_setAttributedString];
        self.textDidChangedBlock ? self.textDidChangedBlock(self.text) : nil;
    };

self.markedTextRange == nil 進行處理即可
4.當設定行間距的刪除文字的時候,我們應該保持游標位置,否則使用者刪除中間字型的時候,會不斷跳到最後邊,如下圖:
游標不準
解決這個問題很簡單 只需要 記錄一下游標位置,重新設定一下即可

NSRange range = self.selectedRange;
self.attributedText = [[NSAttributedString alloc]initWithString:self.text attributes:[self attrs]];
 self.selectedRange = range;

如下圖:
游標修復
基本上這都是實際使用中需要注意到的問題,其實程式碼什麼的都挺簡單。

看一下實際使用效果吧:
實際使用效果
希望能夠幫助到大家吧,demo已上傳到我的github,下載拖進工程即可使用,如果使用中有什麼問題請及時與我聯絡。