本文翻译自: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? 有谁知道如何做到这一点?
参考:https://stackoom.com/question/1s1bf/文本视图-UITextView-占位符Swift
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)
}
}
}
I did this by using two different text views: 我通过使用两个不同的文本视图来做到这一点:
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
}
}
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
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
的条件。
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];
}`