【发布时间】:2010-11-23 08:05:50
【问题描述】:
我想更改我在UITextField 控件中设置的占位符文本的颜色,使其变为黑色。
我宁愿这样做,而不使用普通文本作为占位符,并且不必重写所有方法来模仿占位符的行为。
我相信如果我重写这个方法:
- (void)drawPlaceholderInRect:(CGRect)rect
那么我应该能够做到这一点。但我不确定如何从这个方法中访问实际的占位符对象。
【问题讨论】:
标签: ios uitextfield
我想更改我在UITextField 控件中设置的占位符文本的颜色,使其变为黑色。
我宁愿这样做,而不使用普通文本作为占位符,并且不必重写所有方法来模仿占位符的行为。
我相信如果我重写这个方法:
- (void)drawPlaceholderInRect:(CGRect)rect
那么我应该能够做到这一点。但我不确定如何从这个方法中访问实际的占位符对象。
【问题讨论】:
标签: ios uitextfield
自从在 iOS 6 中的 UIViews 中引入了属性字符串,可以像这样为占位符文本分配颜色:
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.
}
【讨论】:
attributedPlaceholder 的文档说它使用文本属性,除了颜色。
[[NSAttributedString alloc] initWithString:@"placeholder" attributes: @{NSForegroundColorAttributeName: color, NSFontAttributeName : font}];
[<UITextField 0x11561d90> valueForUndefinedKey:]: this class is not key value coding-compliant for the key _field.
简单无痛,对某些人来说可能是一种简单的选择。
_placeholderLabel.textColor
不建议用于生产,Apple 可能会拒绝您的提交。
【讨论】:
_placeholderLabel 是私有财产。此解决方案可能会因使用私有 API 而被拒绝。
您可以像这样覆盖drawPlaceholderInRect:(CGRect)rect 以手动呈现占位符文本:
- (void) drawPlaceholderInRect:(CGRect)rect {
[[UIColor blueColor] setFill];
[[self placeholder] drawInRect:rect withFont:[UIFont systemFontOfSize:16]];
}
【讨论】:
[self.placeholder drawInRect:rect withFont:self.font lineBreakMode:UILineBreakModeTailTruncation alignment:self.textAlignment]; 之类的可能更好。这样你就会尊重textAlignment 属性。我已将此添加到我的SSTextField 课程中。随意在您的项目中使用。
您可以使用以下代码将占位符文本颜色更改为您想要的任何颜色。
UIColor *color = [UIColor lightTextColor];
YOURTEXTFIELD.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"PlaceHolder Text" attributes:@{NSForegroundColorAttributeName: color}];
【讨论】:
这适用于 Swift
myTextField.attributedPlaceholder =
NSAttributedString(string: "placeholder text", attributes: [NSForegroundColorAttributeName : UIColor.redColor()])
在 iOS 8.2 和 iOS 8.3 beta 4 中测试。
斯威夫特 3:
myTextfield.attributedPlaceholder =
NSAttributedString(string: "placeholder text", attributes: [NSForegroundColorAttributeName : UIColor.red])
斯威夫特 4:
myTextfield.attributedPlaceholder =
NSAttributedString(string: "placeholder text", attributes: [NSAttributedStringKey.foregroundColor: UIColor.red])
斯威夫特 4.2:
myTextfield.attributedPlaceholder =
NSAttributedString(string: "placeholder text", attributes: [NSAttributedString.Key.foregroundColor: UIColor.red])
【讨论】:
也许您想尝试这种方式,但 Apple 可能会警告您访问私有 ivar:
[self.myTextField setValue:[UIColor darkGrayColor]
forKeyPath:@"_placeholderLabel.textColor"];
注意
根据 Martin Alléus 的说法,这不再适用于 iOS 7。
【讨论】:
Access to UITextField's _placeholderLabel ivar is prohibited. This is an application bug?
为了更改情节提要中的占位符颜色,请使用下一个代码创建一个扩展。 (请随意更新此代码,如果您认为它可以更清晰,更安全)。
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)
}
}
}
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)
}
}
}
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。
在斯威夫特中:
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])
}
【讨论】:
以下仅适用于 iOS6+(如 Alexander W 的评论所示):
UIColor *color = [UIColor grayColor];
nameText.attributedPlaceholder =
[[NSAttributedString alloc]
initWithString:@"Full Name"
attributes:@{NSForegroundColorAttributeName:color}];
【讨论】:
我已经遇到过这个问题。在我的情况下,下面的代码是正确的。
目标 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
希望对您有所帮助。
【讨论】:
viewWillAppear 或 viewDidAppear 中进行此更改。 viewDidLoad 太早了。
UIColor(displayP3Red: 255, green: 255, blue: 255, alpha: 0.3) 构造函数而不是 UIColor(red: 255, green: 255, blue: 255, alpha: 0.3)
通过这个我们可以改变iOS中textfield的占位符文本的颜色
[self.userNameTxt setValue:[UIColor colorWithRed:41.0/255.0 green:91.0/255.0 blue:106.0/255.0 alpha:1.0] forKeyPath:@"_placeholderLabel.textColor"];
【讨论】:
在 swift 3.X 中
textField.attributedPlaceholder = NSAttributedString(string: "placeholder text", attributes:[NSForegroundColorAttributeName: UIColor.black])
在 Swift 5 中
textField.attributedPlaceholder = NSAttributedString(string: "placeholder text", attributes: [NSAttributedString.Key.foregroundColor : UIColor.black])
【讨论】:
你为什么不直接使用UIAppearance方法:
[[UILabel appearanceWhenContainedIn:[UITextField class], nil] setTextColor:[UIColor whateverColorYouNeed]];
【讨论】:
[textfield setValue:your_color forKeyPath:@"_placeholderLabel.textColor"];
希望对你有帮助。
注意: Apple 可能会拒绝(0.01% 的机会)您的应用,因为我们正在访问私有 API。两年以来,我在所有项目中都使用它,但 Apple 并没有要求这样做。
【讨论】:
terminating with uncaught exception of type NSException
对于 Xamarin.iOS 开发人员,我从这个文档中找到了它 https://developer.xamarin.com/api/type/Foundation.NSAttributedString/
textField.AttributedPlaceholder = new NSAttributedString ("Hello, world",new UIStringAttributes () { ForegroundColor = UIColor.Red });
【讨论】:
new NSAttributedString("placeholderstring", new CTStringAttributes() { ForegroundColor = UIColor.Blue.CGColor });
Swift 版本。可能会对某人有所帮助。
class TextField: UITextField {
override var placeholder: String? {
didSet {
let placeholderString = NSAttributedString(string: placeholder!, attributes: [NSForegroundColorAttributeName: UIColor.whiteColor()])
self.attributedPlaceholder = placeholderString
}
}
}
【讨论】:
iOS 6 及更高版本在UITextField 上提供attributedPlaceholder。
iOS 3.2 及更高版本在NSMutableAttributedString 上提供setAttributes:range:。
您可以执行以下操作:
NSMutableAttributedString *ms = [[NSMutableAttributedString alloc] initWithString:self.yourInput.placeholder];
UIFont *placeholderFont = self.yourInput.font;
NSRange fullRange = NSMakeRange(0, ms.length);
NSDictionary *newProps = @{NSForegroundColorAttributeName:[UIColor yourColor], NSFontAttributeName:placeholderFont};
[ms setAttributes:newProps range:fullRange];
self.yourInput.attributedPlaceholder = ms;
【讨论】:
此解决方案适用于 Swift 4.1
textName.attributedPlaceholder = NSAttributedString(string: textName.placeholder!, attributes: [NSAttributedStringKey.foregroundColor : UIColor.red])
【讨论】:
类别 FTW。可以进行优化以检查有效的颜色变化。
#import <UIKit/UIKit.h>
@interface UITextField (OPConvenience)
@property (strong, nonatomic) UIColor* placeholderColor;
@end
#import "UITextField+OPConvenience.h"
@implementation UITextField (OPConvenience)
- (void) setPlaceholderColor: (UIColor*) color {
if (color) {
NSMutableAttributedString* attrString = [self.attributedPlaceholder mutableCopy];
[attrString setAttributes: @{NSForegroundColorAttributeName: color} range: NSMakeRange(0, attrString.length)];
self.attributedPlaceholder = attrString;
}
}
- (UIColor*) placeholderColor {
return [self.attributedPlaceholder attribute: NSForegroundColorAttributeName atIndex: 0 effectiveRange: NULL];
}
@end
【讨论】:
在 iOS7 中处理垂直和水平对齐以及占位符的颜色。 drawInRect 和 drawAtPoint 不再使用当前上下文填充颜色。
Obj-C
@interface CustomPlaceHolderTextColorTextField : UITextField
@end
@implementation CustomPlaceHolderTextColorTextField : UITextField
-(void) drawPlaceholderInRect:(CGRect)rect {
if (self.placeholder) {
// color of placeholder text
UIColor *placeHolderTextColor = [UIColor redColor];
CGSize drawSize = [self.placeholder sizeWithAttributes:[NSDictionary dictionaryWithObject:self.font forKey:NSFontAttributeName]];
CGRect drawRect = rect;
// verticially align text
drawRect.origin.y = (rect.size.height - drawSize.height) * 0.5;
// set alignment
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.alignment = self.textAlignment;
// dictionary of attributes, font, paragraphstyle, and color
NSDictionary *drawAttributes = @{NSFontAttributeName: self.font,
NSParagraphStyleAttributeName : paragraphStyle,
NSForegroundColorAttributeName : placeHolderTextColor};
// draw
[self.placeholder drawInRect:drawRect withAttributes:drawAttributes];
}
}
@end
【讨论】:
带有警告的 Swift 5。
let attributes = [ NSAttributedString.Key.foregroundColor: UIColor.someColor ]
let placeHolderString = NSAttributedString(string: "DON'T_DELETE", attributes: attributes)
txtField.attributedPlaceholder = placeHolderString
需要注意的是,您必须在“DON'T_DELETE”所在的位置输入非空String,即使该字符串已在其他地方的代码中设置。可能会为您节省五分钟的时间。
【讨论】:
覆盖 drawPlaceholderInRect: 是正确的方法,但由于 API(或文档)中的错误,它不起作用。
永远不会在 UITextField 上调用该方法。
另见drawTextInRect on UITextField not called
您可以使用 digdog 的解决方案。由于我不确定这是否能通过 Apple 的审核,所以我选择了不同的解决方案:用我自己的标签覆盖文本字段,模仿占位符的行为。
这有点乱。 代码如下所示(注意我在 TextField 的子类中执行此操作):
@implementation PlaceholderChangingTextField
- (void) changePlaceholderColor:(UIColor*)color
{
// Need to place the overlay placeholder exactly above the original placeholder
UILabel *overlayPlaceholderLabel = [[[UILabel alloc] initWithFrame:CGRectMake(self.frame.origin.x + 8, self.frame.origin.y + 4, self.frame.size.width - 16, self.frame.size.height - 8)] autorelease];
overlayPlaceholderLabel.backgroundColor = [UIColor whiteColor];
overlayPlaceholderLabel.opaque = YES;
overlayPlaceholderLabel.text = self.placeholder;
overlayPlaceholderLabel.textColor = color;
overlayPlaceholderLabel.font = self.font;
// Need to add it to the superview, as otherwise we cannot overlay the buildin text label.
[self.superview addSubview:overlayPlaceholderLabel];
self.placeholder = nil;
}
【讨论】:
我是 xcode 的新手,我找到了一种方法来达到同样的效果。
我用所需格式放置了一个 uilabel 代替占位符并将其隐藏
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
switch (textField.tag)
{
case 0:
lblUserName.hidden=YES;
break;
case 1:
lblPassword.hidden=YES;
break;
default:
break;
}
}
我同意它是一种变通方法,而不是真正的解决方案,但从link得到的效果是一样的
注意:在 iOS 7 上仍然有效:|
【讨论】:
对于 iOS7 和更低版本,我能做的最好的事情是:
- (CGRect)placeholderRectForBounds:(CGRect)bounds {
return [self textRectForBounds:bounds];
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return [self textRectForBounds:bounds];
}
- (CGRect)textRectForBounds:(CGRect)bounds {
CGRect rect = CGRectInset(bounds, 0, 6); //TODO: can be improved by comparing font size versus bounds.size.height
return rect;
}
- (void)drawPlaceholderInRect:(CGRect)rect {
UIColor *color =RGBColor(65, 65, 65);
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
[self.placeholder drawInRect:rect withAttributes:@{NSFontAttributeName:self.font, UITextAttributeTextColor:color}];
} else {
[color setFill];
[self.placeholder drawInRect:rect withFont:self.font];
}
}
【讨论】:
对于那些使用 Monotouch (Xamarin.iOS) 的人,这里是 Adam 的答案,翻译成 C#:
public class MyTextBox : UITextField
{
public override void DrawPlaceholder(RectangleF rect)
{
UIColor.FromWhiteAlpha(0.5f, 1f).SetFill();
new NSString(this.Placeholder).DrawString(rect, Font);
}
}
【讨论】:
Font 属性中设置的字体是一个更好的主意。
对于设置具有多种颜色的属性文本字段占位符,
只需指定文本,
//txtServiceText is your Textfield
_txtServiceText.placeholder=@"Badal/ Shah";
NSMutableAttributedString *mutable = [[NSMutableAttributedString alloc] initWithString:_txtServiceText.placeholder];
[mutable addAttribute: NSForegroundColorAttributeName value:[UIColor whiteColor] range:[_txtServiceText.placeholder rangeOfString:@"Badal/"]]; //Replace it with your first color Text
[mutable addAttribute: NSForegroundColorAttributeName value:[UIColor orangeColor] range:[_txtServiceText.placeholder rangeOfString:@"Shah"]]; // Replace it with your secondcolor string.
_txtServiceText.attributedPlaceholder=mutable;
输出:-
【讨论】:
我需要保持占位符对齐,所以亚当的回答对我来说还不够。
为了解决这个问题,我使用了一个小变化,希望对你们中的一些人也有帮助:
- (void) drawPlaceholderInRect:(CGRect)rect {
//search field placeholder color
UIColor* color = [UIColor whiteColor];
[color setFill];
[self.placeholder drawInRect:rect withFont:self.font lineBreakMode:UILineBreakModeTailTruncation alignment:self.textAlignment];
}
【讨论】:
UILineBreakModeTailTruncation 自 iOS 6 起已弃用。
[txt_field setValue:ColorFromHEX(@"#525252") forKeyPath:@"_placeholderLabel.textColor"];
【讨论】:
另一个不需要子类化的选项 - 将占位符留空,并在编辑按钮顶部放置一个标签。像管理占位符一样管理标签(用户输入任何内容后清除..)
【讨论】: