如何在UITextView中添加占位符,类似于你可以为UITextField设置的占位符,在Swift中?
当前回答
我们的解决方案避免了与UITextView文本和textColor属性的混淆,如果您要维护字符计数器,这是非常方便的。
很简单:
1)在Storyboard中创建一个与主UITextView属性相同的虚拟UITextView。将占位符文本分配给虚拟文本。
2)对齐两个uitextview的上、左、右边缘。
3)把假人放在主人的后面。
4)重写master的textViewDidChange(textView:)委托函数,如果master有0个字符,则显示dummy。否则,显示master。
这假设两个uitextview的背景都是透明的。如果没有,当有0个字符时,将假人放在上面,当有>个0个字符时,将它推到下面。您还必须交换响应器,以确保光标跟随正确的UITextView。
其他回答
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
}
}
然后,当用户完成编辑文本视图并将其作为第一响应器时,如果文本视图为空,则通过重新添加占位符文本并将其颜色设置为浅灰色来重置其占位符。
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text.isEmpty {
textView.text = "Placeholder"
textView.textColor = UIColor.lightGray
}
}
解决方案#2 -如果你想要占位符显示文本视图是空的,即使文本视图被选中:
首先在viewDidLoad中设置占位符:
textView.text = "Placeholder"
textView.textColor = UIColor.lightGray
textView.becomeFirstResponder()
textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
(注意:由于OP希望在视图加载时立即选择文本视图,所以我将文本视图选择合并到上面的代码中。如果这不是你想要的行为,你不希望在视图加载时选择文本视图,从上面的代码块中删除最后两行。)
然后使用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
}
也实现textViewDidChangeSelection,以防止用户改变光标的位置,而占位符是可见的。(注意: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)
}
}
}
协议版本的clearlight的答案上面,因为协议是伟大的。随便放哪都行。扣篮!
extension UITextViewPlaceholder where Self: UIViewController {
// Use this in ViewController's ViewDidLoad method.
func addPlaceholder(text: String, toTextView: UITextView, font: UIFont? = nil) {
placeholderLabel = UILabel()
placeholderLabel.text = text
placeholderLabel.font = font ?? UIFont.italicSystemFont(ofSize: (toTextView.font?.pointSize)!)
placeholderLabel.sizeToFit()
toTextView.addSubview(placeholderLabel)
placeholderLabel.frame.origin = CGPoint(x: 5, y: (toTextView.font?.pointSize)! / 2)
placeholderLabel.textColor = UIColor.lightGray
placeholderLabel.isHidden = !toTextView.text.isEmpty
}
// Use this function in the ViewController's textViewDidChange delegate method.
func textViewWithPlaceholderDidChange(_ textView: UITextView) {
placeholderLabel.isHidden = !textView.text.isEmpty
}
}
对我来说,一个简单而快速的解决方法是:
@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
}
}
迅速:
添加你的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
}
}
}
以下是我解决这个问题的方法(Swift 4):
这个想法是做出最简单的解决方案,允许使用不同颜色的占位符,调整占位符大小,不会覆盖委托,同时保持所有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) }
}
推荐文章
- 我如何在我的iOS应用程序中每n分钟得到一个后台位置更新?
- 如何使用iOS创建GUID/UUID
- 禁用所呈现视图控制器的交互式撤销
- 在Swift中转换字符串为日期
- 点击按钮时如何打开手机设置?
- 如何使用UIVisualEffectView来模糊图像?
- 如何修复UITableView分隔符在iOS 7?
- 故事板中的自定义单元格行高设置没有响应
- 在Swift中使用自定义消息抛出错误/异常的最简单方法?
- 编译器错误:带有Objective-C选择器的方法与前面带有相同Objective-C选择器的声明冲突
- 如何在Swift中获得唯一的设备ID ?
- 如何在Swift中获得枚举值的名称?
- 复制文本到剪贴板与iOS
- 在Swift中根据字符串计算UILabel的大小
- 如何调用手势点击在UIView编程在迅速