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


当前回答

我相信这是一个非常干净的解决方案。它在实际文本视图下面添加了一个虚拟文本视图,并根据实际文本视图中的文本显示或隐藏它:

import Foundation
import UIKit

class TextViewWithPlaceholder: UITextView {

    private var placeholderTextView: UITextView = UITextView()

    var placeholder: String? {
        didSet {
            placeholderTextView.text = placeholder
        }
    }

    override var text: String! {
        didSet {
            placeholderTextView.isHidden = text.isEmpty == false
        }
    }

    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    private func commonInit() {
        applyCommonTextViewAttributes(to: self)
        configureMainTextView()
        addPlaceholderTextView()
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(textDidChange),
                                               name: UITextView.textDidChangeNotification,
                                               object: nil)
    }

    func addPlaceholderTextView() {
        applyCommonTextViewAttributes(to: placeholderTextView)
        configurePlaceholderTextView()
        insertSubview(placeholderTextView, at: 0)
    }

    private func applyCommonTextViewAttributes(to textView: UITextView) {
        textView.translatesAutoresizingMaskIntoConstraints = false
        textView.textContainer.lineFragmentPadding = 0
        textView.textContainerInset = UIEdgeInsets(top: 10,
                                                   left: 10,
                                                   bottom: 10,
                                                   right: 10)
    }

    private func configureMainTextView() {
        // Do any configuration of the actual text view here
    }

    private func configurePlaceholderTextView() {
        placeholderTextView.text = placeholder
        placeholderTextView.font = font
        placeholderTextView.textColor = UIColor.lightGray
        placeholderTextView.frame = bounds
        placeholderTextView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        placeholderTextView.frame = bounds
    }

    @objc func textDidChange() {
        placeholderTextView.isHidden = !text.isEmpty
    }

}

其他回答

我不知道为什么人们会把这个问题复杂化....这是相当直接和简单的。下面是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];
    }`

斯威夫特3.1

这个扩展为我工作得很好:https://github.com/devxoul/UITextView-Placeholder

下面是一个代码片段:

通过pod安装:

pod 'UITextView+Placeholder', '~> 1.2'

将它导入到类中

import UITextView_Placeholder

并添加占位符属性到您已经创建的UITextView

textView.placeholder = "Put some detail"

这是…… 这里是它的外观(第三个框是一个UITextView)

我知道这是一个老问题,但想分享我认为是一个有用的方式扩展UITextView有placeholderText和placeholderColor字段。基本上你将UITextView转换为UITextField,然后设置attributedPlaceholder字段。PlaceholderText和placeholderColor是IBInspectable字段,所以它们的值可以在IB中设置,并与UITextField占位符功能完全相同。

UITextView+Extend.h

#import <UIKit/UIKit.h>

@interface UITextView (Extend)

@property (nonatomic) IBInspectable NSString *placeholderText;
@property (nonatomic) IBInspectable UIColor *placeholderColor;

@end

UITextView+Extend.m

#import "UITextView+Extend.h"
#import "objc/runtime.h"

@implementation UITextView (Extend)

- (void)setPlaceholderText:(NSString *)placeholderText
{
    objc_setAssociatedObject(self, @selector(placeholderText), placeholderText, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [self updatePlaceholderText];
}

- (NSString*)placeholderText
{
    return objc_getAssociatedObject(self, @selector(placeholderText));
}

- (void)setPlaceholderColor:(UIColor *)placeholderColor
{
    objc_setAssociatedObject(self, @selector(placeholderColor), placeholderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [self updatePlaceholderText];
}

- (UIColor*)placeholderColor
{
    return objc_getAssociatedObject(self, @selector(placeholderColor));
}

- (void)updatePlaceholderText
{
    NSString *text = self.placeholderText;
    UIColor *color = self.placeholderColor;
    if(text && color)
    {
        UITextField *textField = (UITextField*)self;
        textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:text attributes:@{NSForegroundColorAttributeName:color}];
    }
}

@end

我通过使用两个不同的文本视图来做到这一点:

一个在后台用作占位符。 一个在前台(具有透明背景),用户实际输入。

其思想是,一旦用户开始在前景视图中输入内容,后台的占位符就会消失(如果用户删除了所有内容,则会重新出现)。因此,它的行为完全类似于单行文本字段的占位符。

这是我用的代码。注意,descriptionField是用户键入的字段,descriptionPlaceholder是后台的字段。

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

迅速:

添加你的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
}

请添加委托使用扩展(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
        }
    }
}