占位文字
-
1礁阁、曾經(jīng)有個這么一個項目需求: 使用textField時,占位文字默認(rèn)是黑色的,我們的需求是當(dāng)開始編輯時,讓占位文字和光標(biāo)變成紅色(或其他顏色)
- 思路: textField和button類似,內(nèi)部都擁有子控件,在OC機制中,所有控件內(nèi)部都是以懶加載的形式添加的.我們可以拿到textField中的子控件label,通過監(jiān)聽textField的狀態(tài),設(shè)置內(nèi)部子控件label的樣式.
-
2、當(dāng)系統(tǒng)自帶的控件滿足不了項目要求時
- 對于 UITextField :
1> 有占位文字 2> 最多只能輸入一行文字
- 對于UITextView :
1> 沒有占位文字 2> 能輸入任意行文字陆馁,并且超出顯示范圍的可以滾動(UITextView繼承自UIScrollView)
- 而我們需要的結(jié)果 :
1> 有占位文字 2> 能輸入任意行文字
那么我們可以用腳想一想便可選擇自定義控件繼承于UITextField /UITextView,實現(xiàn)添加其占位文字的功能绢淀。
-
3慌申、以后開發(fā)中可能經(jīng)常會使用到這種技術(shù)访圃,所以我現(xiàn)在就總結(jié)一下如何弄占位文字以及修改占位文字的顏色替蔬,方便以后開發(fā)(只提供了一種思路告私,其他方法思路自己可以總結(jié))。
- 注意 : 以下方法我們最好是將它封裝到一個分類中,提高代碼的復(fù)用和封裝性.
以下是封裝的代碼:
一承桥、UITextField
1.第一種方法:UITextField利用RunTime來設(shè)置占位文字的顏色
主要思路: 方法二的主要思路是利用KVC思想,拿到TextFiled內(nèi)部中的子控件,在使用KVC之前,用runtime變出TextFiled中所有子控件,找到placeholderLabel即可.
########################### .h文件 ###########################
// UITextField+LYMPlaceholderColor.m
// Created by ming on 14/12/20.
// Copyright ? 2014年 ming. All rights reserved.
#import <UIKit/UIKit.h>
@interface UITextField (LYMPlaceholderColor)
/** 占位顏色 */
@property (nonatomic,strong) UIColor *placeholderColor;
/** 名字 */
@property (nonatomic,copy) NSString *name;
@end
########################### .m文件 ###########################
// UITextField+LYMPlaceholderColor.m
// Created by ming on 14/12/20.
// Copyright ? 2014年 ming. All rights reserved.
/**
* 利用RunTime來設(shè)置占位文字的顏色
*/
#import "UITextField+LYMPlaceholderColor.h"
// 導(dǎo)入頭文件驻粟,導(dǎo)入下面其中一個即可
#import <objc/runtime.h>
//#import <objc/message.h>
// OC最喜歡懶加載,用的的時候才會去加載
// 需要給系統(tǒng)UITextField添加屬性,只能使用runtime
static NSString *const LYMPlaceholderLabelKey = @"placeholderLabel";
static NSString *const placeholderColorName = @"placeholderColor";
@implementation UITextField (LYMPlaceholderColor)
#pragma mark - 利用RunTime動態(tài)增加屬性和交換方法 =
/// 實現(xiàn)交換方法 (mg_setPlaceholder:和setPlaceholder:的互換)
+ (void)load{
Method mg_setPlaceholder = class_getInstanceMethod(self, @selector(mg_setPlaceholder:));
Method setPlaceholder = class_getInstanceMethod(self, @selector(setPlaceholder:));
method_exchangeImplementations(setPlaceholder, mg_setPlaceholder);
}
/// 外界賦值占位顏色的時候就會調(diào)用
- (void)setPlaceholderColor:(UIColor *)placeholderColor{
// 動態(tài)增加placeholderColor屬性
objc_setAssociatedObject(self, (__bridge const void *)(placeholderColorName), placeholderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// 設(shè)置顏色
UILabel *placeholderLabel = [self valueForKeyPath:LYMPlaceholderLabelKey];
placeholderLabel.textColor = placeholderColor;
}
- (UIColor *)placeholderColor{
// return _placeholderColor;
return objc_getAssociatedObject(self,(__bridge const void *)(placeholderColorName));
}
/// 外界賦值占位文字的時候會調(diào)用(自定義的方法,用來和系統(tǒng)的方法交換)
- (void)mg_setPlaceholder:(NSString *)placeholder{
// 1.設(shè)置占位文字
[self mg_setPlaceholder:placeholder];
// 2.設(shè)置占位文字顏色
self.placeholderColor = self.placeholderColor;
}
#pragma mark - 測試RunTime動態(tài)增加屬性
- (void)setName:(NSString *)name{
// 動態(tài)增加“name”屬性
objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name{
return objc_getAssociatedObject(self, @"name");
}
@end
總結(jié):
1, 文本框和按鈕一樣,都可以編輯文字,所以內(nèi)部是有l(wèi)abel的,所以需要拿到文本框中的label(可以在"小面包中檢測"),當(dāng)輸入文字后,有個label就會消失,那個就是占位label,所以需要拿到系統(tǒng)內(nèi)部的私有屬性,但是不能直接拿到私有的屬性和方法,所以需要用到KVC去取值和賦值.通過"運行時"拿到屬性
2, 然后通過KVC取值
容易出錯點: 不要用setValu:forKey,程序會崩掉,要用forKeyPath:表示不管你在文件的那一層都能去拿到
2.第二種方法:UITextField 設(shè)置占位文字的顏色,讓外界直接使用(這種方法有點投機取巧)
--這樣設(shè)置相對上一中方法來說就相對比較簡潔
########################### .h文件 ###########################
#import <UIKit/UIKit.h>
@interface UITextField (placeholderColor)
/** 占位顏色 */
@property (nonatomic,strong) UIColor *placeholderColor;
@end
########################### .m文件 ###########################
/**
* 設(shè)置占位文字的顏色,讓外界直接使用
*/
#import "UITextField+placeholderColor.h"
static NSString *const placeholderColorKey = @"placeholderLabel.textColor";
@implementation UITextField (placeholderColor)
// 重寫placeholderColor的setter方法
- (void)setPlaceholderColor:(UIColor *)placeholderColor{
// bool屬性凶异,有文字就這設(shè)置為YES
BOOL change = NO;
// 如果當(dāng)前placeholder文字為空蜀撑,那么就隨便賦值幾個文字,讓它不為空
if (self.placeholder == nil) {
self.placeholder = @"mingge";
// 設(shè)置 change = YES
change = YES;
}
[self setValue:placeholderColor forKey:placeholderColorKey];
// 如果change = YES,那么要把placeholder文字再次設(shè)為空
if (change) {
self.placeholder = nil;
}
}
// 重寫placeholderColor的getter方法
- (UIColor *)placeholderColor{
return [self valueForKeyPath:placeholderColorKey];
}
@end
二剩彬、UITextView
1.第一種方法:UITextView利用
Quartz2D繪圖 來設(shè)置占位文字以及顏色
// 重繪
[self setNeedsDisplay];
########################### .h文件 ###########################
// LYMTextView.h
// Created by ming on 14/12/9.
// Copyright ? 2014年 ming. All rights reserved.
#import <UIKit/UIKit.h>
@interface LYMTextView : UITextView
/** 占位文字 */
@property (nonatomic,copy) NSString *placeholder;
/** 文字顏色 */
@property (nonatomic,strong) UIColor *placeholderColor;
@end
########################### .m文件 ###########################
/**
* 給UITTextView顯示占位文字的功能屯掖,以后如需使用,就可以直接拿去用
*/
#import "LYMTextView.h"
@implementation LYMTextView
#pragma mark ========== 通知 =============
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]){
self.textColor = [UIColor blackColor];
// 設(shè)置占位文字的默認(rèn)字體顏色和字體大小
self.placeholderColor = [UIColor grayColor];
self.font = [UIFont systemFontOfSize:15];
// 發(fā)布通知(當(dāng)空間的內(nèi)容發(fā)生改變時)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:UITextViewTextDidChangeNotification object:self];
}
return self;
}
- (void)textDidChange:(NSNotification *)note{
// 重繪
[self setNeedsDisplay];
}
// 移除監(jiān)聽者
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark ========== 繪制占位文字 ===========
// 繪制占位文字
- (void)drawRect:(CGRect)rect {
// 如果有文字就不繪制(不執(zhí)行下面的操作)
if (self.text.length) return;
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
// if (self.font) dict[NSFontAttributeName] = self.font;
// if (self.placeholderColor) dict[NSForegroundColorAttributeName] = self.placeholderColor;
dict[NSFontAttributeName] = self.font;
dict[NSForegroundColorAttributeName] = self.placeholderColor;
rect.origin.x = 4;
rect.origin.y = 8;
rect.size.width = LYMScreenWidth - 2 * rect.origin.x;
[self.placeholder drawInRect:rect withAttributes:dict];
}
#pragma mark ========== 需要重寫的屬性 ===========
// 重寫占位文字
- (void)setPlaceholder:(NSString *)placeholder{
_placeholder = [placeholder copy];
// 重繪
[self setNeedsDisplay];
}
// 重寫占位文字顏色
- (void)setPlaceholderColor:(UIColor *)placeholderColor{
_placeholderColor = placeholderColor;
// 重繪
[self setNeedsDisplay];
}
// 重寫占位文字字體大小
- (void)setFont:(UIFont *)font{
[super setFont:font];
// 重繪
[self setNeedsDisplay];
}
// 重寫文字
- (void)setText:(NSString *)text{
[super setText:text];
// 重繪
[self setNeedsDisplay];
}
// 重寫文字屬性
- (void)setAttributedText:(NSAttributedString *)attributedText{
[super setAttributedText:attributedText];
// 重繪
[self setNeedsDisplay];
}
// textView的尺寸發(fā)生改變
- (void)layoutSubviews{
[super layoutSubviews];
// 重繪
[self setNeedsDisplay];
}
@end
2.第二種方法:UITextView利用
刷新 來設(shè)置占位文字以及顏色
// 重新布局
[self setNeedsLayout];
########################### .h文件 ###########################
// LYMTextViewWithLabel.h
// Created by ming on 14/12/9.
// Copyright ? 2014年 ming. All rights reserved.
#import <UIKit/UIKit.h>
@interface LYMTextViewWithLabel : UITextView
/** 占位文字 */
@property (nonatomic,copy) NSString *placeholder;
/** 文字顏色 */
@property (nonatomic,strong) UIColor *placeholderColor;
@end
########################### .m文件 ###########################
#import "LYMTextViewWithLabel.h"
@interface LYMTextViewWithLabel ()
/** 占位Label */
@property (nonatomic,weak) UILabel *placeholderLabel;
@end
@implementation LYMTextViewWithLabel
#pragma mark ========== 通知 =============
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]){
// 創(chuàng)建一個UILabel
UILabel *placeholderLabel = [[UILabel alloc] init];
placeholderLabel.numberOfLines = 0;
[self addSubview:placeholderLabel];
self.placeholderLabel = placeholderLabel;
// 設(shè)置占位文字的默認(rèn)字體顏色和字體大小
self.textColor = [UIColor blackColor];
self.font = [UIFont systemFontOfSize:15];
// 發(fā)布通知(當(dāng)空間的內(nèi)容發(fā)生改變時)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:UITextViewTextDidChangeNotification object:self];
}
return self;
}
// 布局占位文字的位置和尺寸
- (void)layoutSubviews{
[super layoutSubviews];
self.placeholderLabel.x = 4;
self.placeholderLabel.y = 8;
self.placeholderLabel.width = self.width - 2*self.placeholderLabel.x;
// 自適應(yīng)
[self.placeholderLabel sizeToFit];
}
- (void)textDidChange:(NSNotification *)note{
// 是否隱藏
self.placeholderLabel.hidden = self.hasText;
}
// 移除監(jiān)聽者
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)setPlaceholderColor:(UIColor *)placeholderColor{
self.placeholderLabel.textColor = placeholderColor;
}
#pragma mark ========== 重新計算placeholderLabel的尺寸 =============
- (void)setFont:(UIFont *)font{
[super setFont:font];
self.placeholderLabel.font = self.font;
// 重新布局
[self setNeedsLayout];
}
- (void)setPlaceholder:(NSString *)placeholder{
self.placeholderLabel.text = [placeholder copy];
// 重新布局
[self setNeedsLayout];
}
#pragma mark ========== 隱藏placeholderLabel =============
- (void)setText:(NSString *)text{
[super setText:text];
// 根據(jù)是否有文字來判斷要不要隱藏
self.placeholderLabel.hidden = self.hasText;
}
- (void)setAttributedText:(NSAttributedString *)attributedText{
[super setAttributedText:attributedText];
// 根據(jù)是否有文字來判斷要不要隱藏
self.placeholderLabel.hidden = self.hasText;
}
@end
3.runTime
- 頭文件
#import <objc/runtime.h>
#import <objc/message.h>```
- viewDidLoad
(void)viewDidLoad {
[super viewDidLoad];
// 通過運行時襟衰,發(fā)現(xiàn)UITextView有一個叫做“_placeHolderLabel”的私有變量
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([UITextView class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *objcName = [NSString stringWithUTF8String:name];
NSLog(@"%d : %@",i,objcName);
}
[self setupTextView];
}```setupTextView
- (void)setupTextView{
// 提示文字
CGFloat margin = 15;
UILabel *tipLabel = [[UILabel alloc] initWithFrame:CGRectMake(margin, 0, MGSCREEN_width - 2 * margin, 50)];
tipLabel.text = @"你的批評和建議能幫助我們更好的完善產(chǎn)品,請留下你的寶貴意見!";
tipLabel.numberOfLines = 2;
tipLabel.textColor = MGRGBColor(255, 10, 10);
tipLabel.font = MGFont(16);
[self.view addSubview:tipLabel];
// 意見輸入框
CGFloat height = 200;
#ifndef __IPHONE_4_0
height = 100;
#endif
UITextView *iderTextView = [[UITextView alloc] initWithFrame:CGRectMake(margin, CGRectGetMaxY(tipLabel.frame) + margin, MGSCREEN_width - 2 * margin, height)];
iderTextView.backgroundColor = [UIColor whiteColor];
iderTextView.scrollEnabled = YES;
iderTextView.scrollsToTop = YES;
iderTextView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
// iderTextView.delegate = self;
self.iderTextView = iderTextView;
[self.view addSubview:iderTextView];
// _placeholderLabel
UILabel *placeHolderLabel = [[UILabel alloc] init];
placeHolderLabel.text = @"請輸入寶貴意見(300字以內(nèi))";
placeHolderLabel.numberOfLines = 0;
placeHolderLabel.font = [UIFont systemFontOfSize:14];
placeHolderLabel.textColor = [UIColor lightGrayColor];
[placeHolderLabel sizeToFit];
[iderTextView addSubview:placeHolderLabel];
[iderTextView setValue:placeHolderLabel forKey:@"_placeholderLabel"];
iderTextView.font = placeHolderLabel.font;
}
補充:一種最簡單的實現(xiàn)占位文字的textView(該方法有點投機取巧)
- viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
// 意見輸入
myTextView=[[UITextView alloc] initWithFrame:(CGRectMake(10, 33, kScreenWidth-20, 130))];
myTextView.font=kFont(15);
myTextView.delegate=self;
myTextView.backgroundColor=self.view.backgroundColor;
ViewBorderRadius(myTextView, 0, 0.5f, kGray);
myTextView.textColor=kGray;
myTextView.text=@" 請輸入詳細(xì)描述";
myTextView.tintColor=kWhite;
[self.view addSubview:myTextView];
// 提交
UIButton *feedBtn=[UIButton buttonWithType:(UIButtonTypeCustom)];
feedBtn.frame=CGRectMake(100, myTextView.tail+40, kScreenWidth-200, 40);
[feedBtn addTarget:self action:@selector(feedBtnHandled:) forControlEvents:(UIControlEventTouchUpInside)];
[feedBtn setTitle:@"提交" forState:(UIControlStateNormal)];
[feedBtn setTitleColor:[UIColor whiteColor] forState:(UIControlStateNormal)];
feedBtn.titleLabel.font=kFont(18);
feedBtn.backgroundColor=naBarTiniColor;
[self.view addSubview:feedBtn];
}```
- UITextViewDelegate
(void)textViewDidBeginEditing:(UITextView *)textView{
if([textView.text isEqualToString:@" 請輸入詳細(xì)描述"]){
textView.text=@"";
textView.textColor=kWhite;
}
}-
(void)textViewDidEndEditing:(UITextView *)textView{
if([textView.text isEmptyString]){
textView.text=@" 請輸入詳細(xì)描述"; textView.textColor=kGray;
}
}
![未輸入時](http://upload-images.jianshu.io/upload_images/1429890-73a3f245a9ced10a.PNG)
![UITextView成為第一響應(yīng)者時](http://upload-images.jianshu.io/upload_images/1429890-10b06997fb7af974.PNG)
***