Wie kann ich einen Platzhalter in einem UITextView
hinzufügen, ähnlich wie bei UITextField
, in Swift
?
Antworten
Zu viele Anzeigen?Wir können den Textview-Platzhalter ganz einfach implementieren, wenn wir pod IQKeyboardManagerSwift
in unserem Projekt verwenden. Sie müssen nur 4 Schritte befolgen
- Wir müssen die Klasse
IQTextView
unserer KlasseTextView
zuweisen. - Wir müssen das
IQKeyboardManagerSwift
in unserer Controller-Seite importieren - Zu guter Letzt machen Sie das Outlet des
textView
auf der Controllerseite // wenn Sie möchten :) - Geben Sie dem
textView
etwas Platzhaltertext über das Storyboard-Inspektor
Eine weitere Lösung (Swift 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)
}
}
Ergebnis
Eine einfache und schnelle Lösung, die für mich funktioniert, ist:
@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
}
}
Schnell 3.2
extension 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 = "Platzhalter"
textView.textColor = UIColor.lightGray
}
}
}
Erstens, wenn der Benutzer mit dem Bearbeiten beginnt, wird textViewDidBeginEditing aufgerufen und dann wird überprüft, ob die Farbe des Textes grau ist, was bedeutet, dass der Benutzer noch nichts geschrieben hat, dann wird der Text als Null gesetzt und die Farbe auf schwarz geändert, damit der Benutzer schreiben kann.
Wenn der Benutzer mit dem Bearbeiten fertig ist, wird textViewDidEndEditing aufgerufen und überprüft, ob der Benutzer nichts im Textfeld geschrieben hat, dann wird der Text mit der grauen Farbe und dem Text "Platzhalter" versehen.
Im Gegensatz zu praktisch jeder Antwort in diesem Beitrag hat UITextView
sehr wohl eine Platzhalter-Eigenschaft. Aus Gründen, die über mein Verständnis hinausgehen, wird sie nur in IB freigegeben, wie folgt:
Wenn Sie Storyboards verwenden und ein statischer Platzhalter ausreicht, setzen Sie die Eigenschaft einfach im Inspektor.
Sie können diese Eigenschaft auch im Code wie folgt setzen:
textView.setValue("Mein Platzhalter", forKeyPath: "placeholder")
Es ist unklar, ob dies über eine private API zugegriffen wird, da die Eigenschaft freigegeben ist.
Ich habe noch nicht versucht, mit dieser Methode einzureichen. Aber ich werde dies in Kürze tun und die Antwort entsprechend aktualisieren.
UPDATE:
Ich habe diesen Code in mehreren Versionen veröffentlicht, ohne Probleme von Apple zu haben.
UPDATE: Dies funktioniert nur in Xcode vor 11.2