更改UITextField的placeholder文字顏色的5種方法
想要達到的目標是:一個頁面上有多個UITextField,當用戶聚焦某textField時,該文本框的placeholder的文字會灰色變為白色,當文本框失去焦點時,placeholder顏色從白色再變回灰色。
1.放置UILabel
最簡單最笨的方法是在每個textField里放一個UILabel來充當placeholder,當該textField聚焦時,讓placeholder的文字會灰色變為白色,失焦后從白色再變回灰色。這種方法需要對每個UILabel和TextField拖線,通過監聽鍵盤通知或者UITextField的代理來獲悉textField是否聚焦,然后寫一堆if語句來判斷。
2.修改textField.attributedPlaceholder屬性
//通過NSAttributedString來更改placeholder顏色。此種方法比較麻煩的是,需要知道頁面上所有的textField什么時候聚焦,什么時候失焦(有兩種方法:A.監聽鍵盤彈出的通知 B.通過UITextField的代理方法textFieldDidBeginEditing),然后再判斷哪個是白色,哪個是灰色。如果頁面上textField非常多,就需要寫很多的if語句。
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc]initWithString:@"手機號" attributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
self.phoneTextField.attributedPlaceholder = attrString;
3. 利用UITextField的子類重寫drawPlaceholderInRect:方法
具體實現見代碼:
//該方法的好處是不用獲取Xib中textField的引用,不用拖線,直接將Xib中textField的class改為自定義類即可。以后有任何textField想要改變placeholder的顏色,直接定義為該類即可。但還是需要自己監控UITextField是否聚焦。 #import "WZCustomPlaceholderTextField.h" @implementation WZCustomPlaceholderTextField /** @interface NSString(NSStringDrawing) NSString的分類 - (CGSize)sizeWithAttributes:(nullable NSDictionary<NSString *, id> *)attrs NS_AVAILABLE(10_0, 7_0); - (void)drawAtPoint:(CGPoint)point withAttributes:(nullable NSDictionary<NSString *, id> *)attrs NS_AVAILABLE(10_0, 7_0); - (void)drawInRect:(CGRect)rect withAttributes:(nullable NSDictionary<NSString *, id> *)attrs NS_AVAILABLE(10_0, 7_0); @end */ - (void)drawPlaceholderInRect:(CGRect)rect {//rect代表該自定義textField的frame/rect //因為placeholder屬於NSString類型,所有的NSString都有drawInRect方法,但此方法似乎只在draw開頭方法中有效 [self.placeholder drawInRect:CGRectMake(0, 10, rect.size.width, rect.size.height) withAttributes:@{ NSForegroundColorAttributeName:[UIColor whiteColor], NSFontAttributeName:[UIFont systemFontOfSize:15] }]; } - (void)drawRect:(CGRect)rect {//rect代表該自定義textField的frame/rect [super drawRect:rect]; //調用父類UITextField的drawRect方法,將自定義尺寸傳進去。必須調用父類 } @end
4.利用UITextField的子類重寫drawRect:方法,在drawRect中通過[self.placeholder drawInRect:]來進行設置。
5.通過KVC向UITextField隱藏的內部實例變量_placeholderLabel設值。
利用runtime打印出UITextField所有的實例變量,發現有個叫_placeholderLabel的內部實例變量,在自定義類中通過KVC設值。此方法好處是:利用KVC設值方便簡潔,而且可以寫在任何位置。本例中我們重寫becomeFirstResponder:和resignFirstResponder方法來監控UITextField是否聚焦,然后在其中利用KVC設值。
// WZTextField.m // 利用runtime打印出UITextField所有的實例變量,發現有個叫_placeholderLabel的內部實例變量,在自定義類中通過KVC設值。 // #import "WZTextField.h" @implementation WZTextField //調用順序1 (從xib創建時調用) - (instancetype)initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { } return self; } //調用順序2 (從xib創建時調用) - (void)awakeFromNib { } //調用順序3 (無論xib還是純代碼創建都會調用) - (void)drawRect:(CGRect)rect { [super drawRect:rect]; self.tintColor = self.textColor; //設置光標顏色和文字顏色一樣 } - (BOOL)becomeFirstResponder { [self setValue:[UIColor whiteColor] forKeyPath:@"_placeholderLabel.textColor"]; return [super becomeFirstResponder]; } - (BOOL)resignFirstResponder { [self setValue:[UIColor grayColor] forKeyPath:@"_placeholderLabel.textColor"]; return [super resignFirstResponder]; } @end