如何在UITextView中添加占位符,类似于你可以为UITextField设置的占位符,在Swift中?


当前回答

无需添加任何第三方库。只需使用下面的代码…

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
}

}

其他回答

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

}

我用swift写了一个类。您需要在需要的时候导入这个类。

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 answer中增加一个委托需求。

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

是需要

因为textViewDidChange不是第一次被调用

斯威夫特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)

文本视图委托方法

使用这两个委托方法,并在类中编写UITextViewDelegate

func textViewDidBeginEditing(_ textView: UITextView) {
    if (commentsTextView.text == "Type Your Comments")
    {
        commentsTextView.text = nil
        commentsTextView.textColor = UIColor.darkGray
    }
}

func textViewDidEndEditing(_ textView: UITextView) {
    if commentsTextView.text.isEmpty
    {
        commentsTextView.text = "Type Your Comments"
        commentsTextView.textColor = UIColor.darkGray
    }
    textView.resignFirstResponder()
}