iPhone UITextField - Change placeholder text color

筅森魡賤 提交于 2019-12-16 22:09:09

问题


I'd like to change the color of the placeholder text I set in my UITextField controls, to make it black.

I'd prefer to do this without using normal text as the placeholder and having to override all the methods to imitate the behaviour of a placeholder.

I believe if I override this method:

- (void)drawPlaceholderInRect:(CGRect)rect

then I should be able to do this. But I'm unsure how to access the actual placeholder object from within this method.


回答1:


Since the introduction of attributed strings in UIViews in iOS 6, it's possible to assign a color to the placeholder text like this:

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:


Easy and pain-free, could be an easy alternative for some.

_placeholderLabel.textColor

Not suggested for production, Apple may reject your submission.




回答3:


You can override drawPlaceholderInRect:(CGRect)rect as such to manually render the placeholder text:

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



回答4:


You can Change the Placeholder textcolor to any color which you want by using the below code.

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



回答5:


Maybe you want to try this way, but Apple might warn you about accessing private ivar:

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

NOTE
This is not working on iOS 7 anymore, according to Martin Alléus.




回答6:


This works in Swift <3.0:

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

Tested in iOS 8.2 and 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])



回答7:


In Swift:

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

In Swift 4.0:

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



回答8:


Swift 3.0 + Storyboard

In order to change placeholder color in storyboard, create an extension with next code. (feel free to update this code, if you think, it can be clearer and safer).

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 version

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 version

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



回答9:


The following only with iOS6+ (as indicated in Alexander W's comment):

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



回答10:


With this we can change the color of textfield's placeholder text in 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"];



回答11:


I had already faced this issue. In my case below code is correct.

Objective C

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

For Swift 4.X

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

For iOS 13 Swift Code

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

You can also use below code for iOS 13

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

Hope, this may help you.




回答12:


Why don't you just use UIAppearance method:

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



回答13:


Also in your storyboard, without single line of code




回答14:


For iOS 6.0 +

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

Hope it helps.

Note: Apple may reject (0.01% chances) your app as we are accessing private API. I am using this in all my projects since two years, but Apple didn't ask for this.




回答15:


For Xamarin.iOS developers, I found it from this document https://developer.xamarin.com/api/type/Foundation.NSAttributedString/

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



回答16:


Swift version. Probably it would help someone.

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



回答17:


in swift 3.X

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

in swift 5

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



回答18:


Categories FTW. Could be optimized to check for effective color change.


#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



回答19:


To handle both vertical and horizontal alignment as well as color of placeholder in iOS7. drawInRect and drawAtPoint no longer use current context fillColor.

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

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



回答20:


iOS 6 and later offers attributedPlaceholder on UITextField. iOS 3.2 and later offers setAttributes:range: on NSMutableAttributedString.

You can do the following:

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;



回答21:


Overriding drawPlaceholderInRect: would be the correct way, but it does not work due to a bug in the API (or the documentation).

The method never gets called on an UITextField.

See also drawTextInRect on UITextField not called

You might use digdog's solution. As I am not sure if that gets past Apples review, I chose a different solution: Overlay the text field with my own label which imitates the placeholder behaviour.

This is a bit messy though. The code looks like this (Note I am doing this inside a subclass of 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;
}



回答22:


Iam new to xcode and i found a way around to the same effect.

I placed a uilabel in place of place holder with the desired format and hide it in

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

        case 1:
            lblPassword.hidden=YES;
            break;

        default:
            break;
    }
}

I agree its a work around and not a real solution but the effect was same got it from this link

NOTE: Still works on iOS 7 :|




回答23:


This solution for Swift 4.1

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



回答24:


The best i can do for both iOS7 and less is:

- (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];
  }
}



回答25:


For those using Monotouch (Xamarin.iOS), here's Adam's answer, translated to C#:

public class MyTextBox : UITextField
{
    public override void DrawPlaceholder(RectangleF rect)
    {
        UIColor.FromWhiteAlpha(0.5f, 1f).SetFill();
        new NSString(this.Placeholder).DrawString(rect, Font);
    }
}



回答26:


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



回答27:


Swift 5 WITH CAVEAT.

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

The caveat being that you MUST enter a non-empty String where "DON'T_DELETE" is, even if that string is set in code elsewhere. Might save you five minutes of head-sctratching.




回答28:


I needed to keep the placeholder alignment so adam's answer was not enough for me.

To solve this I used a small variation that I hope will help some of you too:

- (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];
}



回答29:


For set Attributed Textfield Placeholder with Multiple color ,

Just specify the 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;

Output :-




回答30:


Another option that doesn't require subclassing - leave placeholder blank, and put a label on top of edit button. Manage the label just like you would manage the placeholder (clearing once user inputs anything..)



来源:https://stackoverflow.com/questions/1340224/iphone-uitextfield-change-placeholder-text-color

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!