UITextView
中添加占位符,类似于您可以在UITextField
中为Swift
设置占位符?#1 楼
已为Swift 4更新UITextView
本质上不具有占位符属性,因此您必须使用UITextViewDelegate
方法以编程方式创建和操作一个占位符。我建议根据所需的行为使用下面的解决方案#1或#2。注意:对于这两种解决方案,请将
UITextViewDelegate
添加到类中,并将textView.delegate = self
设置为使用文本视图的委托方法。 > 解决方案1-如果您希望占位符在用户选择文本视图后就消失:
首先将
UITextView
设置为包含占位符文本并进行设置为浅灰色,以模仿UITextField
的占位符文本的外观。请在viewDidLoad
中或在创建文本视图时执行此操作。 (如果其文本颜色为浅灰色),清除占位符文本并将文本颜色设置为黑色,以适应用户的输入。textView.text = "Placeholder"
textView.textColor = UIColor.lightGray
然后当用户完成编辑时文本视图,并将其辞去为第一响应者,如果文本视图为空,请通过重新添加占位符文本并将其颜色设置为浅灰色来重置其占位符。
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.textColor == UIColor.lightGray {
textView.text = nil
textView.textColor = UIColor.black
}
}
解决方案#2-如果希望在文本视图为空时显示占位符,即使选择了文本视图也是如此:
首先在
viewDidLoad
中设置占位符:func textViewDidEndEditing(_ textView: UITextView) {
if textView.text.isEmpty {
textView.text = "Placeholder"
textView.textColor = UIColor.lightGray
}
}
(注意:由于OP希望在加载视图后立即选择文本视图,因此我将文本视图选择合并到了上面的代码中。期望的行为并且您不希望在加载视图时选择文本视图,请从上述代码块中删除最后两行。)
然后使用
shouldChangeTextInRange
UITextViewDelegate
方法,如下所示:textView.text = "Placeholder"
textView.textColor = UIColor.lightGray
textView.becomeFirstResponder()
textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
并且还实现了
textViewDidChangeSelection
以防止用户在占位符可见的情况下更改光标的位置。 (注意:textViewDidChangeSelection
在视图加载之前被调用,因此,如果窗口可见,则仅检查文本视图的颜色):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
}
评论
嗨,请确保将视图控制器设置为textView的委托。您可以通过创建从textView到viewController的出口来实现此目的。然后使用yourTextField.delegate = self。如果不这样做,则textViewDidBeginEditing和textViewDidEndEditing函数将不起作用。
– Ujjwal-Nadhani
16-4-23在17:05
代码未编译,出现错误,因为无法将类型“ NSRange”(也称为“ _NSRange”)的值转换为预期的参数类型“ Range
– iPeter
17年6月27日在15:02
我找到了解决方案,并将附加修订后的代码@iPeter。当前文本必须采用NSString格式:让currentText = textView.text作为NSString?。将let UpdatedText =行转换为letupdatedText = currentText?.replacingCharacters(in:range,with:text)。最后,将if updateText.isEmpty行转换为if(updatedText?.isEmpty)! {。这应该够了吧!
–贝勒·米切尔(Baylor Mitchell)
17年7月14日在22:21
@LyndseyScott在func textViewDidChangeSelection(_ textView:UITextView)中设置textView.selectedTextRange会导致无限循环...
– MikeG
19年2月5日在18:37
(iOS)开发人员需要如此简单的操作,实在令人震惊。这是很久以前应该已经在TextView控件中包含的基本功能,我不明白为什么Apple尚未解决此问题。
–肯尼
20年8月31日在13:01
#2 楼
浮动占位符
将占位符标签放置在文本视图上方,设置其字体,颜色并通过跟踪文本视图的更改来管理占位符可见性是简单,安全和可靠的字符数。
Swift 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:相同,除了:
italicSystemFontOfSize(textView.font.pointSize)
,UIColor.lightGrayColor
评论
不可否认,这种方法是我发现的最简单且最不容易出错的方法。极好。
–大卫
2015年2月3日,下午2:17
这是一个好方法,但是如果占位符文本很长,则标签文本可能会超出范围。
–问
2015年2月3日在7:02
简单易用,并与现有行为很好地集成在一起。无论如何,占位符消息不应太冗长,但是将行设置为0不会解决该问题吗?
–汤米C.
2015年11月4日13:59
我通常更喜欢这种方法,尽管如果文本居中对齐会出现问题,因为光标将位于占位符的顶部而不是其左侧的中心。
–blwinters
17年6月21日在15:31
@blwinters-那将是一个非常不寻常的极端情况,不是吗?但是,在这种情况下,假设它是一个多行输入字段(我必须假设),您难道不就调整垂直偏移量计算以将占位符文本稍微移开光标吗?
–clearlight
17-6-27在0:15
#3 楼
Swift:以编程方式或通过Interface Builder添加文本视图,如果是最后一个,则创建出口:
@IBOutlet weak var yourTextView: UITextView!
请添加委托( UITextViewDelegate):
class ViewController: UIViewController, UITextViewDelegate {
在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
现在让我介绍魔术部分,添加此功能:
func textViewDidBeginEditing(_ textView: UITextView) {
if yourTextView.textColor == UIColor.lightGray {
yourTextView.text = ""
yourTextView.textColor = UIColor.black
}
}
请注意,此操作将在编辑开始时执行,我们将使用color属性检查条件以告知状态。
我不建议将文本设置为
nil
。之后,我们将文本颜色设置为所需的颜色,在这种情况下为黑色。现在也添加此功能:
func textViewDidEndEditing(_ textView: UITextView) {
if yourTextView.text == "" {
yourTextView.text = "Placeholder text ..."
yourTextView.textColor = UIColor.lightGray
}
}
我坚持认为,请勿将其与
nil
进行比较,我已经尝试过了,但无法正常工作。然后,我们将这些值重新设置为占位符样式,并将颜色重新设置为占位符颜色,因为这是签入textViewDidBeginEditing
的条件。#4 楼
我很惊讶没有人提到NSTextStorageDelegate
。 UITextViewDelegate
的方法将仅由用户交互触发,而不会以编程方式触发。例如。当您以编程方式设置文本视图的text
属性时,必须自己设置占位符的可见性,因为不会调用委托方法。但是,使用
NSTextStorageDelegate
的textStorage(_:didProcessEditing:range:changeInLength:)
方法,您将即使对文字进行了更改,也会收到通知,即使该文字已通过编程方式完成。只需这样分配:textView.textStorage.delegate = self
(在
UITextView
中,此委托属性默认为nil
,因此不会影响任何默认行为。)通过@clearlight演示的
UILabel
技术进行组合,可以轻松地将整个UITextView
的placeholder
实现包装到扩展中。extension UITextView {
private class PlaceholderLabel: UILabel { }
private var placeholderLabel: PlaceholderLabel {
if let label = subviews.compactMap( { q4312078q as? PlaceholderLabel }).first {
return label
} else {
let label = PlaceholderLabel(frame: .zero)
label.font = font
addSubview(label)
return label
}
}
@IBInspectable
var placeholder: String {
get {
return subviews.compactMap( { q4312078q as? PlaceholderLabel }).first?.text ?? ""
}
set {
let placeholderLabel = self.placeholderLabel
placeholderLabel.text = newValue
placeholderLabel.numberOfLines = 0
let width = frame.width - textContainer.lineFragmentPadding * 2
let size = placeholderLabel.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude))
placeholderLabel.frame.size.height = size.height
placeholderLabel.frame.size.width = width
placeholderLabel.frame.origin = CGPoint(x: textContainer.lineFragmentPadding, y: textContainerInset.top)
textStorage.delegate = self
}
}
}
extension UITextView: NSTextStorageDelegate {
public func textStorage(_ textStorage: NSTextStorage, didProcessEditing editedMask: NSTextStorageEditActions, range editedRange: NSRange, changeInLength delta: Int) {
if editedMask.contains(.editedCharacters) {
placeholderLabel.isHidden = !text.isEmpty
}
}
}
请注意用法称为
PlaceholderLabel
的私有(嵌套)类的实例。它根本没有实现,但是它为我们提供了一种识别占位符标签的方法,该标签比使用tag
属性要“花哨得多”。 通过这种方法,您仍然可以将
UITextView
的委托分配给其他人。您甚至不必更改文本视图的类。只需添加扩展,就可以为项目中的每个
UITextView
分配一个占位符字符串,即使在Interface Builder中也是如此。 ,但可以再执行几行,并使用与placeholderColor
类似的计算变量。评论
非常优雅的解决方案。我喜欢它。
–戴夫·巴顿(Dave Batton)
18/12/30在19:35
textView.textStorage.delegate = self这在视图控制器中将需要我们将该视图控制器与NSTextStorageDelegate绑定。真的需要吗?
– Hemang
19年8月8日在8:21
简单而富有魅力。这是必须接受的答案
– Qaiser Abbas
19-09-14在8:01
@Hemang是文本视图本身是NSTextStorageDelegate,而不是视图控制器。
– yesleon
19-09-19在15:12
#5 楼
使用此扩展程序,这是在UITextView中设置占位符的最佳方法。但请确保已将委托附加到TextView。您可以这样设置占位符:-
yourTextView.placeholder = "Placeholder"
extension UITextView :UITextViewDelegate
{
/// Resize the placeholder when the UITextView bounds change
override open var bounds: CGRect {
didSet {
self.resizePlaceholder()
}
}
/// The UITextView placeholder text
public var placeholder: String? {
get {
var placeholderText: String?
if let placeholderLabel = self.viewWithTag(100) as? UILabel {
placeholderText = placeholderLabel.text
}
return placeholderText
}
set {
if let placeholderLabel = self.viewWithTag(100) as! UILabel? {
placeholderLabel.text = newValue
placeholderLabel.sizeToFit()
} else {
self.addPlaceholder(newValue!)
}
}
}
/// When the UITextView did change, show or hide the label based on if the UITextView is empty or not
///
/// - Parameter textView: The UITextView that got updated
public func textViewDidChange(_ textView: UITextView) {
if let placeholderLabel = self.viewWithTag(100) as? UILabel {
placeholderLabel.isHidden = self.text.characters.count > 0
}
}
/// Resize the placeholder UILabel to make sure it's in the same position as the UITextView text
private func resizePlaceholder() {
if let placeholderLabel = self.viewWithTag(100) as! UILabel? {
let labelX = self.textContainer.lineFragmentPadding
let labelY = self.textContainerInset.top - 2
let labelWidth = self.frame.width - (labelX * 2)
let labelHeight = placeholderLabel.frame.height
placeholderLabel.frame = CGRect(x: labelX, y: labelY, width: labelWidth, height: labelHeight)
}
}
/// Adds a placeholder UILabel to this UITextView
private func addPlaceholder(_ placeholderText: String) {
let placeholderLabel = UILabel()
placeholderLabel.text = placeholderText
placeholderLabel.sizeToFit()
placeholderLabel.font = self.font
placeholderLabel.textColor = UIColor.lightGray
placeholderLabel.tag = 100
placeholderLabel.isHidden = self.text.characters.count > 0
self.addSubview(placeholderLabel)
self.resizePlaceholder()
self.delegate = self
}
}
评论
像魅力一样工作!非常感谢你 ! :)
–纳希德·赖汉(Nahid Raihan)
18-10-17在4:19
亲爱的祝一切顺利
–山地ip
18-10-17在4:51
#6 楼
我通过使用两个不同的文本视图来做到这一点:背景中的一个用作占位符。
用户中的一个在前景(具有透明背景)
其想法是,一旦用户开始在前景视图中键入内容,背景中的占位符就会消失(如果用户删除所有内容,则占位符会再次出现)。因此,它的行为就像单行文本字段的占位符。
这是我使用的代码。请注意,descriptionField是用户键入的字段,descriptionPlaceholder是后台的字段。
func textViewDidChange(descriptionField: UITextView) {
if descriptionField.text.isEmpty == false {
descriptionPlaceholder.text = ""
} else {
descriptionPlaceholder.text = descriptionPlaceholderText
}
}
评论
这种方法有点笨拙,但却是最简单的方法,可以精确地生成您想要的结果。好主意
– William T.
17年6月11日在18:14
#7 楼
基于这里的一些重要建议,我能够将UITextView
的以下轻量级,与Interface-Builder兼容的子类放到一起,其中:像UITextField
一样。不需要任何其他子视图或约束。
不需要ViewController的任何委派或其他行为。
不需要任何通知。
>请保持文本与查看该字段的
text
属性的所有外部类完全分开。 Swift v5:
import UIKit
@IBDesignable class TextViewWithPlaceholder: UITextView {
override var text: String! { // Ensures that the placeholder text is never returned as the field's text
get {
if showingPlaceholder {
return "" // When showing the placeholder, there's no real text to return
} else { return super.text }
}
set { super.text = newValue }
}
@IBInspectable var placeholderText: String = ""
@IBInspectable var placeholderTextColor: UIColor = UIColor(red: 0.78, green: 0.78, blue: 0.80, alpha: 1.0) // Standard iOS placeholder color (#C7C7CD). See https://stackoverflow.com/questions/31057746/whats-the-default-color-for-placeholder-text-in-uitextfield
private var showingPlaceholder: Bool = true // Keeps track of whether the field is currently showing a placeholder
override func didMoveToWindow() {
super.didMoveToWindow()
if text.isEmpty {
showPlaceholderText() // Load up the placeholder text when first appearing, but not if coming back to a view where text was already entered
}
}
override func becomeFirstResponder() -> Bool {
// If the current text is the placeholder, remove it
if showingPlaceholder {
text = nil
textColor = nil // Put the text back to the default, unmodified color
showingPlaceholder = false
}
return super.becomeFirstResponder()
}
override func resignFirstResponder() -> Bool {
// If there's no text, put the placeholder back
if text.isEmpty {
showPlaceholderText()
}
return super.resignFirstResponder()
}
private func showPlaceholderText() {
showingPlaceholder = true
textColor = placeholderTextColor
text = placeholderText
}
}
#8 楼
我试图从clearlight的答案中简化代码。extension UITextView{
func setPlaceholder() {
let placeholderLabel = UILabel()
placeholderLabel.text = "Enter some text..."
placeholderLabel.font = UIFont.italicSystemFont(ofSize: (self.font?.pointSize)!)
placeholderLabel.sizeToFit()
placeholderLabel.tag = 222
placeholderLabel.frame.origin = CGPoint(x: 5, y: (self.font?.pointSize)! / 2)
placeholderLabel.textColor = UIColor.lightGray
placeholderLabel.isHidden = !self.text.isEmpty
self.addSubview(placeholderLabel)
}
func checkPlaceholder() {
let placeholderLabel = self.viewWithTag(222) as! UILabel
placeholderLabel.isHidden = !self.text.isEmpty
}
}
用法
override func viewDidLoad() {
textView.delegate = self
textView.setPlaceholder()
}
func textViewDidChange(_ textView: UITextView) {
textView.checkPlaceholder()
}
评论
有几个问题。 (1)作为假定并“借用” UIView标签属性值的扩展,有人可能会在自己的视图层次结构中使用相同的标签,而没有意识到该扩展的用法,从而造成极其难以诊断的错误。诸如此类的事情不属于库代码或扩展名。 (2)仍然要求调用者声明一个委托。浮动占位符可避免黑客入侵,占地面积小,简单且完全本地化,这是一个安全的选择。
–clearlight
17年2月28日在8:24
#9 楼
在视图负载中设置SET值 txtVw!.autocorrectionType = UITextAutocorrectionType.No
txtVw!.text = "Write your Placeholder"
txtVw!.textColor = UIColor.lightGrayColor()
func textViewDidBeginEditing(textView: UITextView) {
if (txtVw?.text == "Write your Placeholder")
{
txtVw!.text = nil
txtVw!.textColor = UIColor.blackColor()
}
}
func textViewDidEndEditing(textView: UITextView) {
if txtVw!.text.isEmpty
{
txtVw!.text = "Write your Placeholder"
txtVw!.textColor = UIColor.lightGrayColor()
}
textView.resignFirstResponder()
}
#10 楼
另一种解决方案(快速3):import UIKit
protocol PlaceholderTextViewDelegate {
func placeholderTextViewDidChangeText(_ text:String)
func placeholderTextViewDidEndEditing(_ text:String)
}
final class PlaceholderTextView: UITextView {
var notifier:PlaceholderTextViewDelegate?
var placeholder: String? {
didSet {
placeholderLabel?.text = placeholder
}
}
var placeholderColor = UIColor.lightGray
var placeholderFont = UIFont.appMainFontForSize(14.0) {
didSet {
placeholderLabel?.font = placeholderFont
}
}
fileprivate var placeholderLabel: UILabel?
// MARK: - LifeCycle
init() {
super.init(frame: CGRect.zero, textContainer: nil)
awakeFromNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
self.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(PlaceholderTextView.textDidChangeHandler(notification:)), name: .UITextViewTextDidChange, object: nil)
placeholderLabel = UILabel()
placeholderLabel?.textColor = placeholderColor
placeholderLabel?.text = placeholder
placeholderLabel?.textAlignment = .left
placeholderLabel?.numberOfLines = 0
}
override func layoutSubviews() {
super.layoutSubviews()
placeholderLabel?.font = placeholderFont
var height:CGFloat = placeholderFont.lineHeight
if let data = placeholderLabel?.text {
let expectedDefaultWidth:CGFloat = bounds.size.width
let fontSize:CGFloat = placeholderFont.pointSize
let textView = UITextView()
textView.text = data
textView.font = UIFont.appMainFontForSize(fontSize)
let sizeForTextView = textView.sizeThatFits(CGSize(width: expectedDefaultWidth,
height: CGFloat.greatestFiniteMagnitude))
let expectedTextViewHeight = sizeForTextView.height
if expectedTextViewHeight > height {
height = expectedTextViewHeight
}
}
placeholderLabel?.frame = CGRect(x: 5, y: 0, width: bounds.size.width - 16, height: height)
if text.isEmpty {
addSubview(placeholderLabel!)
bringSubview(toFront: placeholderLabel!)
} else {
placeholderLabel?.removeFromSuperview()
}
}
func textDidChangeHandler(notification: Notification) {
layoutSubviews()
}
}
extension PlaceholderTextView : UITextViewDelegate {
// MARK: - UITextViewDelegate
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if(text == "\n") {
textView.resignFirstResponder()
return false
}
return true
}
func textViewDidChange(_ textView: UITextView) {
notifier?.placeholderTextViewDidChangeText(textView.text)
}
func textViewDidEndEditing(_ textView: UITextView) {
notifier?.placeholderTextViewDidEndEditing(textView.text)
}
}
结果
#11 楼
这是我完成这项工作所使用的。@IBDesignable class UIPlaceholderTextView: UITextView {
var placeholderLabel: UILabel?
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
sharedInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
sharedInit()
}
override func prepareForInterfaceBuilder() {
sharedInit()
}
func sharedInit() {
refreshPlaceholder()
NotificationCenter.default.addObserver(self, selector: #selector(textChanged), name: UITextView.textDidChangeNotification, object: nil)
}
@IBInspectable var placeholder: String? {
didSet {
refreshPlaceholder()
}
}
@IBInspectable var placeholderColor: UIColor? = .darkGray {
didSet {
refreshPlaceholder()
}
}
@IBInspectable var placeholderFontSize: CGFloat = 14 {
didSet {
refreshPlaceholder()
}
}
func refreshPlaceholder() {
if placeholderLabel == nil {
placeholderLabel = UILabel()
let contentView = self.subviews.first ?? self
contentView.addSubview(placeholderLabel!)
placeholderLabel?.translatesAutoresizingMaskIntoConstraints = false
placeholderLabel?.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: textContainerInset.left + 4).isActive = true
placeholderLabel?.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: textContainerInset.right + 4).isActive = true
placeholderLabel?.topAnchor.constraint(equalTo: contentView.topAnchor, constant: textContainerInset.top).isActive = true
placeholderLabel?.bottomAnchor.constraint(lessThanOrEqualTo: contentView.bottomAnchor, constant: textContainerInset.bottom)
}
placeholderLabel?.text = placeholder
placeholderLabel?.textColor = placeholderColor
placeholderLabel?.font = UIFont.systemFont(ofSize: placeholderFontSize)
}
@objc func textChanged() {
if self.placeholder?.isEmpty ?? true {
return
}
UIView.animate(withDuration: 0.25) {
if self.text.isEmpty {
self.placeholderLabel?.alpha = 1.0
} else {
self.placeholderLabel?.alpha = 0.0
}
}
}
override var text: String! {
didSet {
textChanged()
}
}
}
我知道有几种类似的方法,但是这种方法的好处是它可以:
在IB中设置占位符文本,字体大小和颜色。
不再在IB中显示“滚动视图具有模糊的可滚动内容”警告。
添加动画以显示/隐藏占位符。
#12 楼
Swift 3.2extension EditProfileVC:UITextViewDelegate{
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.textColor == UIColor.lightGray {
textView.text = nil
textView.textColor = UIColor.black
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text.isEmpty {
textView.text = "Placeholder"
textView.textColor = UIColor.lightGray
}
}
}
首先,当用户开始编辑textViewDidBeginEditing调用,然后检查文本的颜色是否为灰色表示用户未写任何东西时,将其设置为textview nil并更改颜色为黑色以供用户发短信。
当调用用户端编辑textViewDidEndEditing并检查用户是否未在textview中编写任何内容时,则将文本设置为灰色,并带有文本“ PlaceHolder”
评论
用更少的代码看起来更短,最简单
–罗马·罗曼年科
20-6-28在19:59
#13 楼
一个对我有用的简单快速的解决方案是:@IBDesignable
class PlaceHolderTextView: UITextView {
@IBInspectable var placeholder: String = "" {
didSet{
updatePlaceHolder()
}
}
@IBInspectable var placeholderColor: UIColor = UIColor.gray {
didSet {
updatePlaceHolder()
}
}
private var originalTextColor = UIColor.darkText
private var originalText: String = ""
private func updatePlaceHolder() {
if self.text == "" || self.text == placeholder {
self.text = placeholder
self.textColor = placeholderColor
if let color = self.textColor {
self.originalTextColor = color
}
self.originalText = ""
} else {
self.textColor = self.originalTextColor
self.originalText = self.text
}
}
override func becomeFirstResponder() -> Bool {
let result = super.becomeFirstResponder()
self.text = self.originalText
self.textColor = self.originalTextColor
return result
}
override func resignFirstResponder() -> Bool {
let result = super.resignFirstResponder()
updatePlaceHolder()
return result
}
}
#14 楼
这是我解决此问题的方法(Swift 4):我们的想法是提供最简单的解决方案,该解决方案允许使用不同颜色的占位符,将其大小调整为占位符的大小,同时不会覆盖
delegate
保持所有UITextView
功能正常运行。import UIKit
class PlaceholderTextView: UITextView {
var placeholderColor: UIColor = .lightGray
var defaultTextColor: UIColor = .black
private var isShowingPlaceholder = false {
didSet {
if isShowingPlaceholder {
text = placeholder
textColor = placeholderColor
} else {
textColor = defaultTextColor
}
}
}
var placeholder: String? {
didSet {
isShowingPlaceholder = !hasText
}
}
@objc private func textViewDidBeginEditing(notification: Notification) {
textColor = defaultTextColor
if isShowingPlaceholder { text = nil }
}
@objc private func textViewDidEndEditing(notification: Notification) {
isShowingPlaceholder = !hasText
}
// MARK: - Construction -
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
private func setup() {
NotificationCenter.default.addObserver(self, selector: #selector(textViewDidBeginEditing(notification:)), name: UITextView.textDidBeginEditingNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(textViewDidEndEditing(notification:)), name: UITextView.textDidEndEditingNotification, object: nil)
}
// MARK: - Destruction -
deinit { NotificationCenter.default.removeObserver(self) }
}
评论
这是一个很棒且简单的解决方案。
– JaredH
19年4月3日在21:01
#15 楼
Swift Answer这是定制占位符的动画类。
class CustomTextView: UITextView {
// MARK: - public
public var placeHolderText: String? = "Enter Reason.."
public lazy var placeHolderLabel: UILabel! = {
let placeHolderLabel = UILabel(frame: .zero)
placeHolderLabel.numberOfLines = 0
placeHolderLabel.backgroundColor = .clear
placeHolderLabel.alpha = 0.5
return placeHolderLabel
}()
// MARK: - Init
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
enableNotifications()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
enableNotifications()
}
func setup() {
placeHolderLabel.frame = CGRect(x: 8, y: 8, width: self.bounds.size.width - 16, height: 15)
placeHolderLabel.sizeToFit()
}
// MARK: - Cycle
override func awakeFromNib() {
super.awakeFromNib()
textContainerInset = UIEdgeInsets(top: 8, left: 5, bottom: 8, right: 8)
returnKeyType = .done
addSubview(placeHolderLabel)
placeHolderLabel.frame = CGRect(x: 8, y: 8, width: self.bounds.size.width - 16, height: 15)
placeHolderLabel.textColor = textColor
placeHolderLabel.font = font
placeHolderLabel.text = placeHolderText
bringSubviewToFront(placeHolderLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
// MARK: - Notifications
private func enableNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(textDidChangeNotification(_:)), name: UITextView.textDidChangeNotification , object: nil)
}
@objc func textDidChangeNotification(_ notify: Notification) {
guard self == notify.object as? UITextView else { return }
guard placeHolderText != nil else { return }
UIView.animate(withDuration: 0.25, animations: {
self.placeHolderLabel.alpha = (self.text.count == 0) ? 0.5 : 0
}, completion: nil)
}
}
#16 楼
我不知道为什么人们会过多地使这个问题复杂化……。这非常简单明了。这是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];
}`
评论
仅供参考,在有人击败我之前……这很直接地转化为Swift。这里没什么复杂的。
–TheCodingArt
15年8月11日在21:33
#17 楼
如果您正在使用多个文本视图,这是我准备使用的解决方案func textViewShouldBeginEditing(textView: UITextView) -> Bool {
// Set cursor to the beginning if placeholder is set
if textView.textColor == UIColor.lightGrayColor() {
textView.selectedTextRange = textView.textRangeFromPosition(textView.beginningOfDocument, toPosition: textView.beginningOfDocument)
}
return true
}
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
// Remove placeholder
if textView.textColor == UIColor.lightGrayColor() && text.characters.count > 0 {
textView.text = ""
textView.textColor = UIColor.blackColor()
}
if text == "\n" {
textView.resignFirstResponder()
return false
}
return true
}
func textViewDidChange(textView: UITextView) {
// Set placeholder if text is empty
if textView.text.isEmpty {
textView.text = NSLocalizedString("Hint", comment: "hint")
textView.textColor = UIColor.lightGrayColor()
textView.selectedTextRange = textView.textRangeFromPosition(textView.beginningOfDocument, toPosition: textView.beginningOfDocument)
}
}
func textViewDidChangeSelection(textView: UITextView) {
// Set cursor to the beginning if placeholder is set
let firstPosition = textView.textRangeFromPosition(textView.beginningOfDocument, toPosition: textView.beginningOfDocument)
// Do not change position recursively
if textView.textColor == UIColor.lightGrayColor() && textView.selectedTextRange != firstPosition {
textView.selectedTextRange = firstPosition
}
}
评论
这是很不错的!
– KevinVuD
18年5月26日在11:03
#18 楼
Swift 3.1此扩展名对我有效:https://github.com/devxoul/UITextView-Placeholder
这是一个代码段: />通过pod安装:
pod 'UITextView+Placeholder', '~> 1.2'
将其导入您的课程
import UITextView_Placeholder
并添加
placeholder
属性到已经创建的UITextView
textView.placeholder = "Put some detail"
就这样...
它的外观(第三盒是
UITextView
) >#19 楼
Swift:添加您的
TextView
@IBOutlet
:@IBOutlet weak var txtViewMessage: UITextView!
在
viewWillAppear
方法中,添加以下内容: override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
txtViewMessage.delegate = self // Give TextViewMessage delegate Method
txtViewMessage.text = "Place Holder Name"
txtViewMessage.textColor = UIColor.lightGray
}
请添加
Delegate
使用扩展名(UITextViewDelegate):// MARK: - UITextViewDelegate
extension ViewController: UITextViewDelegate
{
func textViewDidBeginEditing(_ textView: UITextView)
{
if !txtViewMessage.text!.isEmpty && txtViewMessage.text! == "Place Holder Name"
{
txtViewMessage.text = ""
txtViewMessage.textColor = UIColor.black
}
}
func textViewDidEndEditing(_ textView: UITextView)
{
if txtViewMessage.text.isEmpty
{
txtViewMessage.text = "Place Holder Name"
txtViewMessage.textColor = UIColor.lightGray
}
}
}
#20 楼
与本文上的每个答案相反,UITextView
确实具有占位符属性。出于超出我的理解范围的原因,它仅在IB中公开,如下所示:在检查员上。 您还可以在这样的代码中设置此属性:属性已公开。
我没有尝试使用此方法提交。但是我很快就会以这种方式提交,并将相应地更新此答案。 >
更新:
这仅适用于Xcode 11.2以下版本
评论
在Swift 5中,您可以编写myTextView,placeholder =“输入您的眼睛颜色”
–user462990
19年4月19日在10:44
@ user462990您可以为此提供文档链接吗?我不认为这是正确的。
– Alex Chase
19年4月24日在20:09
抱歉,没有找到dox,但是它确实很容易测试……例如,“ alert.addTextField {(textField3.placeholder = language.JBLocalize(phrase:“ yourName”)}}中的。串
–user462990
19年4月26日12:00
@ user462990您引用的是UITextField而不是UITextView,请更仔细地阅读问题/回答。
– Alex Chase
19年5月1日,0:22
很好的解决方案,但对我不起作用。它总是以某种方式崩溃。您能指定正在使用的部署目标,swift和xCode版本吗?
– T. Pasichnyk
19年8月15日在12:20
#21 楼
Swift 5.2独立类
如果您想要一个可以在任何地方使用的类,请使用此类,因为它是独立的
import UIKit
class PlaceHolderTextView:UITextView, UITextViewDelegate{
var placeholderText = "placeholderText"
override func willMove(toSuperview newSuperview: UIView?) {
textColor = .lightText
delegate = self
}
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.text == placeholderText{
placeholderText = textView.text
textView.text = ""
textView.textColor = .darkText
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text == ""{
textView.text = placeholderText
textColor = .lightText
}
}
}
这里的关键是
willMove(toSuperView:)
函数,因为它允许您在将视图添加到另一个视图的层次结构之前对其进行设置(类似于ViewControllers中的viewDidLoad / viewWillAppear)#22 楼
无需添加任何第三方库。只需使用下面的代码...class SubmitReviewVC : UIViewController, UITextViewDelegate {
@IBOutlet var txtMessage : UITextView!
var lblPlaceHolder : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
txtMessage.delegate = self
lblPlaceHolder = UILabel()
lblPlaceHolder.text = "Enter message..."
lblPlaceHolder.font = UIFont.systemFont(ofSize: txtMessage.font!.pointSize)
lblPlaceHolder.sizeToFit()
txtMessage.addSubview(lblPlaceHolder)
lblPlaceHolder.frame.origin = CGPoint(x: 5, y: (txtMessage.font?.pointSize)! / 2)
lblPlaceHolder.textColor = UIColor.lightGray
lblPlaceHolder.isHidden = !txtMessage.text.isEmpty
}
func textViewDidChange(_ textView: UITextView) {
lblPlaceHolder.isHidden = !textView.text.isEmpty
}
#23 楼
ios中没有此类属性可直接在TextView中添加占位符,而是可以添加标签并在textView中的更改上显示/隐藏。 SWIFT 2.0并确保实现textviewdelegatefunc textViewDidChange(TextView: UITextView)
{
if txtShortDescription.text == ""
{
self.lblShortDescription.hidden = false
}
else
{
self.lblShortDescription.hidden = true
}
}
#24 楼
Swift-我编写了一个继承UITextView的类,并添加了UILabel作为子视图以充当占位符。 import UIKit
@IBDesignable
class HintedTextView: UITextView {
@IBInspectable var hintText: String = "hintText" {
didSet{
hintLabel.text = hintText
}
}
private lazy var hintLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFontOfSize(16)
label.textColor = UIColor.lightGrayColor()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setupView()
}
private func setupView() {
translatesAutoresizingMaskIntoConstraints = false
delegate = self
font = UIFont.systemFontOfSize(16)
addSubview(hintLabel)
NSLayoutConstraint.activateConstraints([
hintLabel.leftAnchor.constraintEqualToAnchor(leftAnchor, constant: 4),
hintLabel.rightAnchor.constraintEqualToAnchor(rightAnchor, constant: 8),
hintLabel.topAnchor.constraintEqualToAnchor(topAnchor, constant: 4),
hintLabel.heightAnchor.constraintEqualToConstant(30)
])
}
override func layoutSubviews() {
super.layoutSubviews()
setupView()
}
}
评论
使用约束来定位占位符的一个很好的例子,但是占位符的理想位置就在文本的第一个字符将要到达的位置的正上方,因此基于文本视图的字体来计算该位置会更好,因为它可以适应设置为文本视图设置的任何字体大小。
–clearlight
16 Dec 10'在0:02
#25 楼
我喜欢@nerdist的解决方案。基于此,我创建了对UITextView
的扩展:例如,在ViewController类中,这是我的使用方法:import Foundation
import UIKit
extension UITextView
{
private func add(_ placeholder: UILabel) {
for view in self.subviews {
if let lbl = view as? UILabel {
if lbl.text == placeholder.text {
lbl.removeFromSuperview()
}
}
}
self.addSubview(placeholder)
}
func addPlaceholder(_ placeholder: UILabel?) {
if let ph = placeholder {
ph.numberOfLines = 0 // support for multiple lines
ph.font = UIFont.italicSystemFont(ofSize: (self.font?.pointSize)!)
ph.sizeToFit()
self.add(ph)
ph.frame.origin = CGPoint(x: 5, y: (self.font?.pointSize)! / 2)
ph.textColor = UIColor(white: 0, alpha: 0.3)
updateVisibility(ph)
}
}
func updateVisibility(_ placeHolder: UILabel?) {
if let ph = placeHolder {
ph.isHidden = !self.text.isEmpty
}
}
}
UITextview上的占位符!
更新:
如果在代码中更改textview的文本,记得调用updateVisibitly方法来隐藏占位符:
class MyViewController: UIViewController, UITextViewDelegate {
private var notePlaceholder: UILabel!
@IBOutlet weak var txtNote: UITextView!
...
// UIViewController
override func viewDidLoad() {
notePlaceholder = UILabel()
notePlaceholder.text = "title\nsubtitle\nmore..."
txtNote.addPlaceholder(notePlaceholder)
...
}
// UITextViewDelegate
func textViewDidChange(_ textView: UITextView) {
txtNote.updateVisbility(notePlaceholder)
...
}
为防止多次添加占位符,在
add()
中添加了一个私有的extension
函数。评论
再次感谢您对原始内容的改进。我在这个周末花了很多时间,但我想您会喜欢我最终想出的EZ Placeholder极限变体:stackoverflow.com/a/41081244/2079103(我为您对开发占位符解决方案)
–clearlight
16 Dec 12'在17:16
#26 楼
在swift2.2中:public class CustomTextView: UITextView {
private struct Constants {
static let defaultiOSPlaceholderColor = UIColor(red: 0.0, green: 0.0, blue: 0.0980392, alpha: 0.22)
}
private let placeholderLabel: UILabel = UILabel()
private var placeholderLabelConstraints = [NSLayoutConstraint]()
@IBInspectable public var placeholder: String = "" {
didSet {
placeholderLabel.text = placeholder
}
}
@IBInspectable public var placeholderColor: UIColor = CustomTextView.Constants.defaultiOSPlaceholderColor {
didSet {
placeholderLabel.textColor = placeholderColor
}
}
override public var font: UIFont! {
didSet {
placeholderLabel.font = font
}
}
override public var textAlignment: NSTextAlignment {
didSet {
placeholderLabel.textAlignment = textAlignment
}
}
override public var text: String! {
didSet {
textDidChange()
}
}
override public var attributedText: NSAttributedString! {
didSet {
textDidChange()
}
}
override public var textContainerInset: UIEdgeInsets {
didSet {
updateConstraintsForPlaceholderLabel()
}
}
override public init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
commonInit()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(textDidChange),
name: UITextViewTextDidChangeNotification,
object: nil)
placeholderLabel.font = font
placeholderLabel.textColor = placeholderColor
placeholderLabel.textAlignment = textAlignment
placeholderLabel.text = placeholder
placeholderLabel.numberOfLines = 0
placeholderLabel.backgroundColor = UIColor.clearColor()
placeholderLabel.translatesAutoresizingMaskIntoConstraints = false
addSubview(placeholderLabel)
updateConstraintsForPlaceholderLabel()
}
private func updateConstraintsForPlaceholderLabel() {
var newConstraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|-(\(textContainerInset.left + textContainer.lineFragmentPadding))-[placeholder]",
options: [],
metrics: nil,
views: ["placeholder": placeholderLabel])
newConstraints += NSLayoutConstraint.constraintsWithVisualFormat("V:|-(\(textContainerInset.top))-[placeholder]",
options: [],
metrics: nil,
views: ["placeholder": placeholderLabel])
newConstraints.append(NSLayoutConstraint(
item: placeholderLabel,
attribute: .Width,
relatedBy: .Equal,
toItem: self,
attribute: .Width,
multiplier: 1.0,
constant: -(textContainerInset.left + textContainerInset.right + textContainer.lineFragmentPadding * 2.0)
))
removeConstraints(placeholderLabelConstraints)
addConstraints(newConstraints)
placeholderLabelConstraints = newConstraints
}
@objc private func textDidChange() {
placeholderLabel.hidden = !text.isEmpty
}
public override func layoutSubviews() {
super.layoutSubviews()
placeholderLabel.preferredMaxLayoutWidth = textContainer.size.width - textContainer.lineFragmentPadding * 2.0
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self,
name: UITextViewTextDidChangeNotification,
object: nil)
}
}
在swift3中:
import UIKit
类CustomTextView:UITextView {
private struct Constants {
static let defaultiOSPlaceholderColor = UIColor(red: 0.0, green: 0.0, blue: 0.0980392, alpha: 0.22)
}
private let placeholderLabel: UILabel = UILabel()
private var placeholderLabelConstraints = [NSLayoutConstraint]()
@IBInspectable public var placeholder: String = "" {
didSet {
placeholderLabel.text = placeholder
}
}
@IBInspectable public var placeholderColor: UIColor = CustomTextView.Constants.defaultiOSPlaceholderColor {
didSet {
placeholderLabel.textColor = placeholderColor
}
}
override public var font: UIFont! {
didSet {
placeholderLabel.font = font
}
}
override public var textAlignment: NSTextAlignment {
didSet {
placeholderLabel.textAlignment = textAlignment
}
}
override public var text: String! {
didSet {
textDidChange()
}
}
override public var attributedText: NSAttributedString! {
didSet {
textDidChange()
}
}
override public var textContainerInset: UIEdgeInsets {
didSet {
updateConstraintsForPlaceholderLabel()
}
}
override public init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
commonInit()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
NotificationCenter.default.addObserver(self,
selector: #selector(textDidChange),
name: NSNotification.Name.UITextViewTextDidChange,
object: nil)
placeholderLabel.font = font
placeholderLabel.textColor = placeholderColor
placeholderLabel.textAlignment = textAlignment
placeholderLabel.text = placeholder
placeholderLabel.numberOfLines = 0
placeholderLabel.backgroundColor = UIColor.clear
placeholderLabel.translatesAutoresizingMaskIntoConstraints = false
addSubview(placeholderLabel)
updateConstraintsForPlaceholderLabel()
}
private func updateConstraintsForPlaceholderLabel() {
var newConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-(\(textContainerInset.left + textContainer.lineFragmentPadding))-[placeholder]",
options: [],
metrics: nil,
views: ["placeholder": placeholderLabel])
newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-(\(textContainerInset.top))-[placeholder]",
options: [],
metrics: nil,
views: ["placeholder": placeholderLabel])
newConstraints.append(NSLayoutConstraint(
item: placeholderLabel,
attribute: .width,
relatedBy: .equal,
toItem: self,
attribute: .width,
multiplier: 1.0,
constant: -(textContainerInset.left + textContainerInset.right + textContainer.lineFragmentPadding * 2.0)
))
removeConstraints(placeholderLabelConstraints)
addConstraints(newConstraints)
placeholderLabelConstraints = newConstraints
}
@objc private func textDidChange() {
placeholderLabel.isHidden = !text.isEmpty
}
public override func layoutSubviews() {
super.layoutSubviews()
placeholderLabel.preferredMaxLayoutWidth = textContainer.size.width - textContainer.lineFragmentPadding * 2.0
}
deinit {
NotificationCenter.default.removeObserver(self,
name: NSNotification.Name.UITextViewTextDidChange,
object: nil)
}
}
我迅速编写了一个类。您需要在需要时导入此类。
#27 楼
由于声誉,我无法添加评论。在@clearlight答案中再添加一个委托需要。func textViewDidBeginEditing(_ textView: UITextView) {
cell.placeholderLabel.isHidden = !textView.text.isEmpty
}
是需要的
,因为第一次不调用
textViewDidChange
#28 楼
不,没有任何占位符可用于textview。您必须在用户进入文本视图时在其上方放置标签,然后将其隐藏或在用户输入时将其默认设置为删除所有值。#29 楼
func setPlaceholder(){
var placeholderLabel = UILabel()
placeholderLabel.text = "Describe your need..."
placeholderLabel.font = UIFont.init(name: "Lato-Regular", size: 15.0) ?? UIFont.boldSystemFont(ofSize: 14.0)
placeholderLabel.sizeToFit()
descriptionTextView.addSubview(placeholderLabel)
placeholderLabel.frame.origin = CGPoint(x: 5, y: (descriptionTextView.font?.pointSize)! / 2)
placeholderLabel.textColor = UIColor.lightGray
placeholderLabel.isHidden = !descriptionTextView.text.isEmpty
}
//Delegate Method.
func textViewDidChange(_ textView: UITextView) {
placeholderLabel.isHidden = !textView.text.isEmpty
}
#30 楼
编辑完成后,我不得不分派队列以使我的占位符文本重新出现。评论
如果我希望该值成为用户键入的内容,我应该键入什么而不是最后一行“ textView.text =” Description”?
–ISS
'18 Sep 6'在10:56
评论
在使用UITextView进行iOS开发中,这是一个古老的问题。我已经编写了类似于此处提到的子类的子类:stackoverflow.com/a/1704469/1403046。好处是您仍然可以拥有一个委托,并且可以在多个地方使用该类而不必重新实现逻辑。在为项目使用swift的同时,我将如何使用您的子类。使用桥文件?
您可以这样做,也可以在Swift中重新实现。答案中的代码比实际需要的更长。重点是显示/隐藏在文本更改时得到通知的方法中添加的标签。
您可以使用来自GitHub的UIFloatLabelTextView示例。书写时,此位置占位符位于顶部。真的很有趣! github.com/ArtSabintsev/UIFloatLabelTextView
老实说,最简单的方法是拥有一个自定义的textView并仅添加占位符文本,当文本不存在时将其绘制到textView上。状态管理(包括当文本应该/不应该/不存在时的误报)