UITextView 设置 PlaceHolder

在日常开发中时常会遇到为 TextView 设置placeholder 的需求。 基本的思想是这个样子的: 1.在 UITextView 的左上角上放一个 UILabel,让 UILabel 的 text 来作为 UITextView的 placeholder; 2.为 UITextView添加一个通知NotificationCenter,监听 UITextView 中值得变化; 3.UITextView 的值发生变化就把UILabel 隐藏或者显示。

来贴代码:(代码中有很详细的注释,如果使用的话可以直接新建一个文件把代码粘贴过去就可以了) Demo 在此

import UIKit

// @IBDesignable 可以让自定义的这个 view 在 Xib 中使用
@IBDesignable
public class YHYPlaceholderTextView: UITextView {
	
	// 默认的占位字的颜色
    private struct Constants {
        static let defaultiOSPlaceholderColor = UIColor(red: 179/255, green: 179/255, blue: 179/255, alpha: 0.2)
    }
	
	// 占位 label
    public let placeholderLabel: UILabel = UILabel()
	
	// 使用 AutoLayout 的约束集合
    private var placeholderLabelConstraints = [NSLayoutConstraint]()
	
	// @IBInspectable xib 中可以设置这些属性  这个属性是 text
    @IBInspectable public var placeholder: String = "" {
        didSet {
            placeholderLabel.text = placeholder
        }
    }
	
	// placeholder 的颜色,有默认值 defaultiOSPlaceholderColor
    @IBInspectable public var placeholderColor: UIColor = YHYPlaceholderTextView.Constants.defaultiOSPlaceholderColor {
        didSet {
            placeholderLabel.textColor = placeholderColor
        }
    }
	
	// textView 的字体大小重写, 默认placeholder 的字体大小和 textView一样
    override public var font: UIFont! {
        didSet {
            if placeholderFont == nil {
                placeholderLabel.font = font
            }
        }
    }
	
	//	placeholder 的字体大小
    public var placeholderFont: UIFont? {
        didSet {
            let font = (placeholderFont != nil) ? placeholderFont : self.font
            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()
        }
    }
	
	// 设置 UIlabel 的位置约束
    override public var textContainerInset: UIEdgeInsets {
        didSet {
            updateConstraintsForPlaceholderLabel()
        }
    }
	
	// 初始化的时候 添加通知,和作为placeholder的UILabel
    override public init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        commonInit()
    }
	
	// 初始化的时候 添加通知,和作为placeholder的UILabel
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }
	
	// 初始化的时候 添加通知,和作为placeholder的UILabel
    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)
		// 添加 UILabel 的约束
        updateConstraintsForPlaceholderLabel()
    }
	
	// AutoLayout 添加约束
    private func updateConstraintsForPlaceholderLabel() {
		// 水平方向上 placeholderLabel 距离 textView 的左边距离为 textContainerInset.left + textContainer.lineFragmentPadding
        var newConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-(\(textContainerInset.left + textContainer.lineFragmentPadding))-[placeholder]",
            options: [],
            metrics: nil,
            views: ["placeholder": placeholderLabel])
		
		// 竖直方向上 placeholderLabel 距离 textView 的上边距离为textContainerInset.top
        newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-(\(textContainerInset.top))-[placeholder]",
            options: [],
            metrics: nil,
            views: ["placeholder": placeholderLabel])
		
		// placeholderLabel 的宽和 self 的宽的比例约束 注意是有 constant的
        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
    }
	
	// 根据 textView 的编辑情况,隐藏或者显示作为placeholder的UILabel
    @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)
    }
    
}

复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值