自定义UITextField达到你要的效果
在项目过程中,你的登录界面的UITextField用系统自带的已经不能满足HR的要求,光标需要其他颜色,placeholder需要别的颜色,点击后placeholder的颜色要改变,这些属性的改变是自定义的UITextField才能完成的。下面来介绍一些修改UITextField一些属性的方法。当然,首先你得创建一个继承UITextField的类,然后我们才能在类中写方法。
如果你只是想要修改一点点地方,又不喜欢用自定义,那么可以用下面的方法,当然下面的方法局限性挺大的,不如自定义的功能强大。
// 文字属性,直接修改全部placeholder的文字颜色 NSMutableDictionary *attrs = [NSMutableDictionary dictionary]; attrs[NSForegroundColorAttributeName] = [UIColor grayColor]; // NSAttributedString : 带有属性的文字(富文本技术) NSAttributedString *placeholder = [[NSAttributedString alloc] initWithString:@"手机号" attributes:attrs]; self.textField.attributedPlaceholder = placeholder; // 可以给每一个文字都修改颜色 NSMutableAttributedString *placehoder = [[NSMutableAttributedString alloc] initWithString:@"手机号"]; [placehoder setAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} range:NSMakeRange(0, 1)]; [placehoder setAttributes:@{ NSForegroundColorAttributeName : [UIColor yellowColor], NSFontAttributeName : [UIFont systemFontOfSize:30] } range:NSMakeRange(1, 1)]; [placehoder setAttributes:@{NSForegroundColorAttributeName : [UIColor redColor]} range:NSMakeRange(2, 1)]; self.phoneField.attributedPlaceholder = placehoder;
如果只是修改placeholder的文字颜色,你用xib的设置的话那就在awakeFromXib方法中用setValue:forKeyPath: 这种方法来修改placeholder的文字颜色。如果是纯代码,那就在初始化方法中实现。xib的话,需要让UITextField继承你自定义的textField。
还能设置光标的颜色,默认是蓝色的。
- (void)awakeFromNib { UILabel *placeholderLabel = [self valueForKeyPath:@"_placeholderLabel"]; placeholderLabel.textColor = [UIColor redColor]; // 设置光标颜色和文字颜色一致 self.tintColor = self.textColor; }
但是高亮状态下的我们还没有写,既然 TA 有聚焦(高亮)状态,那么应该有一个方法有可以设置highlighted。
下面代码的确可以实现聚焦状态下文字颜色改变,但是改变后就改变不回来了。
- (void)setHighlighted:(BOOL)highlighted { // 修改placeholder(占位)文字颜色 [self setValue:self.textColor forKeyPath:@"_placeholderLabel.textColor"]; }
既然这样不能改回来,那我们就可以重写成为第一响应者与放弃第一响应者的方法。
// 建议定义这样,使用方便 static NSString * const SQPlacerholderColorKeyPath = @"_placeholderLabel.textColor"; /* ** 修改一下这个方法 */ - (void)awakeFromNib { // UILabel *placeholderLabel = [self valueForKeyPath:@"_placeholderLabel"]; // placeholderLabel.textColor = [UIColor redColor]; // 不成为第一响应者 [self resignFirstResponder]; // 设置光标颜色和文字颜色一致 self.tintColor = self.textColor; } /** * 当前文本框聚焦时就会调用 */ - (BOOL)becomeFirstResponder { // 修改placeholder(占位)文字颜色 [self setValue:self.textColor forKeyPath:SQPlacerholderColorKeyPath]; return [super becomeFirstResponder]; } /** * 当前文本框失去焦点时就会调用 */ - (BOOL)resignFirstResponder { // 修改placeholder(占位)文字颜色 [self setValue:[UIColor grayColor] forKeyPath:SQPlacerholderColorKeyPath]; return [super resignFirstResponder]; }
利用上面的这个方法,就可以实现UITextField你想要的效果了。但是UITextField的成员变量我们是看不到的,这个时候我们就可以用runtime来查看到底有哪些成员变量,这样我们就可以用setValue:forKeyPath: 来赋值了。想要使用runtime我们需要导入一个头文件 #import <objc/runtime.h> ,下面有两个方法,可以访问成员变量跟属性。
/** * 运行时(Runtime):苹果官方一套C语言库 能做很多底层操作(比如访问隐藏的一些成员变量\成员方法...) */ + (void)getProperties { unsigned int count = 0; objc_property_t *properties = class_copyPropertyList([UITextField class], &count); for (int i = 0; i < count; i++) { // 取出属性 objc_property_t property = properties[i]; // 打印属性名字 SQLog(@"%s", property_getName(property)); // 打印属性类型 SQLog(@"%s",property_getAttributes(property)); } free(properties); } - (void)getIvars { unsigned int count = 0; // 拷贝出所有的成员变量列表 Ivar *ivars = class_copyIvarList([UITextField class], &count); for (int i = 0; i < count; i++) { // 取出成员变量 // Ivar ivar = *(ivars + i); Ivar ivar = ivars[i]; // 打印成员变量名字 SQLog(@"%s", ivar_getName(ivar)); } // 释放 free(ivars); }
runtime其实有很多的方法,这里就介绍这么点,想要了解更多,可以查看官方文档,里面有详细的介绍,网上也有已经翻译好的中文文档,因为这个比较重要,翻译的比较好,当然这里没有传送门。