關(guān)于設(shè)置TextFiled中占位文字的顏色的幾個(gè)方法

歡迎"@WilliamAlex大叔"一起討論iOS技術(shù)

項(xiàng)目需求: 使用textField時(shí),占位文字默認(rèn)是黑色的,我們的需求是當(dāng)開(kāi)始編輯時(shí),讓占位文字和光標(biāo)變成紅色(或其他顏色)

思路: textField和button類(lèi)似,內(nèi)部都擁有子控件,在OC機(jī)制中,所有控件內(nèi)部都是以懶加載的形式添加的.我們可以拿到textField中的子控件label,通過(guò)監(jiān)聽(tīng)textField的狀態(tài),設(shè)置內(nèi)部子控件label的樣式.

  • 方法: 有四中方法:

  • 1, 代理. 2, 通知. 3, target. 4, 是否是第一相應(yīng)者.

  • 方法一: 使用target方法監(jiān)聽(tīng)富文本字符串的改變.

// 1, 首先在xib中描述登錄界面

// 2, 新建一個(gè)繼承于UITextField的類(lèi),將xib中的所有TextFiled都綁定這個(gè)類(lèi).
// 方法1: 通過(guò)富文本字符串來(lái)設(shè)置樣式

- (void)awakeFromNib
{

    // 1, 設(shè)置光標(biāo)的顏色
    self.tintColor = [UIColor whiteColor];

    // 2, 監(jiān)聽(tīng)textField的開(kāi)始編輯狀態(tài)
    [self addTarget:self action:@selector(textFieldBeginEditing) forControlEvents:UIControlEventEditingDidBegin];

    // 3, 監(jiān)聽(tīng)textField的結(jié)束編輯
    [self addTarget:self action:@selector(textFieldEndEditing) forControlEvents:UIControlEventEditingDidEnd];

    // 4, 描述占位文字屬性
    NSMutableDictionary *attr = [NSMutableDictionary dictionary];
    attr[NSForegroundColorAttributeName] = [UIColor darkGrayColor];

    // 5, 富文本屬性
    NSAttributedString *attribute = [[NSAttributedString alloc] initWithString:self.placeholder attributes:attr];

    self.attributedPlaceholder = attribute;

}

  • 注意: 當(dāng)不知道設(shè)置某個(gè)控件的什么屬性時(shí),先去頭文件中找,有沒(méi)有和占位文字相關(guān)的屬性或者方法.如果實(shí)在找不到可以使用runtime,遍歷內(nèi)部的子控件,拿到它對(duì)應(yīng)的控件設(shè)置屬性值即可.
#pragma mark - 事件監(jiān)聽(tīng)方法

// 監(jiān)聽(tīng)開(kāi)始編輯
- (void)textFieldBeginEditing {

    // 1, 描述占位文字屬性
    NSMutableDictionary *attr = [NSMutableDictionary dictionary];
    attr[NSForegroundColorAttributeName] = [UIColor whiteColor];

    // 2, 富文本屬性
    NSAttributedString *attribute = [[NSAttributedString alloc] initWithString:self.placeholder attributes:attr];

    self.attributedPlaceholder = attribute;

}

// 監(jiān)聽(tīng)結(jié)束編輯
- (void)textFieldEndEditing {

    // 4, 描述占位文字屬性
    NSMutableDictionary *attr = [NSMutableDictionary dictionary];
    attr[NSForegroundColorAttributeName] = [UIColor darkGrayColor];

    // 5, 富文本屬性
    NSAttributedString *attribute = [[NSAttributedString alloc] initWithString:self.placeholder attributes:attr];

    self.attributedPlaceholder = attribute;
}

方法二 :

  • 不使用富文本字符串的形式修改占位文字的字體顏色.因?yàn)橹貜?fù)代碼太多.前面講過(guò)最好是直接給對(duì)象控件設(shè)置顏色.TextFiled和Button一樣,內(nèi)部之所以能夠顯示文字,是因?yàn)槠鋬?nèi)部包含有l(wèi)abel.所以只要我們,拿到這個(gè)占位用的label,就可以直接設(shè)置顏色.
  • 主要思路: 方法二的主要思路是利用KVC思想,拿到TextFiled內(nèi)部中的子控件,在使用KVC之前,用runtime變出TextFiled中所有子控件,找到placeholderLabel即可.
- (void)awakeFromNib
{
    UITextField *textFiled;
    // 1.設(shè)置光標(biāo)
    self.tintColor = [UIColor whiteColor];

    // 監(jiān)聽(tīng)開(kāi)始編輯
    [self addTarget:self action:@selector(textBegin) forControlEvents:UIControlEventEditingDidBegin];

    // 監(jiān)聽(tīng)結(jié)束編輯
    [self addTarget:self action:@selector(textEnd) forControlEvents:UIControlEventEditingDidEnd];

    // 根據(jù)屬性名獲取這個(gè)屬性的值
    UILabel *placeholderLabel = [self valueForKeyPath:@"placeholderLabel"];

    placeholderLabel.textColor = [UIColor lightGrayColor];

}

// 文本框開(kāi)始編輯
- (void)textBegin
{
    // 修改占位文字樣式
    // 根據(jù)屬性名獲取這個(gè)屬性的值
    UILabel *placeholderLabel = [self valueForKeyPath:@"placeholderLabel"];

    placeholderLabel.textColor = [UIColor whiteColor];
}

// 文本框結(jié)束編輯
- (void)textEnd
{
    // 根據(jù)屬性名獲取這個(gè)屬性的值
    UILabel *placeholderLabel = [self valueForKeyPath:@"placeholderLabel"];

    placeholderLabel.textColor = [UIColor lightGrayColor];
}
  • 注意 : 這樣設(shè)置相對(duì)上一中方法來(lái)說(shuō)就相對(duì)比較簡(jiǎn)潔一點(diǎn).但是,我們最好是將設(shè)置封裝到一個(gè)分類(lèi)中,提高代碼的復(fù)用.

封裝代碼

- (void)awakeFromNib
{
    // 1.設(shè)置光標(biāo)
    self.tintColor = [UIColor whiteColor];

    // 監(jiān)聽(tīng)開(kāi)始編輯
    [self addTarget:self action:@selector(textBegin) forControlEvents:UIControlEventEditingDidBegin];

    // 監(jiān)聽(tīng)結(jié)束編輯
    [self addTarget:self action:@selector(textEnd) forControlEvents:UIControlEventEditingDidEnd];

    // 根據(jù)屬性名獲取這個(gè)屬性的值
    self.placeholderColor = [UIColor lightGrayColor];
}

// 文本框開(kāi)始編輯
- (void)textBegin
{
    // 修改占位文字樣式
    self.placeholderColor = [UIColor whiteColor];
}

// 文本框結(jié)束編輯
- (void)textEnd
{
    self.placeholderColor = [UIColor lightGrayColor];
}

  • 定義一個(gè)分類(lèi),將設(shè)置占位文字顏色的具體實(shí)現(xiàn)封裝到分類(lèi)中.
.h文件
// 需要將屬性定義在.h文件中,方便外界調(diào)用
// 設(shè)置占位文字顏色
@property UIColor *placeholderColor;
#import "UITextField+Placeholder.h"
#import <objc/message.h>
// runtime:主要目的操作系統(tǒng)的類(lèi)

// OC系統(tǒng)自帶控件中,所有的子控件都是懶加載
@implementation UITextField (Placeholder)

+ (void)load
{
    Method setPlaceholderMethod = class_getInstanceMethod(self, @selector(setPlaceholder:));
     Method wg_setPlaceholderMethod = class_getInstanceMethod(self, @selector(wg_setPlaceholder:));

    // 交互方法
    method_exchangeImplementations(setPlaceholderMethod, wg_setPlaceholderMethod);

}

// 設(shè)置占位文字顏色
- (void)setPlaceholderColor:(UIColor *)placeholderColor
{
    // 1.保存占位文字顏色到系統(tǒng)的類(lèi),關(guān)聯(lián)
    // object:保存到哪個(gè)對(duì)象中
    // key:屬性名
    // value:屬性值
    // policy:策略
    objc_setAssociatedObject(self, @"placeholderColor", placeholderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    UILabel *placeholderLabel = [self valueForKeyPath:@"placeholderLabel"];
    placeholderLabel.textColor = placeholderColor;
}

- (UIColor *)placeholderColor
{
    return objc_getAssociatedObject(self, @"placeholderColor");
}

- (void)wg_setPlaceholder:(NSString *)placeholder
{
    // 設(shè)置占位文字
    [self wg_setPlaceholder:placeholder];

    // 設(shè)置占位文字顏色
    self.placeholderColor = self.placeholderColor;
}

  • 知識(shí)拓展: 在使用代理時(shí),最好不要讓自己成為自己的代理,雖然不會(huì)報(bào)錯(cuò),但是不符合代理的原理.所以,建議不要使用這種方法,上面所述的方法.主要是想知道有這么個(gè)方法和過(guò)程.在實(shí)際開(kāi)發(fā)中我會(huì)運(yùn)用的方法如下:

使用Target監(jiān)聽(tīng)TextField內(nèi)部控件的私有屬性.

  • 首先是使用運(yùn)行時(shí)機(jī)制獲取某個(gè)控件內(nèi)部的私有屬性
// 1, 獲取私有屬性
    // 運(yùn)行時(shí)獲取類(lèi)中的私有屬性
    unsigned int count;
    // 運(yùn)行時(shí)打印出文本框中的所有成員屬性
    Ivar *ivarList = class_copyIvarList([UITextField class], &count);
    for (int i =0; i< count; i++) {
        Ivar ivar = ivarList[i];

        NSLog(@"%s",ivar_getName(ivar));
    }
    free(ivarList);

  • 其次將從遍歷出來(lái)的屬性中找到想要修改的屬性
// 2, 找到對(duì)應(yīng)的私有屬性,將它設(shè)置為一個(gè)宏
static NSString * const WGPlaceholderLabel = @"placeholderLabel.textColor";

  • 然后監(jiān)聽(tīng)私有屬性
    // 設(shè)置占位文字原有顏色
    [self setValue:[UIColor grayColor] forKeyPath:WGPlaceholderLabel];

    // 監(jiān)聽(tīng)文本框開(kāi)始編輯
    [self addTarget:self action:@selector(editingBegin) forControlEvents:UIControlEventEditingDidBegin];

    // 監(jiān)聽(tīng)文本框結(jié)束編輯
    [self addTarget:self action:@selector(editingEnd) forControlEvents:UIControlEventEditingDidEnd];

  • 最后實(shí)現(xiàn)監(jiān)聽(tīng)方法
#pragma mark - 監(jiān)聽(tīng)文本框的編輯狀態(tài)

- (void)editingBegin{

    [self setValue:[UIColor whiteColor] forKeyPath:WGPlaceholderLabel];
}

- (void)editingEnd {

   [self setValue:[UIColor grayColor] forKeyPath:WGPlaceholderLabel];
}
  • 總結(jié):
  • 1, 文本框和按鈕一樣,都可以編輯文字,所以?xún)?nèi)部是有l(wèi)abel的,所以需要拿到文本框中的label(可以在"小面包中檢測(cè)"),當(dāng)輸入文字后,有個(gè)label就會(huì)消失,那個(gè)就是占位label,所以需要拿到系統(tǒng)內(nèi)部的私有屬性,但是不能直接拿到私有的屬性和方法,所以需要用到KVC去取值和賦值.通過(guò)"運(yùn)行時(shí)"拿到屬性
  • 2, 然后通過(guò)KVC取值
    容易出錯(cuò)點(diǎn): 不要用setValu:forKey,程序會(huì)崩掉,要用forKeyPath:表示不管你在文件的那一層都能去拿到

代理(不推薦使用)

  • 這里使用代理需要注意一點(diǎn):它是自己成為了自己的代理,雖然可以實(shí)現(xiàn)項(xiàng)目需求,但是,這和"代理"的本質(zhì)有沖突.
  • 代理本質(zhì): 自己不能做的事,讓自己的代理去做
/*
 總結(jié): 本章是用代理的方式監(jiān)聽(tīng)文本框的編輯狀態(tài),然后通過(guò)拿到UITextField中的私有的_placeholderLabel屬性,給私有屬性賦值即可,通過(guò)運(yùn)行時(shí)獲取查看其內(nèi)部的所有私有屬性,然后通過(guò)KVC賦值;
 */

#import "WGLoginRegisterTextFiled.h"
#import <objc/message.h>

static NSString * const WGPlaceholderLabel = @"_placeholderLabel.textColor";

@interface WGLoginRegisterTextFiled () <UITextFieldDelegate>
@end
@implementation WGLoginRegisterTextFiled

- (void)awakeFromNib {

    // 設(shè)置光標(biāo)顏色
    self.tintColor = [UIColor cyanColor];

    // 通過(guò)運(yùn)行時(shí)獲取TextFiled的內(nèi)部私有屬性
    unsigned int count ;
    Ivar *ivarList = class_copyIvarList([UITextField class], &count);
    // 遍歷UITextField的所有屬性,ivarList(指針)實(shí)質(zhì)是一個(gè)數(shù)組

    for (int i = 0; i < count; i++) {

        // 獲取每一個(gè)屬性
        Ivar ivar = ivarList[i];

        NSLog(@"%s",ivar_getName(ivar));  // "%s"原因是運(yùn)行時(shí)是一個(gè)C語(yǔ)言的語(yǔ)法

    }

    // 銷(xiāo)毀運(yùn)行時(shí)創(chuàng)建的ivarList
    free(ivarList);

    // 通過(guò)KVC將屬性取出來(lái)并賦值
    [self setValue:[UIColor grayColor] forKeyPath:WGPlaceholderLabel];

    // 設(shè)置代理
    self.delegate = self; // 自己成為自己的代理,在實(shí)際開(kāi)發(fā)中不這樣寫(xiě),這和代理的原理意義上違背了

}

#pragma mark - 設(shè)置代理的方法

// 開(kāi)始編輯
- (void)textFieldDidBeginEditing:(UITextField *)textField {

    // KVC
    [self setValue:[UIColor whiteColor] forKeyPath:WGPlaceholderLabel];

}

// 結(jié)束編輯
- (void)textFieldDidEndEditing:(UITextField *)textField {

    [self setValue:[UIColor grayColor] forKeyPath:WGPlaceholderLabel];

}

根據(jù)某些控件特有的方法或者屬性來(lái)設(shè)置

  • TextFiled有一個(gè)特別的屬性方法:即是否成為第一響應(yīng)者和不當(dāng)?shù)谝豁憫?yīng)者.根據(jù)這樣的特性做一些操作.
/*
 分析:UITextField有一個(gè)特有的屬性,就是響應(yīng)者屬性,通過(guò)重寫(xiě)成為第一響應(yīng)者和辭去第一響應(yīng)者來(lái)給占位文字設(shè)置顏色


 */
#import "WGLoginRegisterTextFiled.h"
#import <objc/message.h>

static NSString * const WGPlaceholderLabel = @"_placeholderLabel.textColor";

@interface WGLoginRegisterTextFiled () <UITextFieldDelegate>
@end
@implementation WGLoginRegisterTextFiled

- (void)awakeFromNib {

    // 設(shè)置光標(biāo)顏色
    self.tintColor = [UIColor cyanColor];

    // 通過(guò)KVC將屬性取出來(lái)并賦值
    [self setValue:[UIColor grayColor] forKeyPath:WGPlaceholderLabel];

    // 調(diào)用時(shí)刻: 當(dāng)成為第一響應(yīng)者 /獲取焦點(diǎn) /彈出鍵盤(pán)
    [self becomeFirstResponder];

    // 調(diào)用時(shí)刻: 當(dāng)失去第一響應(yīng)者 /獲取焦點(diǎn) /彈出鍵盤(pán)
    [self resignFirstResponder];

}

#pragma mark - 設(shè)置代理的方法


// 調(diào)用時(shí)刻: 當(dāng)成為第一響應(yīng)者 /獲取焦點(diǎn) /彈出鍵盤(pán)
- (BOOL)becomeFirstResponder {

    [self setValue:[UIColor whiteColor] forKeyPath:WGPlaceholderLabel];

    return [super becomeFirstResponder];
}

// 調(diào)用時(shí)刻: 當(dāng)失去第一響應(yīng)者 /獲取焦點(diǎn) /彈出鍵盤(pán)
- (BOOL)resignFirstResponder {

    [self setValue:[UIColor grayColor] forKeyPath:WGPlaceholderLabel];

   return [super resignFirstResponder];

}
@end

  • 總結(jié):其實(shí)還有通知方法的,和代理類(lèi)似,所以就不寫(xiě)了.本章重點(diǎn).

  • 1, 學(xué)會(huì)編程思想,不要局限于某一種方式開(kāi)發(fā)

  • 2, 學(xué)會(huì)利用某些特有的方法或者屬性來(lái)解決問(wèn)題

  • 3, 如果有時(shí)間可以深入學(xué)習(xí)運(yùn)行時(shí)機(jī)制(特別有意思)

  • 知識(shí)拓展: 在使用代理時(shí),最好不要讓自己成為自己的代理,雖然不會(huì)報(bào)錯(cuò),但是不符合代理的原理.所以,建議不要使用這種方法

  • 注意: 本章使用的target監(jiān)聽(tīng)textFiled的編輯狀態(tài),但是這是不符合代理的原理,在實(shí)際開(kāi)發(fā)中"盡量不要自己成為自己的代理".我的建議是使用textFiled的特性,即"第一響應(yīng)者"來(lái)監(jiān)聽(tīng)textFiled的編輯狀態(tài).

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市铝条,隨后出現(xiàn)的幾起案子靖苇,更是在濱河造成了極大的恐慌,老刑警劉巖攻晒,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件顾复,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鲁捏,警方通過(guò)查閱死者的電腦和手機(jī)芯砸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)萧芙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人假丧,你說(shuō)我怎么就攤上這事双揪。” “怎么了包帚?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵渔期,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我渴邦,道長(zhǎng)疯趟,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任谋梭,我火速辦了婚禮信峻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瓮床。我一直安慰自己盹舞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布隘庄。 她就那樣靜靜地躺著踢步,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丑掺。 梳的紋絲不亂的頭發(fā)上获印,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音吼鱼,去河邊找鬼蓬豁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛菇肃,可吹牛的內(nèi)容都是我干的地粪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼琐谤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蟆技!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起斗忌,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤质礼,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后织阳,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體眶蕉,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年唧躲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了造挽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碱璃。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖饭入,靈堂內(nèi)的尸體忽然破棺而出嵌器,到底是詐尸還是另有隱情,我是刑警寧澤谐丢,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布爽航,位于F島的核電站,受9級(jí)特大地震影響乾忱,放射性物質(zhì)發(fā)生泄漏讥珍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一饭耳、第九天 我趴在偏房一處隱蔽的房頂上張望串述。 院中可真熱鬧,春花似錦寞肖、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至右蕊,卻和暖如春琼稻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背饶囚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工帕翻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人萝风。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓嘀掸,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親规惰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子睬塌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

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