textField修改占位文字的方案共有3种:
- 方案一:富文本(给textField的attributedText属性赋值)
/*在textField的自定义控件中*/
#import "ZGKTextField.h"
@implementation ZGKTextField
- (void)awakeFromNib{
[super awakeFromNib];
// 0.设置光标颜色
self.tintColor = [UIColor whiteColor];
// 0.设置输入文字颜色
self.textColor = [UIColor redColor];
// 1.设置占位文字颜色
// 1.1 设置文字属性(不可变富文本NSAttributedString)
// self.placeholder = @"占位文字";
/**** attributedPlaceholder的优先级比palceholder的高 ****/
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
/**** attributes的key都在NSAttributedString.h文件里面 ****/
/*
设置占位文字为黄色
设置背景颜色为紫色
*/
attributes[NSForegroundColorAttributeName] = [UIColor whiteColor];
// attributes[NSBackgroundColorAttributeName] = [UIColor purpleColor];
/**** 将布尔类型包装成对象 ****/
// attributes[NSUnderlineStyleAttributeName] = @YES;
/**** self.placeholder xib设置的占位文字 ****/
NSAttributedString *attributedStr = [[NSAttributedString alloc] initWithString:self.placeholder attributes:attributes];
// 1.2给占位文字赋值(可以是palceholder或者attributedPlacedholder)
self.attributedPlaceholder = attributedStr;
// // 2.设置文字属性(可变富文本NSMutableAttributedString)
// NSMutableAttributedString *mutableAttriStr = [[NSMutableAttributedString alloc] initWithString:self.placeholder];
// NSMutableDictionary *attributes2 = [NSMutableDictionary dictionary];
// attributes2[NSForegroundColorAttributeName] = [UIColor greenColor];
// // 不同属性进行富文本格式的叠加
// [mutableAttriStr addAttributes:attributes range:NSMakeRange(0, 1)];
// [mutableAttriStr addAttributes:attributes2 range:NSMakeRange(1, 1)];
// // 这个才有效
// [mutableAttriStr setAttributes:attributes2 range:NSMakeRange(0, 1)];
// self.attributedPlaceholder = mutableAttriStr;
// 3.设置默认输入文字(xib设置了,所以此处不用设置)
self.attributedText = [[NSAttributedString alloc] initWithString:@"" attributes:nil];
}
总结:
1.textField的属性attributedPlaceholder的优先级比placeholder的高,所以设置带有属性的占位文字即可改变占位文字的大小和颜色
2.textField的属性attributedPlaceholder可以设置不可变富文本NSAttributedString,也可以设置可变富文本NSMutableAttributedString,可变富文本可以设置多个Attributes属性
// 2.设置文字属性(可变富文本NSMutableAttributedString)
NSMutableAttributedString *mutableAttriStr = [[NSMutableAttributedString alloc] initWithString:self.placeholder];
NSMutableDictionary *attributes2 = [NSMutableDictionary dictionary];
attributes2[NSForegroundColorAttributeName] = [UIColor greenColor];
// 不同属性进行富文本格式的叠加
[mutableAttriStr addAttributes:attributes range:NSMakeRange(0, 1)];
[mutableAttriStr addAttributes:attributes2 range:NSMakeRange(1, 1)];
// 这个才有效
[mutableAttriStr setAttributes:attributes2 range:NSMakeRange(0, 1)];
self.attributedPlaceholder = mutableAttriStr;
3.富文本的addAttributes:方法和setAttributes:方法是不同的,前者可以叠加,后者是set方法,只能有一个值,不能叠加属性.
- 方案二:重写textField的- (void)drawPlaceholderInRect:(CGRect)rect方法
#pragma mark - 重写
/**** 先调用 ****/
// 该方法控制占位文字的大小和位置
// bounds是默认的占位文字的bounds
- (CGRect)placeholderRectForBounds:(CGRect)bounds{
// textField默认的rect==bounds
NSLog(@"%@", NSStringFromCGRect(bounds));
// 在这里修改占位文字的大小和位置
// return CGRectMake(0, 0, 60, 10);
return bounds;
}
/**** 后调用 ****/
// 该方法控制占位文字的格式及大小和位置
// ===>rect是上面方法传入的rect,上面方法修改了rect,则这个方法传入的rect也会改变
- (void)drawPlaceholderInRect:(CGRect)rect{
NSLog(@"2---%@", NSStringFromCGRect(rect));
// 0.rect
CGRect placeholderRect;
placeholderRect.size.width = rect.size.width;
/**** self.font是占位文字或者光标文字的字体大小,lineHeight用于计算字体的行高 ****/
placeholderRect.size.height = self.font.lineHeight;
placeholderRect.origin.x = 0;
placeholderRect.origin.y = (rect.size.height - self.font.lineHeight) * 0.5;
// 1.attributes
NSMutableDictionary *attriDict = [NSMutableDictionary dictionary];
/**** 字体大小和xib的字体大小要一致,不然self.font.lineHeight计算行高就不管用了 ****/
attriDict[NSFontAttributeName] = [UIFont systemFontOfSize:14];
attriDict[NSForegroundColorAttributeName] = [UIColor blueColor];
// 2.1 drawInRect
// [self.placeholder drawInRect:placeholderRect withAttributes:attriDict];
// 2.1 drawInPoint
// [self.placeholder drawAtPoint:CGPointMake(0, 0) withAttributes:attriDict];
[self.placeholder drawAtPoint:CGPointMake(0, placeholderRect.origin.y) withAttributes:attriDict];
}
特别注意:
1.运行时,程序会先执行- (CGRect)placeholderRectForBounds:(CGRect)bounds方法,后执行- (void)drawPlaceholderInRect:(CGRect)rect方法,前者是修改占位文字的大小和位置的,不修改则为默认的bounds.后者是重绘占位文字,可以用drawInRect或者drawAtPoint方法,该方法传入的rect是前者返回的值.
- 方案三:运行时通过KVC, 给textFiled的placeholderLabel.textColor赋值
#import "ZGKTextField.h"
#import
@implementation ZGKTextField
- (void)awakeFromNib{
[super awakeFromNib];
// 0.设置光标颜色
self.tintColor = [UIColor whiteColor];
// 0.设置输入文字颜色
self.textColor = [UIColor redColor];
// 方法3:(从子控件入手)
/**** ******************************************************************** ****/
// 1.因为占位文字在没有输入时,一直存在, 一输入字,占位文字就会消失,所以我们猜测占位文字是UITextField的一个子控件(可以输入文字,并用调试小面包来观察)
// 直接打印,并不能打印出子控件
// NSLog(@"textField的子控件---%@", self.subviews);
// 2.直接打印,因为从xib加载textField时,textField内部的自控件可能还没有添加,因为延迟打印看看
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 1.打印子控件
// NSLog(@"textField的子控件---%@", self.subviews);
// 2.通过上面打印发现:textField只有一个子控件,因此将他的类型打印出来
NSLog(@"textField的子控件---%@", [self.subviews.lastObject class]);
// 3.取出UITextFieldLabel,给其的textColor属性赋值就可以改变占位文字的颜色
// UITextFieldLabel是私有类,不能用,所以只能找他的父类
// UITextFieldLabel *textFieldLabel = self.subviews.lastObject;
// 4.找到 UITextFieldLabel的父类是UILabel(父类:superclass, 父控件:superview)
NSLog(@" UITextFieldLabel.superView = %@", self.subviews.lastObject.superclass);
/*
2017-01-29 00:25:10.846 MyProject[4298:201733] textField的子控件---UITextFieldLabel
2017-01-29 00:25:10.847 MyProject[4298:201733] UITextFieldLabel.superView = UILabel
*/
// 5.多态, 用父类来接收子类对象,并改变对象的属性值
UILabel *textFieldLabel = self.subviews.lastObject;
// 验证第四种方法,所以要注释掉,因为是延迟0.1秒执行的
// textFieldLabel.textColor = [UIColor whiteColor];
});
// 上述方法的弊端:
/*
// 2017-01-29 00:57:33.584 MyProject[4557:217054] textField的子控件---(null)
// 2017-01-29 00:57:33.584 MyProject[4557:217054] UITextFieldLabel.superView = (null)
2017-01-29 00:57:33.628 MyProject[4557:217054] textField的子控件---UITextFieldLabel
2017-01-29 00:57:33.628 MyProject[4557:217054] UITextFieldLabel.superView = UILabel
2017-01-29 00:57:33.661 MyProject[4557:217054] textField的子控件---UITextFieldLabel
2017-01-29 00:57:33.662 MyProject[4557:217054] UITextFieldLabel.superView = UILabel
2017-01-29 00:57:33.671 MyProject[4557:217054] textField的子控件---UITextFieldLabel
2017-01-29 00:57:33.672 MyProject[4557:217054] UITextFieldLabel.superView = UILabel
*/
// 1.不知道什么时候textfield才添加了子控件UITextFieldLabel,只能一定时间以后才执行,延迟执行的时间不好控制
// 2.该控件不像控制器,可以在viewWillAppear方法中做事情
// 3.通过数组(self.subviews)去拿对象也不靠谱,本案例中,刚好只有一个子控件UITextFieldLabel,如果有多个子控件,则不能用lastObject去取
/**** ******************************************************************** ****/
// 方法4:(从属性入手)
/**** ******************************************************************** ****/
// 1.1.因为占位文字在没有输入时,一直存在, 一输入字,占位文字就会消失,所以我们猜测TextField里面有个属性强引用UITextfieldLabel,所以我们可以用kvc去赋值(无论是公共属性还是私有属性)
// UILabel *label = [self valueForKeyPath:@"placeholderLabel"];
// label.textColor = [UIColor yellowColor];
//
/**** ******************************************************************** ****/
// 方法5:(相比方法3和4,推荐使用方法5:从属性入手)
/**** ******************************************************************** ****/
// 1.1 因为方法4中,我们可能无法得知是哪个属性强引用UITextfieldLabel,所以我们可以用运行时方法来找出相关属性名
// 2.获取属性列表
// c语言
unsigned int count;
// ivarList是指针,指向数组, 传入的参数是指针&count
Ivar *ivarList = class_copyIvarList([UITextField class], &count);
// 3.打印属性列表
for (int i= 0; i< count; i++) {
Ivar ivar = ivarList[i];
/*
2017-01-29 00:55:40.856 MyProject[4520:215206] 属性列表31---_placeholderLabel
*/
NSLog(@"属性列表%d---%s", i, ivar_getName(ivar));
}
// 4.释放指针
free(ivarList);
// 4.设置占位文字的颜色为绿色
[self setValue:[UIColor greenColor] forKeyPath:@"placeholderLabel.textColor"];
}