文本视图(UITextView)占位符Swift

冯俊英
2023-12-01

本文翻译自:Text View (UITextView) Placeholder Swift

I'm making an application which uses a UITextView . 我正在制作一个使用UITextView的应用程序。 Now I want the Text View to have a placeholder similar to the one you can set for a Text Field. 现在,我希望“文本视图”具有一个类似于您可以为“文本字段”设置的占位符。 How would you accomplish this using swift. 您将如何快速完成此任务。

Does anyone know how to do this? 有谁知道如何做到这一点?


#1楼

参考:https://stackoom.com/question/1s1bf/文本视图-UITextView-占位符Swift


#2楼

Updated for Swift 4 为Swift 4更新

UITextView doesn't inherently have a placeholder property so you'd have to create and manipulate one programmatically using UITextViewDelegate methods. UITextView本质上不具有占位符属性,因此您必须使用UITextViewDelegate方法以编程方式创建和操作一个占位符。 I recommend using either solution #1 or #2 below depending on the desired behavior. 我建议根据所需的行为使用下面的解决方案#1或#2。

Note: For either solution, add UITextViewDelegate to the class and set textView.delegate = self to use the text view's delegate methods. 注意:对于这两种解决方案,请将UITextViewDelegate添加到该类,并设置textView.delegate = self以使用文本视图的委托方法。


Solution #1 - If you want the placeholder to disappear as soon as the user selects the text view: 解决方案1- 如果您希望占位符在用户选择文本视图后立即消失:

First set the UITextView to contain the placeholder text and set it to a light gray color to mimic the look of a UITextField 's placeholder text. 首先将UITextView设置为包含占位符文本,然后将其设置为浅灰色,以模仿UITextField占位符文本的外观。 Either do so in the viewDidLoad or upon the text view's creation. 可以在viewDidLoad或在创建文本视图时执行。

textView.text = "Placeholder"
textView.textColor = UIColor.lightGray

Then when the user begins to edit the text view, if the text view contains a placeholder (ie if its text color is light gray) clear the placeholder text and set the text color to black in order to accommodate the user's entry. 然后,当用户开始编辑文本视图时,如果文本视图包含占位符(即,如果其文本颜色为浅灰色),则清除占位符文本并将文本颜色设置为黑色,以适应用户的输入。

func textViewDidBeginEditing(_ textView: UITextView) {
    if textView.textColor == UIColor.lightGray {
        textView.text = nil
        textView.textColor = UIColor.black
    }
}

Then when the user finishes editing the text view and it's resigned as the first responder, if the text view is empty, reset its placeholder by re-adding the placeholder text and setting its color to light gray. 然后,当用户完成文本视图的编辑并将其辞去为第一响应者时,如果文本视图为空,请通过重新添加占位符文本并将其颜色设置为浅灰色来重置其占位符。

func textViewDidEndEditing(_ textView: UITextView) {
    if textView.text.isEmpty {
        textView.text = "Placeholder"
        textView.textColor = UIColor.lightGray
    }
}

Solution #2 - If you want the placeholder to show whenever the text view is empty, even if the text view's selected: 解决方案2- 如果希望占位符在文本视图为空时显示,即使选择了文本视图:

First set the placeholder in the viewDidLoad : 首先在viewDidLoad设置占位符:

textView.text = "Placeholder"
textView.textColor = UIColor.lightGray

textView.becomeFirstResponder()

textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)

(Note: Since the OP wanted to have the text view selected as soon as the view loads, I incorporated text view selection into the above code. If this is not your desired behavior and you do not want the text view selected upon view load, remove the last two lines from the above code chunk.) (注意:由于OP希望在加载视图后立即选择文本视图,因此我将文本视图选择合并到了上面的代码中。如果这不是您想要的行为,并且您不希望在加载视图时选择文本视图,从上述代码块中删除最后两行。)

Then utilize the shouldChangeTextInRange UITextViewDelegate method, like so: 然后,使用shouldChangeTextInRange UITextViewDelegate方法,如下所示:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {

    // Combine the textView text and the replacement text to
    // create the updated text string
    let currentText:String = textView.text
    let updatedText = (currentText as NSString).replacingCharacters(in: range, with: text)

    // If updated text view will be empty, add the placeholder
    // and set the cursor to the beginning of the text view
    if updatedText.isEmpty {

        textView.text = "Placeholder"
        textView.textColor = UIColor.lightGray

        textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
    }

    // Else if the text view's placeholder is showing and the
    // length of the replacement string is greater than 0, set 
    // the text color to black then set its text to the
    // replacement string
     else if textView.textColor == UIColor.lightGray && !text.isEmpty {
        textView.textColor = UIColor.black
        textView.text = text
    }

    // For every other case, the text should change with the usual
    // behavior...
    else {
        return true
    }

    // ...otherwise return false since the updates have already
    // been made
    return false
}

And also implement textViewDidChangeSelection to prevent the user from changing the position of the cursor while the placeholder's visible. 并且还实现了textViewDidChangeSelection以防止用户在占位符可见的情况下更改光标的位置。 (Note: textViewDidChangeSelection is called before the view loads so only check the text view's color if the window is visible): (注意: textViewDidChangeSelection在视图加载之前被调用,因此,如果窗口可见,则仅检查文本视图的颜色):

func textViewDidChangeSelection(_ textView: UITextView) {
    if self.view.window != nil {
        if textView.textColor == UIColor.lightGray {
            textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
        }
    }
}

#3楼

I did this by using two different text views: 我通过使用两个不同的文本视图来做到这一点:

  1. One in the background that is used as a placeholder. 在后台用作占位符的一个。
  2. One in the foreground (with a transparent background) that the user actually types in. 用户实际键入的前景(透明背景)中的一个。

The idea is that once the user starts typing stuff in the foreground view, the placeholder in the background disappears (and reappears if the user deletes everything). 这个想法是,一旦用户开始在前景视图中键入内容,背景中的占位符就会消失(如果用户删除所有内容,则占位符会重新出现)。 So it behaves exactly like a placeholder for the single line text field. 因此,它的行为与单行文本字段的占位符完全相同。

Here's the code I used for it. 这是我使用的代码。 Note that descriptionField is the field the user types in and descriptionPlaceholder is the one in the background. 请注意,descriptionField是用户键入的字段,而descriptionPlaceholder是用户在后台键入的字段。

func textViewDidChange(descriptionField: UITextView) {
    if descriptionField.text.isEmpty == false {
        descriptionPlaceholder.text = ""
    } else {
        descriptionPlaceholder.text = descriptionPlaceholderText
    }
}

#4楼


Floating Placeholder 浮动占位符


It's simple, safe and reliable to position a placeholder label above a text view, set its font, color and manage placeholder visibility by tracking changes to the text view's character count. 将占位符标签放置在文本视图上方,设置其字体,颜色并通过跟踪文本视图的字符数变化来管理占位符的可见性是简单,安全和可靠的。

Swift 3: 斯威夫特3:

class NotesViewController : UIViewController, UITextViewDelegate {

    @IBOutlet var textView : UITextView!
    var placeholderLabel : UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        textView.delegate = self
        placeholderLabel = UILabel()
        placeholderLabel.text = "Enter some text..."
        placeholderLabel.font = UIFont.italicSystemFont(ofSize: (textView.font?.pointSize)!)
        placeholderLabel.sizeToFit()
        textView.addSubview(placeholderLabel)
        placeholderLabel.frame.origin = CGPoint(x: 5, y: (textView.font?.pointSize)! / 2)
        placeholderLabel.textColor = UIColor.lightGray
        placeholderLabel.isHidden = !textView.text.isEmpty
    }

    func textViewDidChange(_ textView: UITextView) {
        placeholderLabel.isHidden = !textView.text.isEmpty
    }
}

Swift 2: Same, except: italicSystemFontOfSize(textView.font.pointSize) , UIColor.lightGrayColor Swift 2:相同,除了: italicSystemFontOfSize(textView.font.pointSize) UIColor.lightGrayColor italicSystemFontOfSize(textView.font.pointSize)UIColor.lightGrayColor



#5楼

Swift: 迅速:

Add your text view programmatically or via Interface Builder, if the last, create the outlet: 以编程方式或通过Interface Builder添加文本视图,如果是最后一个,则创建出口:

@IBOutlet weak var yourTextView: UITextView!

Please add the delegate (UITextViewDelegate): 请添加委托(UITextViewDelegate):

class ViewController: UIViewController, UITextViewDelegate {

In the viewDidLoad method, do add the following: 在viewDidLoad方法中,添加以下内容:

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

    yourTextView.delegate = self
    yourTextView.text = "Placeholder text goes right here..."
    yourTextView.textColor = UIColor.lightGray

Now let me introduce the magic part, add this function: 现在让我介绍魔术部分,添加以下功能:

func textViewDidBeginEditing(_ textView: UITextView) {

    if yourTextView.textColor == UIColor.lightGray {
        yourTextView.text = ""
        yourTextView.textColor = UIColor.black
    }
}

Do note that this will execute whenever editing starts, there we will check conditions to tell the state, using the color property. 请注意,此操作将在编辑开始时执行,在那里我们将使用color属性检查条件以告知状态。 Setting text to nil i do not recommend. 我不建议将文本设置为nil Right after that, we set the text color to desired, in this case, black. 之后,我们将文本颜色设置为所需的颜色,在这种情况下为黑色。

Now add this function too: 现在也添加此功能:

func textViewDidEndEditing(_ textView: UITextView) {

    if yourTextView.text == "" {

        yourTextView.text = "Placeholder text ..."
        yourTextView.textColor = UIColor.lightGray
    }
}

Let me insist, do not compare to nil , i have already tried that and it would not work. 让我坚持,不要比作nil ,我已经尝试过了,那是行不通的。 We then set the values back to placeholder style, and set the color back to placeholder color because it is a condition to check in textViewDidBeginEditing . 然后,将值设置回占位符样式,并将颜色设置回占位符颜色,因为这是签入textViewDidBeginEditing的条件。


#6楼

I don't know why people over complicate this issue so much.... It's fairly straight forward and simple. 我不知道为什么人们会把这个问题弄得如此复杂。。。 Here's a subclass of UITextView that provides the requested functionality. 这是UITextView的子类,提供所需的功能。

- (void)customInit
{
    self.contentMode = UIViewContentModeRedraw;
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
}

    - (void)textChanged:(NSNotification *)notification
    {
        if (notification.object == self) {
            if(self.textStorage.length != 0 || !self.textStorage.length) {
                [self setNeedsDisplay];
            }
        }
    }


    #pragma mark - Setters

    - (void)setPlaceholderText:(NSString *)placeholderText withFont:(UIFont *)font
    {
        self.placeholderText = placeholderText;
        self.placeholderTextFont = font;

    }



    - (void)drawRect:(CGRect)rect
    {
        [super drawRect:rect];
        [[UIColor lightGrayColor] setFill];

        if (self.textStorage.length != 0) {
            return;
        }

        CGRect inset = CGRectInset(rect, 8, 8);//Default rect insets for textView
        NSDictionary *attributes =  @{NSFontAttributeName: self.placeholderTextFont, NSForegroundColorAttributeName: [UIColor grayColor]};
        [self.placeholderText drawInRect:inset withAttributes:attributes];
    }`
 类似资料: