我的应用程序使用UITextView。现在我想让UITextView有一个占位符,类似于你可以为UITextField设置的占位符。

如何做到这一点?


当前回答

你可以在textview上设置一个标签。

MyUITextView.h

@interface MyUITextView : UITextView {
    UILabel* _placeholderLabel;
}

@property(nonatomic, assign)NSString *placeholder;

MyUITextView.m

@implementation MyUITextView

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Create placeholder
        viewFrame = CGRectMake(0, 0, frame.size.width, 15);
        _placeholderLabel = [[UILabel alloc] initWithFrame:viewFrame];
        _placeholderLabel.textColor = [UIColor lightGrayColor];
        [self addSubview:_placeholderLabel];

        // Add text changed notification 
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
    }
    return self;
}

- (void)setPlaceholder:(NSString *)placeholder {
    _placeholderLabel.text = placeholder;
}

- (NSString*)placeholder {
    return _placeholderLabel.text;
}

#pragma mark UITextViewTextDidChangeNotification

- (void)textChanged:(NSNotification *)notification {
    _placeholderLabel.hidden = ([self.text lenght] == 0);
}

@end

其他回答

我创建了一个实例变量来检查是否显示占位符:

BOOL showPlaceHolder;
UITextView * textView; // and also the textView

在viewDidLoad上设置:

[self setPlaceHolder]; 

下面是它的作用:

- (void)setPlaceholder
{
    textView.text = NSLocalizedString(@"Type your question here", @"placeholder");
    textView.textColor = [UIColor lightGrayColor];
    self.showPlaceHolder = YES; //we save the state so it won't disappear in case you want to re-edit it
}

我还创建了一个按钮来退出键盘。您不必这样做,但这里很酷的事情是,如果没有输入任何内容,占位符将再次显示

- (void)textViewDidBeginEditing:(UITextView *)txtView 
{
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(resignKeyboard)];
    if (self.showPlaceHolder == YES) 
    {
        textView.textColor = [UIColor blackColor];
        textView.text = @"";
        self.showPlaceHolder = NO;
    }
}

- (void)resignKeyboard 
{
    [textView resignFirstResponder];
    //here if you created a button like I did to resign the keyboard, you should hide it
    if (textView.text.length == 0) {
        [self setPlaceholder];
    }       
}

你也可以创建一个新的类TextViewWithPlaceholder作为UITextView的子类。

(这段代码有点粗糙——但我认为它在正确的轨道上。)

@interface TextViewWithPlaceholder : UITextView
{

    NSString *placeholderText;  // make a property
    UIColor *placeholderColor;  // make a property
    UIColor *normalTextColor;   // cache text color here whenever you switch to the placeholderColor
}

- (void) setTextColor: (UIColor*) color
{
   normalTextColor = color;
   [super setTextColor: color];
}

- (void) updateForTextChange
{
    if ([self.text length] == 0)
    { 
        normalTextColor = self.textColor;
        self.textColor = placeholderColor;
        self.text = placeholderText;
    }
    else
    {
        self.textColor = normalTextColor;
    }

}

在委托中,添加以下内容:

- (void)textViewDidChange:(UITextView *)textView
{
    if ([textView respondsToSelector: @selector(updateForTextChange)])
    {
        [textView updateForTextChange];
    }

}

在UITextView中创建占位符是不可能的,但是你可以通过这个生成类似占位符的效果。

  - (void)viewDidLoad{      
              commentTxtView.text = @"Comment";
              commentTxtView.textColor = [UIColor lightGrayColor];
              commentTxtView.delegate = self;

     }
       - (BOOL) textViewShouldBeginEditing:(UITextView *)textView
     {
         commentTxtView.text = @"";
         commentTxtView.textColor = [UIColor blackColor];
         return YES;
     }

     -(void) textViewDidChange:(UITextView *)textView
     {

    if(commentTxtView.text.length == 0){
        commentTxtView.textColor = [UIColor lightGrayColor];
        commentTxtView.text = @"Comment";
        [commentTxtView resignFirstResponder];
    }
    }

或者你可以添加标签在textview就像

       lbl = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 0.0,textView.frame.size.width - 10.0, 34.0)];


[lbl setText:kDescriptionPlaceholder];
[lbl setBackgroundColor:[UIColor clearColor]];
[lbl setTextColor:[UIColor lightGrayColor]];
textView.delegate = self;

[textView addSubview:lbl];

并设置

- (void)textViewDidEndEditing:(UITextView *)theTextView
{
     if (![textView hasText]) {
     lbl.hidden = NO;
}
}

- (void) textViewDidChange:(UITextView *)textView
{
    if(![textView hasText]) {
      lbl.hidden = NO;
}
else{
    lbl.hidden = YES;
 }  
}

你可以在textview上设置一个标签。

MyUITextView.h

@interface MyUITextView : UITextView {
    UILabel* _placeholderLabel;
}

@property(nonatomic, assign)NSString *placeholder;

MyUITextView.m

@implementation MyUITextView

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Create placeholder
        viewFrame = CGRectMake(0, 0, frame.size.width, 15);
        _placeholderLabel = [[UILabel alloc] initWithFrame:viewFrame];
        _placeholderLabel.textColor = [UIColor lightGrayColor];
        [self addSubview:_placeholderLabel];

        // Add text changed notification 
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
    }
    return self;
}

- (void)setPlaceholder:(NSString *)placeholder {
    _placeholderLabel.text = placeholder;
}

- (NSString*)placeholder {
    return _placeholderLabel.text;
}

#pragma mark UITextViewTextDidChangeNotification

- (void)textChanged:(NSNotification *)notification {
    _placeholderLabel.hidden = ([self.text lenght] == 0);
}

@end

一个更简单的方法是创建一个次要的UITextView,它具有与原始文本视图相同的所有属性,除了不同的textColor,并带有约束以确保它们保持对齐。然后当任何字符进入主文本视图时,隐藏克隆文本视图,否则显示带有一些文本的克隆文本视图。

这可以通过几种方式实现,但相对简单的方法是子类化UITextView并将所有这些逻辑保留在子类中。

所以,子类UITextView并允许它惰性地创建它的占位符视图

接口文件:

@interface FOOTextView : UITextView <UITextViewDelegate>

@property (nonatomic, copy) NSString *placeholderText;

- (void)checkPlaceholder;

@end

实现文件:

#import "FOOTextView.h"

@interface FOOTextView ()

@property (nonatomic, strong) UITextView *placeholderTextView;

@end

@implementation FOOTextView

- (void)checkPlaceholder {
    // Hide the placeholder text view if we've got any text
    self.placeholderTextView.hidden = (self.text.length > 0 || self.attributedText.length > 0);
}

- (void)setPlaceholderText:(NSString *)placeholderText {
    _placeholderText = [placeholderText copy];

    // Setup the placeholder text view if we haven't already
    [self setupPlaceholderTextView];

    // Apply the placeholder text to the placeholder text view
    self.placeholderTextView.text = placeholderText;
}

- (void)setupPlaceholderTextView {
    if (!self.placeholderTextView) {

        // Setup the place holder text view, duplicating our visual setup
        self.placeholderTextView = [[UITextView alloc] initWithFrame:CGRectZero];
        self.placeholderTextView.translatesAutoresizingMaskIntoConstraints = NO;
        self.placeholderTextView.textColor = self.placeholderTextColor ? self.placeholderTextColor : [UIColor colorWithRed:199.f/255.f green:199.f/255.f blue:205.f/255.f alpha:1.f];
        self.placeholderTextView.userInteractionEnabled = NO;
        self.placeholderTextView.font = self.font;
        self.placeholderTextView.textAlignment = self.textAlignment;
        self.placeholderTextView.backgroundColor = self.backgroundColor;
        self.placeholderTextView.editable = NO;

        // Our background color must be clear for the placeholder text view to show through
        self.backgroundColor = [UIColor clearColor];

        // Insert the placeholder text view into our superview, below ourself so it shows through
        [self.superview insertSubview:self.placeholderTextView belowSubview:self];

        // Setup constraints to ensure the placeholder text view stays aligned with us
        NSLayoutConstraint *constraintCenterX = [NSLayoutConstraint constraintWithItem:self.placeholderTextView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.f constant:0.f];
        NSLayoutConstraint *constraintCenterY = [NSLayoutConstraint constraintWithItem:self.placeholderTextView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.f constant:0.f];
        NSLayoutConstraint *constraintWidth = [NSLayoutConstraint constraintWithItem:self.placeholderTextView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1.f constant:0.f];
        NSLayoutConstraint *constraintHeight = [NSLayoutConstraint constraintWithItem:self.placeholderTextView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeHeight multiplier:1.f constant:0.f];
        NSArray *constraints = @[constraintCenterX, constraintCenterY, constraintWidth, constraintHeight];
        [self.superview addConstraints:constraints];

    }
}

- (void)setPlaceholderTextColor:(UIColor *)placeholderTextColor {
    _placeholderTextColor = placeholderTextColor;
    self.placeholderTextView.textColor = _placeholderTextColor;
}

- (void)setBackgroundColor:(UIColor *)backgroundColor {
    // We don't want a background color ourselves, instead we want our placeholder text view to have the desired background color
    [self.placeholderTextView setBackgroundColor:backgroundColor];
}

- (void)removeFromSuperview {
    // Ensure we also remove our placeholder text view
    [self.placeholderTextView removeFromSuperview];
    self.placeholderTextView = nil;
    [super removeFromSuperview];
}

#pragma mark - Text View Delegation 
- (void)textViewDidChange:(UITextView *)textView {
    [self checkPlaceholder];
}

@end

使用上面的类,如果你设置了一个FOOTextView的委托实例到它自己,一切都将开箱工作:

FOOTextView *myTextView = ...
myTextView.placeholderText = @"What's on your mind?";
myTextView.placeholderTextColor = [UIColor lightGrayColor];
myTextView.delegate = myTextView;

如果你想另一个对象接管作为委托,那么你只需要在textViewDidChange: delegate方法中调用文本视图的checkPlaceholder方法,例如;

FOOTextView *myTextView = ...
myTextView.placeholderText = @"What's on your mind?";
myTextView.placeholderTextColor = [UIColor lightGrayColor];
myTextView.delegate = self;
self.myTextView = myTextView;

- (void)textViewDidChange:(UITextView *)textView {
    // Call the checkPlaceholder method to update the visuals
    [self.myTextView checkPlaceholder];
}