知识点总结13:textField占位文字的颜色的修改

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"];
 }

你可能感兴趣的:(知识点总结13:textField占位文字的颜色的修改)