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


566

我想更改在UITextField控件中设置的占位符文本的颜色,使其变黑。

我更愿意在不使用常规文本作为占位符的情况下执行此操作,而必须重写所有方法来模仿占位符的行为。

我相信如果我重写此方法:

- (void)drawPlaceholderInRect:(CGRect)rect

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

Answers:


804

由于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.
}

2
很好-但是请记住,在此之前,您需要在IB中设置一个占位符值
gheese 2013年

4
它也值得将其包装在reactsToSelector调用中-因为没有它,此代码将在6.0之前的部署目标上崩溃(无法识别的选择器发送到实例)
gheese 2013年

5
attributedPlaceholder所说的文档使用文本属性,但颜色除外。
马特·康诺利

1
不知道为什么它不适用于该属性-NSFontAttributeName [[NSAttributedString alloc] initWithString:@"placeholder" attributes: @{NSForegroundColorAttributeName: color, NSFontAttributeName : font}];
dev4u 2014年

3
在iOS 7上,我收到此错误:[<UITextField 0x11561d90> valueForUndefinedKey:]: this class is not key value coding-compliant for the key _field.
i_am_jorf 2014年

237

简单且无痛苦,对于某些人来说可能是一个简单的选择。

_placeholderLabel.textColor

不建议生产,Apple可能会拒绝您的提交。


1
在生产中使用这个吗?我的意思是访问私有财产。
GeriBorbás2014年

11
也许将文本添加到您的答案中以便快速复制和粘贴。_placeholderLabel.textColor
Philiiiiiipp 2014年

47
不要使用此方法,我已经使用过此方法,而iTunes存储已拒绝了我的应用程序。
阿萨德阿里2015年

1
我认为绝不应该建议使用任何类型的私有库方法来解决任何问题
Skrew

2
@jungledev _placeholderLabel是私有财产。该解决方案可能会因为使用私有API而被拒绝。
肖恩·克拉德克

194

您可以这样重写drawPlaceholderInRect:(CGRect)rect以手动呈现占位符文本:

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

44
这样的东西[self.placeholder drawInRect:rect withFont:self.font lineBreakMode:UILineBreakModeTailTruncation alignment:self.textAlignment];可能更好。这样,您将尊重textAlignment财产。我已将此添加到我的SSTextField类中。随时在您的项目中使用。
山姆·索菲斯

52
绝对不做科泰格所说的话。切勿通过类别覆盖方法。永远
约书亚·温伯格

8
@JoshuaWeinberg您的建议背后是否有任何特定原因。
克里希南(Krishnan)

5
@Krishnan不支持在类别中实现重复方法,并且您永远无法确定将调用哪个方法,是否同时调用了两个方法或调用它们的顺序。
肖恩伍德沃德

8
在iOS7中,您可以通过使用CGRectInset(rect,0,(rect.size.height-self.font.lineHeight)/ 2.0)来改变文本的垂直居中位置。
Brian S

170

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

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

6
建议最佳答案。可以使用并使用已记录的API。
伊恩·霍尔2014年

2
如何使UISearchBar起作用?没有attributedPlaceholder属性。
gilsaints88

1
这个答案是不正确的-根据文档,attributedPlaceholder的文本颜色信息被忽略developer.apple.com/library/ios/documentation/UIKit/Reference/...
阿德莱·奥莱

谢谢大家。希望对您有所帮助。阿德莱·霍勒(Adlai Holler)试试看!该答案适用于以前的iOS版本。如果您有更好的答案,我们欢迎您提出建议。
Manju 2015年

由于没有归因的Placeholder属性,因此无法在iOS8上运行
Ben Clayton

157

也许您想尝试这种方式,但是Apple可能会警告您有关访问私有ivar的信息:

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

注意
根据MartinAlléus的说法,这在iOS 7上不再有效。


6
我在我的应用程序中使用此方法。审查还可以。因此,我认为可以使用它。
Michael A.

9
这不是安全的应用商店,因此建议您这样做,我们不保证您会获得批准或继续使用这些技术。
Sveinung Kval Bakken

31
是否获得批准并不重要。重要的是,这可能会在将来的操作系统更新中破坏您的应用程序。
pablasso

2
iOS 7没有任何问题...尽管有注释,我还是尝试了一下,它似乎运行良好,并且我过去使用这种方法没有问题。
WCByrne

6
这一直是个坏主意,而现在它在iOS上破13:Access to UITextField's _placeholderLabel ivar is prohibited. This is an application bug😈
莱德麦凯

153

在Swift <3.0中可以使用:

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])

Swift 4.2:

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

在iOS8.2上使用您的解决方案,就像一个魅力。完美的解决方案。在目标C中也使用。
Akshit Zaveri

73

在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中,如果让placeholder = yourTextField.placeholder {yourTextField.attributedPlaceholder = NSAttributedString(string:placeholder,attribute:[NSAttributedStringKey.foregroundColor:UIColor.white])}
罗纳尔多·阿尔贝蒂尼

请注意,在执行此代码后更改占位符文本值会带回默认的占位符颜色。
亚历山德罗·冯杜斯科洛

66

Swift 3.0 +故事板

为了在情节提要中更改占位符颜色,请使用下一个代码创建扩展。(如果您认为可以随意更新此代码,则可以更清楚,更安全)。

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
米兰·卡米利亚

适用于iOS 13
Jalil

43

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

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

33

我已经遇到了这个问题。就我而言,以下代码是正确的。

目标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

希望对您有帮助。


@Ashu这会导致ios 13中的崩溃'禁止访问UITextField的_placeholderLabel ivar。这是一个应用程序错误,“它甚至不会构建”,我并不是在谈论将其放入AppStore
Melany

1
iOS 13受到限制,不能再使用了
Kishore Kumar

对象代码已在IOS 13上经过测试,无法正常工作。
Mehdico

1
@Mehdico我更新了iOS 13的答案。希望这会对您有所帮助。
阿舒(Ashu),

我花了很长时间才知道我必须在viewWillAppear或进行这项改变viewDidAppearviewDidLoad为时过早。
4

32

这样我们就可以在iOS中更改文本字段占位符文本的颜色

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

1
从iOS13开始这是不行的
泰迪

@Teddy您现在是怎么做到的?我开始对此有疑问。
哈利勒

@Jalil我希望我仍然准时为您服务。textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@“ text”属性:@ {NSForegroundColorAttributeName:[UIColor colorWithHexString:@“ ffffff55”]}]];
泰迪

18

你为什么不只使用UIAppearance方法:

[[UILabel appearanceWhenContainedIn:[UITextField class], nil] setTextColor:[UIColor whateverColorYouNeed]];

很棒!文本的颜色不受影响(至少使用textColor属性的不同代理)
HotJard

18

同样在情节提要中,无需单行代码

在此处输入图片说明


1
你怎么知道这个?我认为这是最好的方法,但是怎么知道呢?请告诉我我是ios编程的新手。
Yawar

2
这是非常普遍的。一旦您知道它到处使用它;)
Petr Syrov '16

我知道一旦了解了背后的原因,我就会经常使用它。但是我的意思是“ _placeholderLabel.textColor”这应该是文本字段的子视图。有没有办法查看有关控件的此类信息?
Yawar

2
@Yawar您可以在Xcode中使用视图层次结构检查器,或者在调试器中内省视图。
大卫·甘斯特

好人,无论文本字段如何,您都可以使用相同的“ tile / name”作为键路径
Naishta

16

迅速3.X

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

迅速5

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

12

对于iOS 6.0 +

[textfield setValue:your_color forKeyPath:@"_placeholderLabel.textColor"];

希望能帮助到你。

注意: 由于我们正在访问私有API,Apple可能会拒绝(0.01%的机会)您的应用程序。自两年以来,我在所有项目中都使用了此功能,但Apple并没有要求这样做。


terminating with uncaught exception of type NSException为iOS8 抛出一个错误
Yar

10

对于Xamarin.iOS开发人员,我可以从本文档中找到它 https://developer.xamarin.com/api/type/Foundation.NSAttributedString/

textField.AttributedPlaceholder = new NSAttributedString ("Hello, world",new UIStringAttributes () { ForegroundColor =  UIColor.Red });

谢谢 !!我首先使用CTStringAttributes而不是UIStringAttributes,但无法弄清楚。注意不要使用此选项:new NSAttributedString("placeholderstring", new CTStringAttributes() { ForegroundColor = UIColor.Blue.CGColor });
Yohan Dahmani

9

迅捷版。可能会帮助某人。

class TextField: UITextField {
   override var placeholder: String? {
        didSet {
            let placeholderString = NSAttributedString(string: placeholder!, attributes: [NSForegroundColorAttributeName: UIColor.whiteColor()])
            self.attributedPlaceholder = placeholderString
        }
    }
}

6

类别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

6

在iOS7中处理垂直和水平对齐以及占位符的颜色。drawInRect和drawAtPoint不再使用当前上下文fillColor。

https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/CustomTextProcessing/CustomTextProcessing.html

对象

@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

感谢您提供的出色解决方案-可以使文本正确地垂直居中(对自定义字体有用)。我想补充一点的是,该解决方案是不是在回落与iOS 6或以上(易不足以解决兼容[self.placeholder drawInRect:RECT withFont:self.font lineBreakMode:NSLineBreakByTruncatingTail对齐:self.textAlignment]
lifjoy 2014年

6

iOS 6或更高版本提供attributedPlaceholderUITextField。的iOS 3.2和更高版本提供setAttributes:range:NSMutableAttributedString

您可以执行以下操作:

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;

不知道是什么原因引起的,我在viewdidLoad中调用了此代码。新颜色和字体大小仅在重绘后出现。还有什么需要做的吗?
Vinayaka Karjigi,

它解决了,我忘了为UITextfield设置字体,然后再将该字体用于占位符文本。我的坏人
Vinayaka Karjigi,

6

Swift 4.1的此解决方案

    textName.attributedPlaceholder = NSAttributedString(string: textName.placeholder!, attributes: [NSAttributedStringKey.foregroundColor : UIColor.red])

4

重写drawPlaceholderInRect:是正确的方法,但是由于API(或文档)中的错误,它无法正常工作。

该方法永远不会在上调用UITextField

另请参见UITextField上的drawTextInRect未调用

您可以使用digdog的解决方案。由于我不确定是否能通过苹果的审查,因此我选择了另一种解决方案:用我自己的标签覆盖文本字段,以模仿占位符行为。

不过这有点混乱。代码看起来像这样(注意,我正在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;
}

您如何分享易于审核的解决方案?
亚当2010年

我添加了我使用的解决方案。我不得不做些挖掘工作,因为这是前一段时间了:)
henning77'5

我做了类似的事情,但是我将代码放置在一个类别中,并且需要在shouldChangeCharacters中进行是否是否可见的检查,这是类别中的第二种方法,称为-(void)overlayPlaceholderVisible:(BOOL)visible ;
David van Dugteren 2013年

3

我是Xcode的新手,我找到了一种实现相同效果的方法。

我将uilabel放置在所需格式的占位符上,并将其隐藏在

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    switch (textField.tag)
    {
        case 0:
            lblUserName.hidden=YES;
            break;

        case 1:
            lblPassword.hidden=YES;
            break;

        default:
            break;
    }
}

我同意它是可以解决的,而不是真正的解决方案,但是从此链接获得的效果是相同的

注意:在iOS 7上仍然可以使用:


3

带CAVEAT的Swift 5。

let attributes = [ NSAttributedString.Key.foregroundColor: UIColor.someColor ]
let placeHolderString = NSAttributedString(string: "DON'T_DELETE", attributes: attributes)
txtField.attributedPlaceholder = placeHolderString

需要注意的String是,即使在其他地方的代码中设置了该字符串,也必须在“ DON'T_DELETE”所在的位置输入非空值。可能会节省您五分钟的时间。


2

对于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];
  }
}

2

对于使用Monotouch(Xamarin.iOS)的用户,以下是亚当的答案,已翻译为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文本字段属性中的字体集是一个更好的主意。
Wolfgang Schreurs 2013年

1

我需要保持占位符对齐,因此亚当的答案对我来说还不够。

为了解决这个问题,我使用了一个小的变体,希望对您有所帮助:

- (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的
Supertecnoboff

1
[txt_field setValue:ColorFromHEX(@"#525252") forKeyPath:@"_placeholderLabel.textColor"];

关于此的一个小提示是,您正在访问私有的iVar(_placeholderLabel),而在过去,Apple对此并不满意。:)
Alexander W

1

对于具有多种颜色的设置属性文本字段占位符,

只需指定Text,

  //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;

输出:-

在此处输入图片说明


0

另一个不需要子类化的选项-将占位符留空,并在“编辑”按钮的顶部放置一个标签。就像管理占位符一样管理标签(用户输入任何内容时清除。)


我认为,如果您有一个文本字段,这将非常有效,但是如果您尝试在更大范围的全球范围内进行此更改,则此解决方案将为您的项目增加大量的开销。
詹姆斯·帕克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.