實現(xiàn)帶有占位文字的textView

UITextView默認(rèn)是不帶有占位文字的,如果實現(xiàn)這個功能,大致有兩個方法:

  • textView中添加一個label,讓label實現(xiàn)占位文字功能.
  • 重寫drawRect方法,直接將文字畫上去.

IQKeyboradManager中實現(xiàn)這個功能用的是第一種方法,實現(xiàn)的類為IQTextView,繼承自UITextView.

方法一:

IQTextView.h

@interface IQTextView : UITextView

/**
 Set textView's placeholder text. Default is nil.
 */
@property(nullable, nonatomic,copy) IBInspectable NSString    *placeholder;
@end

IQTextView.m

@interface IQTextView ()

-(void)refreshPlaceholder;

@end

// 寫到這里比寫成屬性懶加載好,因為只有設(shè)置占位文字的時候才需要創(chuàng)建占位Label
@implementation IQTextView
{
    UILabel *placeHolderLabel;
}

@synthesize placeholder = _placeholder;

// 初始化方法中添加監(jiān)聽 UITextViewTextDidChangeNotification 事件
-(void)initialize
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshPlaceholder) name:UITextViewTextDidChangeNotification object:self];
}

-(void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self initialize];
    }
    return self;
}

// xib加載時也要初始化
-(void)awakeFromNib
{
    [super awakeFromNib];
    [self initialize];
}

-(void)refreshPlaceholder
{
    if([[self text] length])
    {
        [placeHolderLabel setAlpha:0];
    }
    else
    {
        [placeHolderLabel setAlpha:1];
    }
    
    [self setNeedsLayout];  // 添加刷新標(biāo)記
    [self layoutIfNeeded];  // 立即刷新
}

- (void)setText:(NSString *)text
{
    [super setText:text];
    [self refreshPlaceholder];
}

-(void)setFont:(UIFont *)font
{
    [super setFont:font];
    placeHolderLabel.font = self.font;
    
    [self setNeedsLayout];  // 添加刷新標(biāo)記
    [self layoutIfNeeded];  // 立即刷新
}

-(void)layoutSubviews
{
    [super layoutSubviews];

    [placeHolderLabel sizeToFit];
    placeHolderLabel.frame = CGRectMake(8, 8, CGRectGetWidth(self.frame)-16, CGRectGetHeight(placeHolderLabel.frame));
}

-(void)setPlaceholder:(NSString *)placeholder
{
    _placeholder = placeholder;
    
    if ( placeHolderLabel == nil )
    {
        placeHolderLabel = [[UILabel alloc] init];
        placeHolderLabel.autoresizingMask = (UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight);
        placeHolderLabel.lineBreakMode = NSLineBreakByWordWrapping;
        placeHolderLabel.numberOfLines = 0;
        placeHolderLabel.font = self.font;
        placeHolderLabel.backgroundColor = [UIColor clearColor];
        placeHolderLabel.textColor = [UIColor colorWithWhite:0.7 alpha:1.0];
        placeHolderLabel.alpha = 0;
        [self addSubview:placeHolderLabel];
    }
    
    placeHolderLabel.text = self.placeholder;
    [self refreshPlaceholder];
}

//When any text changes on textField, the delegate getter is called. At this time we refresh the textView's placeholder
// 代理的get方法中刷新占位文字狀態(tài)
-(id<UITextViewDelegate>)delegate
{
    [self refreshPlaceholder];
    return [super delegate];
}

@end
  • IBInspectable 關(guān)鍵字

在類的聲明中,placeholder屬性聲明為IBInspectable.這是什么意思呢?

標(biāo)有 @IBInspectable(或是 Objective-C 中的 IBInspectable),他們就可以很容易在 Interface Builder 的觀察面板(inspector panel)里編輯适揉。需要注意的是 Xcode 在這里做了更多的事幅疼,屬性名稱是從 camel- 轉(zhuǎn)換為 title- 模式 并且相關(guān)的名稱組合在一起:因為可檢查屬性僅僅是用戶定義的運行時屬性頂部的接口沸停,所以支持相同的類型列表:布爾圃泡,字符串和數(shù)字(即浸颓,NSNumber 或任何數(shù)值類型),以及 CGPoint壮啊、CGSize嫉鲸、CGRect、UIColor 和 NSRange歹啼,額外增加了 UIImage玄渗。

如圖Interface Builder 中多了placeholder屬性:


顯示屬性

擴展: IBDesignable 關(guān)鍵字

當(dāng)應(yīng)用到 UIView 或 NSView 子類中的時候,@ IBDesignable 讓 Interface Builder 知道它應(yīng)該在畫布上直接渲染視圖狸眼。你會看到你的自定義視圖在每次更改后不必編譯并運行你的應(yīng)用程序就會顯示藤树。
標(biāo)記一個自定義視圖為 IBDesignable,只需在類名前加上 @IBDesignable 的前綴(或是 Objective-C 里的 IB_DESIGNABLE 宏)拓萌。你的初始化岁钓、布置和繪制方法將被用來在畫布上渲染你的自定義視圖:


IBDesignable作用

使用方法:

swift中:

@IBDesignable
class View: UIView { .... }

OC中:

IB_DESIGNABLE
@implementation View
  • @proprety@synthesize@dynamic 關(guān)鍵字

@proprety = ivar + getter + setter
在聲明中寫@property(nullable, nonatomic,copy) IBInspectable NSString *placeholder; 這句代碼后,編譯器會自動寫出一套 微王、 方法.這個過程由編譯 器在編譯期執(zhí)行,所以編輯器里看不到這些“合成方法”(synthesized method)的源代碼.除了生成方法代碼 getter屡限、setter 之外,編譯器還要 自動向類中添加適當(dāng)類型的實例變量 ,并且 在屬性名前面加下劃線 炕倘,以此作為實例變量的名字.

也可以在類的實現(xiàn)代碼里通過 @synthesize 語法來指定實例變量的名字.

@implementation IQTextView

@synthesize placeholder = _myPlaceholder;
...
@end

@property有兩個 對應(yīng) 的詞,一個是@synthesize,一個是@dynamic.如果@synthesize和@dynamic都沒寫钧大,那么默認(rèn)的就是@syntheszie placeholder = _myPlaceholder;

@synthesize的語義是如果你沒有手動實現(xiàn)setter方法和getter方法,那么編譯器會自動為你加上這兩個方法罩旋。
@dynamic告訴編譯器:屬性的setter與getter方法由用戶自己實現(xiàn),不自動生成.(當(dāng)然對于readonly的屬性只需提供getter即可).假如一個屬性被聲明為@dynamic var,然后你沒有提供@setter方法和@getter方法,編譯的時候沒問題,但是當(dāng)程序運行到 instance.var = someVar ,由于缺setter方法會導(dǎo)致程序崩潰啊央;或者當(dāng)運行到 someVar = var 時,由于缺getter方法同樣會導(dǎo)致崩潰涨醋。編譯時沒問題瓜饥,運行時才執(zhí)行相應(yīng)的方法,這就是所謂的動態(tài)綁定东帅。

  • setNeedsLayout 压固、 layoutIfNeeded 關(guān)鍵字

參考 http://www.reibang.com/p/eb2c4bb4e3f1

方法二:

- (void)drawRect:(CGRect)rect {
    if (self.hasText) return;
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    dic[NSFontAttributeName] = [UIFont systemFontOfSize:17];
    dic[NSForegroundColorAttributeName] = [UIColor grayColor];
    [self.placeholder drawInRect:CGRectMake(4, 5, self.bounds.size.width, self.bounds.size.height) withAttributes:dic];
}
- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame])  {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextViewTextDidChangeNotification object:nil];
    }
    return self;
}
- (void)awakeFromNib {
    [super awakeFromNib];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextViewTextDidChangeNotification object:nil];
}
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)textChange{
    [self setNeedsDisplay]; //這個方法會調(diào)用drawRect方法。
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末靠闭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坎炼,更是在濱河造成了極大的恐慌愧膀,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谣光,死亡現(xiàn)場離奇詭異檩淋,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門蟀悦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來媚朦,“玉大人,你說我怎么就攤上這事日戈⊙牛” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵浙炼,是天一觀的道長份氧。 經(jīng)常有香客問我,道長弯屈,這世上最難降的妖魔是什么蜗帜? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮资厉,結(jié)果婚禮上厅缺,老公的妹妹穿的比我還像新娘。我一直安慰自己宴偿,他們只是感情好店归,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著酪我,像睡著了一般消痛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上都哭,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天秩伞,我揣著相機與錄音,去河邊找鬼欺矫。 笑死纱新,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的穆趴。 我是一名探鬼主播脸爱,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼未妹!你這毒婦竟也來了簿废?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤络它,失蹤者是張志新(化名)和其女友劉穎族檬,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體化戳,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出线梗,到底是詐尸還是另有隱情仪搔,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布抱虐,位于F島的核電站懦冰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瓤鼻,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沃粗。 院中可真熱鬧最盅,春花似錦、人聲如沸起惕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惹想。三九已至问词,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嘀粱,已是汗流浹背激挪。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留草穆,地道東北人灌灾。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像悲柱,于是被迫代替她去往敵國和親锋喜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

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

  • 很長一段時間對圈子持排斥態(tài)度豌鸡,不太愿意參與嘿般,總感覺功利性太強。最近倆個參加的圈子改變了自己對圈子的看法涯冠。一個是北大...
    韌性十足的牛皮糖閱讀 286評論 0 0
  • Ubuntu16.04 已經(jīng)出現(xiàn)N次循環(huán)登錄的問題了炉奴,每次都重裝,這次實在受不了了蛇更,擼起袖子就是干罢案稀赛糟!循環(huán)登錄的原...
    izhangxm閱讀 25,273評論 4 8
  • 看了二熊的端午節(jié),我想說其實我也和端午節(jié)有很深的淵源砸逊,我是端午節(jié)的前一天生日璧南。 小時候問過我媽,怎么就正好生...
    水吉先森閱讀 927評論 0 0