最终设置UITextField的placeholder效果(实际效果可能比这好一点点...):
有需求1如下:
- 未点击时UITextField的placeholder为浅灰色
- 点击后,还未进行输入时,UITextField的placeholder变为深灰色
这个实现并不难:
- 通过通知或者重写UITextField的响应者处理方法(becomeFirstResponder/resignFirstResponder),都可以实现捕获点击时间
- UITextField设置placeholder可以使用以下属性:
- 通过设置这个富文本属性,可以得到丰富多彩的placeholder
- 通过设置这个富文本属性,可以得到丰富多彩的placeholder
@NSCopying var attributedPlaceholder: NSAttributedString?
// 附带光标颜色属性
var tintColor: UIColor!
但是需求2加了点东西:
- 点击后,还未进行输入时,UITextField的placeholder文字左右进行小幅度抖动
可以看到通过设置attributedPlaceholder,可以改变一些静态的属性,如颜色和文字大小。
但是如果需要里面的文字做一些简单的抖动效果貌似就不行了,UITextField没有提供相关属性,我们也不知道placeholder是在何种控件中显示的。
既然不知道placeholder是在何种控件中显示,那就通过以下代码打印出UITextField中所有的成员变量(函数参考runtime基础元素解析),看看是否会有什么发现:
Ivar *ivars = class_copyIvarList([UITextField class], &outCount);
for (int i = 0; i < outCount; i++) {
Ivar ivar = ivars[i];
NSLog(@"%s", ivar_getName(ivar));
}
free(ivars);
截取关键部分如下:
从字面上看,上面的
_placeholderLabel
是否就是显示placeholder的控件?测试实际结果的确是显示placeholder的控件。
只要有了这个控件,那要做一些小抖动的动画那就没什么问题了,先获取这个UILabel:
private var tpcPlaceholderLabel:UILabel? {
get {
return self.valueForKey("_placeholderLabel") as? UILabel
}
}
然后重写UITextField的响应者处理函数:
// 成为第一响应者
override func becomeFirstResponder() -> Bool {
if normalColor == nil {
normalColor = tpcPlaceholderLabel?.textColor
}
if selectedColor == nil {
selectedColor = tpcPlaceholderLabel?.textColor
}
tpcPlaceholderLabel?.textColor = selectedColor
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.1, initialSpringVelocity: 10, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in
tpcPlaceholderLabel?.transform = CGAffineTransformMakeTranslation(10, 0)
}, completion: nil)
return super.becomeFirstResponder()
}
// 放弃第一响应者
override func resignFirstResponder() -> Bool {
tpcPlaceholderLabel?.transform = CGAffineTransformIdentity
tpcPlaceholderLabel?.textColor = normalColor
return super.resignFirstResponder()
}
这样就可以做简单的抖动了
还有一点,根据上面打印的UITextField成员变量,看到了_displayLabel
,这个就是在键盘输入后显示文字的UILabel了。这个属性可以用来干嘛?
我想,可能会有这么一种需求(不过可能没有),就是用户输入错误时,UITextField中已经输入的文字做简单左右抖动,并且颜色变为红色,以间接的形式,辅助提醒用户,这一栏输错了,而不是弹出一个HUB
。
由于UITextField内部做了某些处理,所以无法在成为第一响应者时做一些动作,那么,就在放弃第一响应者函数中。
相关代码如下:
// 设置一个在放弃第一响应者调用的闭包属性
var operateWhenResignFirstResponder: (() -> ())?
// 在func resignFirstResponder() -> Bool函数中调用
if let operate = operateWhenResignFirstResponder {
operate()
}