iPhone UITextField - 更改占位符文本颜色

596

我想改变我在UITextField控件中设置的占位文本的颜色,让它变成黑色。

我希望能够不使用常规文本作为占位符,并且无需覆盖所有方法来模仿占位符的行为。

我相信如果我覆盖这个方法:

- (void)drawPlaceholderInRect:(CGRect)rect

那么我应该能够这样做。但我不确定如何从这个方法中访问实际的占位符对象。

32个回答

817

自从iOS 6引入了UIView中的属性字符串,就可以像这样为占位符文本分配颜色:

if ([textField respondsToSelector:@selector(setAttributedPlaceholder:)]) {
  UIColor *color = [UIColor blackColor];
  textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:placeholderText attributes:@{NSForegroundColorAttributeName: color}];
} else {
  NSLog(@"Cannot set placeholder text's color, because deployment target is earlier than iOS 6.0");
  // TODO: Add fall-back code to set placeholder color.
}

2
这很好 - 但请记住,在此之前,您需要在IB中设置占位符值才能使其工作。 - gheese
4
值得一提的是,在进行iOS开发时,建议将这段代码包裹在一个respondsToSelector调用中。如果不这样做,在部署目标版本低于6.0的情况下,该代码将会导致崩溃(未识别的选择器发送到实例)。 - gheese
5
attributedPlaceholder的文档表明它使用文本属性,除了颜色。 - Matt Connolly
1
有没有想法为什么 NSFontAttributeName 属性无法正常工作?[[NSAttributedString alloc] initWithString:@"placeholder" attributes: @{NSForegroundColorAttributeName: color, NSFontAttributeName : font}]; - dev4u
3
在iOS 7上,我遇到了这个错误:[<UITextField 0x11561d90> valueForUndefinedKey:]:该类不支持键值编码_compliant for the key _field. - i_am_jorf
显示剩余11条评论

239

易于操作且无痛苦,可能是某些人的简便选择。

_placeholderLabel.textColor

不建议在生产环境中使用,因为苹果可能会拒绝您的提交。



1
你是在生产环境中使用这个吗?我的意思是访问一个私有属性。 - Geri Borbás
11
_placeholderLabel.textColor:可能将文本添加到您的答案中以快速复制和粘贴。 - Philiiiiiipp
55
不要使用这种方法,我曾尝试使用它并在iTunes Store中被拒绝了申请。 - Asad ali
1
我认为任何类型的私有库方法都不应该被推荐作为解决方案。 - Skrew
2
@jungledev _placeholderLabel 是一个私有属性。使用私有 API 可能会导致该解决方案被拒绝。 - Sean Kladek
显示剩余6条评论

196

你可以通过如下方式覆盖 drawPlaceholderInRect:(CGRect)rect 方法来手动渲染占位符文本:

- (void) drawPlaceholderInRect:(CGRect)rect {
    [[UIColor blueColor] setFill];
    [[self placeholder] drawInRect:rect withFont:[UIFont systemFontOfSize:16]];
}

45
类似于[self.placeholder drawInRect:rect withFont:self.font lineBreakMode:UILineBreakModeTailTruncation alignment:self.textAlignment]; 这样的写法可能更好。这样可以尊重 textAlignment 属性。我已经将其添加到我的 SSTextField 类中,欢迎在您的项目中使用。 - Sam Soffes
53
绝对不要按照Koteg所说的做。永远不要通过分类覆盖方法,无论何时。 - Joshua Weinberg
8
有没有具体的原因促使您提出这个建议,@JoshuaWeinberg? - RK-
5
在一个类别中实现重复方法是不被支持的,你无法确定哪个方法会被调用,或者两个都会被调用,以及它们被调用的顺序。 - sean woodward
8
在iOS7中,您可以使用CGRectInset(rect,0,(rect.size.height - self.font.lineHeight)/ 2.0)来更改矩形以使文本垂直居中,而不会改变原始含义。 - Brian S
显示剩余4条评论

181

在Swift <3.0中可行:

myTextField.attributedPlaceholder = 
NSAttributedString(string: "placeholder text", attributes: [NSForegroundColorAttributeName : UIColor.redColor()])

iOS 8.2和iOS 8.3 beta 4中测试通过。

Swift 3:

myTextfield.attributedPlaceholder =
NSAttributedString(string: "placeholder text", attributes: [NSForegroundColorAttributeName : UIColor.red])

Swift 4:

myTextfield.attributedPlaceholder =
NSAttributedString(string: "placeholder text", attributes: [NSAttributedStringKey.foregroundColor: UIColor.red])

Swift 4.2:

myTextfield.attributedPlaceholder =
NSAttributedString(string: "placeholder text", attributes: [NSAttributedString.Key.foregroundColor: UIColor.red])

在iOS8.2上使用您的解决方案,效果非常好。这是完美的解决方案。也在使用Objective C。 - Akshit Zaveri

175

您可以使用以下代码将占位符文本颜色更改为任何颜色。

UIColor *color = [UIColor lightTextColor];
YOURTEXTFIELD.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"PlaceHolder Text" attributes:@{NSForegroundColorAttributeName: color}];

6
最佳答案建议。起作用,使用记录的API。 - Ian Hoar
2
你如何让它适用于UISearchBar?没有attributedPlaceholder属性。 - gilsaints88
1
这个答案是不正确的 - 根据文档,attributedPlaceholder 的文本颜色信息将会被忽略。https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextField_Class/index.html#//apple_ref/occ/instp/UITextField/attributedPlaceholder - Adlai Holler
在iOS8上无法正常工作,因为没有attributedPlaceholder属性。 - Ben Clayton
适用于iOS 12。 - user5306470
显示剩余3条评论

157

也许你想尝试这种方法,但是苹果可能会警告你访问私有的ivar:

[self.myTextField setValue:[UIColor darkGrayColor] 
                forKeyPath:@"_placeholderLabel.textColor"];

注意
根据Martin Alléus的说法,这在iOS 7上不再起作用。


6
我在我的应用程序中使用这种方法。审核通过了。因此我认为使用它是可以的。 - Michael A.
9
这并不是应用商店认可的安全做法,不建议采用这些技巧,因为不能保证您的应用能够被批准或保持已批准状态。 - Sveinung Kval Bakken
32
是否获得批准并不是真正重要的。重要的是,未来操作系统更新可能会导致您的应用程序出现故障。 - pablasso
2
尽管有注释,我在iOS 7上没有任何问题...我尝试了一下,似乎运行良好。我以前也用过这种方法,没有出现任何问题。 - WCByrne
6
这始终都是个不好的想法,现在在iOS 13上已经出了问题:访问UITextField的_placeholderLabel ivar是被禁止的。这是一个应用程序错误。 - Ryder Mackay
显示剩余10条评论

94

Swift 3.0 + Storyboard

为了在Storyboard中更改占位符的颜色,请创建一个扩展并使用以下代码(如果您认为可以使代码更清晰和安全,请随意更新此代码)。

extension UITextField {
    @IBInspectable var placeholderColor: UIColor {
        get {
            guard let currentAttributedPlaceholderColor = attributedPlaceholder?.attribute(NSForegroundColorAttributeName, at: 0, effectiveRange: nil) as? UIColor else { return UIColor.clear }
            return currentAttributedPlaceholderColor
        }
        set {
            guard let currentAttributedString = attributedPlaceholder else { return }
            let attributes = [NSForegroundColorAttributeName : newValue]

            attributedPlaceholder = NSAttributedString(string: currentAttributedString.string, attributes: attributes)
        }
    }
}

在此输入图像描述

Swift 4 版本

extension UITextField {
    @IBInspectable var placeholderColor: UIColor {
        get {
            return attributedPlaceholder?.attribute(.foregroundColor, at: 0, effectiveRange: nil) as? UIColor ?? .clear
        }
        set {
            guard let attributedPlaceholder = attributedPlaceholder else { return }
            let attributes: [NSAttributedStringKey: UIColor] = [.foregroundColor: newValue]
            self.attributedPlaceholder = NSAttributedString(string: attributedPlaceholder.string, attributes: attributes)
        }
    }
}

Swift 5 版本

extension UITextField {
    @IBInspectable var placeholderColor: UIColor {
        get {
            return attributedPlaceholder?.attribute(.foregroundColor, at: 0, effectiveRange: nil) as? UIColor ?? .clear
        }
        set {
            guard let attributedPlaceholder = attributedPlaceholder else { return }
            let attributes: [NSAttributedString.Key: UIColor] = [.foregroundColor: newValue]
            self.attributedPlaceholder = NSAttributedString(string: attributedPlaceholder.string, attributes: attributes)
        }
    }
}

编译器找不到 NSAttributedStringKey - Milan Kamilya
适用于iOS 13。 - Jalil

78

在 Swift 中:

if let placeholder = yourTextField.placeholder {
    yourTextField.attributedPlaceholder = NSAttributedString(string:placeholder, 
        attributes: [NSForegroundColorAttributeName: UIColor.blackColor()])
}

在 Swift 4.0 中:

if let placeholder = yourTextField.placeholder {
    yourTextField.attributedPlaceholder = NSAttributedString(string:placeholder, 
        attributes: [NSAttributedStringKey.foregroundColor: UIColor.black])
}

如果在调用之前没有设置占位符文本,它将会导致应用程序崩溃。 - apinho
这是最好的,谢谢。@apinho 这里不会崩溃。 - Markus
//在Swift 4中 如果let占位符 = yourTextField.placeholder { yourTextField.attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [NSAttributedStringKey.foregroundColor: UIColor.white]) } - Ronaldo Albertini
请注意,在执行此代码后更改占位符文本值将会恢复默认的占位符颜色。 - Alessandro Vendruscolo

43

以下仅适用于iOS6+(如Alexander W的评论中所示):

UIColor *color = [UIColor grayColor];
nameText.attributedPlaceholder =
   [[NSAttributedString alloc]
       initWithString:@"Full Name"
       attributes:@{NSForegroundColorAttributeName:color}];

36

我已经遇到过这个问题。在我的情况下,以下代码是正确的。

Objective C

[textField setValue:[UIColor whiteColor] forKeyPath:@"_placeholderLabel.textColor"];

适用于 Swift 4.X

tf_mobile.setValue(UIColor.white, forKeyPath: "_placeholderLabel.textColor")

针对iOS 13的Swift代码

tf_mobile.attributedPlaceholder = NSAttributedString(string:"PlaceHolder Text", attributes: [NSAttributedString.Key.foregroundColor: UIColor.red])

您也可以使用以下代码适用于iOS 13

let iVar = class_getInstanceVariable(UITextField.self, "_placeholderLabel")!
let placeholderLabel = object_getIvar(tf_mobile, iVar) as! UILabel
placeholderLabel.textColor = .red

希望这能对你有所帮助。


1
@Ashu,这会导致iOS 13崩溃:“访问UITextField的_placeholderLabel ivar是被禁止的。这是一个应用程序错误”,甚至无法构建,我不是在谈论放置到AppStore中。 - Melany
2
IOS 13已被限制,无法再使用。 - Kishore Kumar
1
@Mehdico,我已经更新了iOS 13的答案。希望这能帮到你。 - Ashu
我花了太长时间才意识到我必须在viewWillAppearviewDidAppear中进行这个更改。viewDidLoad太早了。 - Four
我不得不使用UIColor(displayP3Red: 255, green: 255, blue: 255, alpha: 0.3)构造函数来代替UIColor(red: 255, green: 255, blue: 255, alpha: 0.3) - AppreciateIt
如果出现崩溃,请使用placeholderLabel属性。 - Aaban Tariq Murtaza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接