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

如何做到这一点?


当前回答

这里还有另一种方法,它复制了UITextField占位符的轻微缩进:

将UITextField拖到UITextView的右边,这样它们的左上角就对齐了。将占位符文本添加到文本字段。

在viewDidLoad中添加:

[tView setDelegate:self];
tView.contentInset = UIEdgeInsetsMake(-8,-8,0,0);
tView.backgroundColor = [UIColor clearColor];

然后添加:

- (void)textViewDidChange:(UITextView *)textView {
    if (textView.text.length == 0) {
        textView.backgroundColor = [UIColor clearColor];            
    } else {
        textView.backgroundColor = [UIColor whiteColor];
    }
}

其他回答

在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;
 }  
}

简单的方法,使用以下UITextViewDelegate方法在UITextView中创建占位符文本:

- (void)textViewDidBeginEditing:(UITextView *)textView
{
    if ([textView.text isEqualToString:@"placeholder text here..."]) {
         textView.text = @"";
         textView.textColor = [UIColor blackColor]; //optional
    }
    [textView becomeFirstResponder];
}

- (void)textViewDidEndEditing:(UITextView *)textView
{
    if ([textView.text isEqualToString:@""]) {
        textView.text = @"placeholder text here...";
        textView.textColor = [UIColor lightGrayColor]; //optional
    }
    [textView resignFirstResponder];
}

只需要记住在创建时使用准确的文本设置myUITextView即可。

UITextView *myUITextView = [[UITextView alloc] init];
myUITextView.delegate = self;
myUITextView.text = @"placeholder text here...";
myUITextView.textColor = [UIColor lightGrayColor]; //optional

在包含这些方法之前,让父类成为一个UITextViewDelegate。

@interface MyClass () <UITextViewDelegate>
@end

Swift 3.1代码

func textViewDidBeginEditing(_ textView: UITextView) 
{
    if (textView.text == "placeholder text here..." && textView.textColor == .lightGray)
    {
        textView.text = ""
        textView.textColor = .black
    }
    textView.becomeFirstResponder() //Optional
}

func textViewDidEndEditing(_ textView: UITextView)
{
    if (textView.text == "")
    {
        textView.text = "placeholder text here..."
        textView.textColor = .lightGray
    }
    textView.resignFirstResponder()
}

只需要记住在创建时使用准确的文本设置myUITextView即可。

 let myUITextView = UITextView.init()
 myUITextView.delegate = self
 myUITextView.text = "placeholder text here..."
 myUITextView.textColor = .lightGray

在包含这些方法之前,让父类成为一个UITextViewDelegate。

class MyClass: UITextViewDelegate
{

}

你也可以创建一个新的类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,它具有与原始文本视图相同的所有属性,除了不同的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];
}

在看完所有答案后,我意识到我需要一些简单的,同时可重用的东西,这样我就可以在我的项目中为所有uitextview添加相同的功能。最后我得到了以下代码:

extension UITextView {

// MARK: TextView PlaceHolderLabel Setup

func createPlaceHolderLabel(with text: String) {
    let lbl = UILabel()
    self.addSubview(lbl)

// Add your constraints here

    lbl.text = text
    lbl.textColor = .lightGray
}

// My Textview contains only one UILabel, and for my use case the below code works, tweak it according to your use case

// Lastly two methods to toggle between show and hide the placeholder label

func hidePlaceHolderLabel() {
    guard let lbl = self.subviews.first(where: { $0 is UILabel }) else { return }
    lbl.isHidden = true
}

func showPlaceHolderLabel() {
    guard let lbl = self.subviews.first(where: { $0 is UILabel }) else { return }
    lbl.isHidden = false
}

}

当UILabel作为子视图添加到UITextView时,textView游标位置和UILabel位置将不匹配,因此在占位符文本之前留下一个空间

class ViewController: UIViewController, UITextViewDelegate {
    var textView: UITextView!

override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(textView)
    // Also setup textView constraints as per your need
    // Add placeholder to your textView
    // Leave one space before placeholder string
    textView.createPlaceHolderLabel(with: " Address")
    textView.delegate = self
}

然后在textViewdidChange方法中添加以下代码

func textViewDidChange(_ textView: UITextView) {
    if textView.text.isEmpty {
        textView.showPlaceHolderLabel()
    } else {
        textView.hidePlaceHolderLabel()
    }
}

它可以在所有uitextview中重用。