UITextView
ฉันทำแอพลิเคชันที่ใช้หนึ่ง ตอนนี้ฉันต้องการให้มุมมองข้อความมีตัวยึดตำแหน่งคล้ายกับที่คุณสามารถตั้งค่าสำหรับฟิลด์ข้อความ คุณจะทำให้สำเร็จด้วยการใช้ Swift ได้อย่างไร
UITextView
ฉันทำแอพลิเคชันที่ใช้หนึ่ง ตอนนี้ฉันต้องการให้มุมมองข้อความมีตัวยึดตำแหน่งคล้ายกับที่คุณสามารถตั้งค่าสำหรับฟิลด์ข้อความ คุณจะทำให้สำเร็จด้วยการใช้ Swift ได้อย่างไร
คำตอบ:
อัปเดตสำหรับ 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)
}
}
}
yourTextField.delegate = self
การใช้งานแล้ว หากคุณไม่ทำเช่นนี้ฟังก์ชั่นtextViewDidBeginEditing
และtextViewDidEndEditing
ฟังก์ชั่นจะไม่ทำงาน
Cannot convert value of type 'NSRange' (aka '_NSRange') to expected argument type 'Range<String.Index>' (aka 'Range<String.CharacterView.Index>')
รหัสไม่ได้รวบรวมฉันกำลังมีข้อผิดพลาดเป็น
let currentText = textView.text as NSString?
NSString: เปลี่ยนสายไปlet updatedText =
let updatedText = currentText?.replacingCharacters(in: range, with: text)
สุดท้ายเปลี่ยนสายไปif updatedText.isEmpty
if (updatedText?.isEmpty)! {
นั่นควรทำเคล็ดลับ!
textView.selectedTextRange
จากภายในfunc textViewDidChangeSelection(_ textView: UITextView)
ทำให้เกิดการวนซ้ำไม่สิ้นสุด ...
ง่ายปลอดภัยและเชื่อถือได้ในการวางตำแหน่งป้ายกำกับตัวยึดเหนือมุมมองข้อความตั้งค่าแบบอักษรสีและจัดการการมองเห็นตัวยึดตำแหน่งโดยการติดตามการเปลี่ยนแปลงการนับจำนวนตัวอักษรของมุมมองข้อความ
สวิฟท์ 3:
class NotesViewController : UIViewController, UITextViewDelegate {
@IBOutlet var textView : UITextView!
var placeholderLabel : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
textView.delegate = self
placeholderLabel = UILabel()
placeholderLabel.text = "Enter some text..."
placeholderLabel.font = UIFont.italicSystemFont(ofSize: (textView.font?.pointSize)!)
placeholderLabel.sizeToFit()
textView.addSubview(placeholderLabel)
placeholderLabel.frame.origin = CGPoint(x: 5, y: (textView.font?.pointSize)! / 2)
placeholderLabel.textColor = UIColor.lightGray
placeholderLabel.isHidden = !textView.text.isEmpty
}
func textViewDidChange(_ textView: UITextView) {
placeholderLabel.isHidden = !textView.text.isEmpty
}
}
Swift 2:เหมือนกันยกเว้น: italicSystemFontOfSize(textView.font.pointSize)
,UIColor.lightGrayColor
แนะนำอย่างยิ่งให้ใช้ไลบรารีKMPlaceholderTextView ใช้งานง่ายมาก
สวิฟท์:
เพิ่มมุมมองข้อความของคุณโดยทางโปรแกรมหรือผ่านเครื่องมือสร้างส่วนต่อประสานหากสร้างล่าสุด:
@IBOutlet weak var yourTextView: UITextView!
โปรดเพิ่มผู้รับมอบสิทธิ์ (UITextViewDelegate):
class ViewController: UIViewController, UITextViewDelegate {
ในวิธี viewDidLoad ให้เพิ่มรายการต่อไปนี้:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
yourTextView.delegate = self
yourTextView.text = "Placeholder text goes right here..."
yourTextView.textColor = UIColor.lightGray
ตอนนี้ให้ฉันแนะนำส่วนมายากลเพิ่มฟังก์ชั่นนี้:
func textViewDidBeginEditing(_ textView: UITextView) {
if yourTextView.textColor == UIColor.lightGray {
yourTextView.text = ""
yourTextView.textColor = UIColor.black
}
}
โปรดทราบว่าสิ่งนี้จะทำงานเมื่อใดก็ตามที่การแก้ไขเริ่มต้นขึ้นที่นั่นเราจะตรวจสอบเงื่อนไขเพื่อบอกสถานะโดยใช้คุณสมบัติสี การตั้งค่าข้อความเป็นnil
ไม่แนะนำให้ฉัน หลังจากนั้นเราตั้งค่าสีข้อความเป็นที่ต้องการในกรณีนี้คือสีดำ
ตอนนี้เพิ่มฟังก์ชั่นนี้ด้วย:
func textViewDidEndEditing(_ textView: UITextView) {
if yourTextView.text == "" {
yourTextView.text = "Placeholder text ..."
yourTextView.textColor = UIColor.lightGray
}
}
ให้ฉันยืนยันอย่าเปรียบเทียบกับnil
ฉันได้ลองแล้วและมันจะไม่ทำงาน textViewDidBeginEditing
จากนั้นเราจะตั้งค่ากลับไปที่รูปแบบตัวยึดและตั้งค่ากลับสีเพื่อสียึดเพราะมันเป็นเงื่อนไขในการตรวจสอบใน
ใช้ส่วนขยายนี้เป็นวิธีที่ดีที่สุดในการกำหนดตัวยึดตำแหน่งใน UITextView แต่ให้แน่ใจว่าคุณแนบผู้รับมอบสิทธิ์เข้ากับ TextView คุณสามารถตั้งค่าให้เจ้าของสถานที่เป็นดังนี้: -
yourTextView.placeholder = "Placeholder"
extension UITextView :UITextViewDelegate
{
/// Resize the placeholder when the UITextView bounds change
override open var bounds: CGRect {
didSet {
self.resizePlaceholder()
}
}
/// The UITextView placeholder text
public var placeholder: String? {
get {
var placeholderText: String?
if let placeholderLabel = self.viewWithTag(100) as? UILabel {
placeholderText = placeholderLabel.text
}
return placeholderText
}
set {
if let placeholderLabel = self.viewWithTag(100) as! UILabel? {
placeholderLabel.text = newValue
placeholderLabel.sizeToFit()
} else {
self.addPlaceholder(newValue!)
}
}
}
/// When the UITextView did change, show or hide the label based on if the UITextView is empty or not
///
/// - Parameter textView: The UITextView that got updated
public func textViewDidChange(_ textView: UITextView) {
if let placeholderLabel = self.viewWithTag(100) as? UILabel {
placeholderLabel.isHidden = self.text.characters.count > 0
}
}
/// Resize the placeholder UILabel to make sure it's in the same position as the UITextView text
private func resizePlaceholder() {
if let placeholderLabel = self.viewWithTag(100) as! UILabel? {
let labelX = self.textContainer.lineFragmentPadding
let labelY = self.textContainerInset.top - 2
let labelWidth = self.frame.width - (labelX * 2)
let labelHeight = placeholderLabel.frame.height
placeholderLabel.frame = CGRect(x: labelX, y: labelY, width: labelWidth, height: labelHeight)
}
}
/// Adds a placeholder UILabel to this UITextView
private func addPlaceholder(_ placeholderText: String) {
let placeholderLabel = UILabel()
placeholderLabel.text = placeholderText
placeholderLabel.sizeToFit()
placeholderLabel.font = self.font
placeholderLabel.textColor = UIColor.lightGray
placeholderLabel.tag = 100
placeholderLabel.isHidden = self.text.characters.count > 0
self.addSubview(placeholderLabel)
self.resizePlaceholder()
self.delegate = self
}
}
NSTextStorageDelegate
ฉันกำลังประหลาดใจที่ไม่มีใครกล่าวถึง UITextViewDelegate
วิธีการของจะถูกเรียกใช้โดยการโต้ตอบของผู้ใช้เท่านั้น เช่นเมื่อคุณตั้งค่ามุมมองข้อความtext
คุณสมบัติโปรแกรมคุณจะต้องตั้งค่าการแสดงผลของตัวยึดตำแหน่งด้วยตนเองเนื่องจากวิธีการมอบหมายจะไม่ถูกเรียก
แต่ด้วยNSTextStorageDelegate
's textStorage(_:didProcessEditing:range:changeInLength:)
วิธีการที่คุณจะได้รับแจ้งการเปลี่ยนแปลงข้อความใด ๆ แม้ว่าจะมีการทำโปรแกรม เพียงกำหนดแบบนี้:
textView.textStorage.delegate = self
(ในUITextView
คุณสมบัติของตัวแทนนี้เป็นnil
ค่าเริ่มต้นดังนั้นจึงไม่มีผลกระทบต่อการทำงานเริ่มต้น)
รวมเข้ากับUILabel
เทคนิคที่แสดงให้เห็นถึง @clearlight หนึ่งสามารถห่อการดำเนินงานทั้งหมดUITextView
ของplaceholder
เป็นส่วนขยาย
extension UITextView {
private class PlaceholderLabel: UILabel { }
private var placeholderLabel: PlaceholderLabel {
if let label = subviews.compactMap( { $0 as? PlaceholderLabel }).first {
return label
} else {
let label = PlaceholderLabel(frame: .zero)
label.font = font
addSubview(label)
return label
}
}
@IBInspectable
var placeholder: String {
get {
return subviews.compactMap( { $0 as? PlaceholderLabel }).first?.text ?? ""
}
set {
let placeholderLabel = self.placeholderLabel
placeholderLabel.text = newValue
placeholderLabel.numberOfLines = 0
let width = frame.width - textContainer.lineFragmentPadding * 2
let size = placeholderLabel.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude))
placeholderLabel.frame.size.height = size.height
placeholderLabel.frame.size.width = width
placeholderLabel.frame.origin = CGPoint(x: textContainer.lineFragmentPadding, y: textContainerInset.top)
textStorage.delegate = self
}
}
}
extension UITextView: NSTextStorageDelegate {
public func textStorage(_ textStorage: NSTextStorage, didProcessEditing editedMask: NSTextStorageEditActions, range editedRange: NSRange, changeInLength delta: Int) {
if editedMask.contains(.editedCharacters) {
placeholderLabel.isHidden = !text.isEmpty
}
}
}
โปรดทราบว่าการใช้งานของเอกชน (ซ้อน) PlaceholderLabel
ระดับที่เรียกว่า ไม่มีการนำมาใช้เลย แต่ให้วิธีการระบุป้ายกำกับตำแหน่งซึ่งเป็น 'swifty' มากกว่าการใช้tag
คุณสมบัติ
ด้วยวิธีการนี้คุณยังคงสามารถมอบหมายผู้รับมอบสิทธิ์UITextView
ให้กับบุคคลอื่นได้
คุณไม่จำเป็นต้องเปลี่ยนคลาสของมุมมองข้อความด้วยซ้ำ เพียงเพิ่มส่วนขยายแล้วคุณจะสามารถกำหนดสตริงตัวยึดให้กับทุกคนUITextView
ในโครงการของคุณแม้ในตัวสร้างส่วนต่อประสาน
ผมออกจากการดำเนินงานของที่placeholderColor
คุณสมบัติสำหรับเหตุผลที่ชัดเจน placeholder
แต่ก็สามารถนำมาใช้สำหรับบรรทัดที่มากขึ้นเพียงไม่กี่กับตัวแปรคำนวณคล้ายกับ
textView.textStorage.delegate = self
ในมุมมองของตัวควบคุมจะต้องมีเราไปผูกที่ View-Controller NSTextStorageDelegate
กับ มันต้องการจริงๆเหรอ?
NSTextStorageDelegate
ไม่ใช่ตัวควบคุมมุมมอง
ฉันทำสิ่งนี้โดยใช้มุมมองข้อความที่แตกต่างกันสองแบบ:
แนวคิดคือเมื่อผู้ใช้เริ่มพิมพ์สิ่งต่าง ๆ ในมุมมองเบื้องหน้าตัวยึดตำแหน่งในพื้นหลังจะหายไป (และปรากฏขึ้นอีกครั้งหากผู้ใช้ลบทุกอย่าง) ดังนั้นจึงมีลักษณะเหมือนตัวยึดตำแหน่งสำหรับฟิลด์ข้อความบรรทัดเดียว
นี่คือรหัสที่ฉันใช้ โปรดทราบว่า descriptionField เป็นฟิลด์ที่ผู้ใช้พิมพ์และ descriptionPlaceholder เป็นฟิลด์ที่อยู่ในพื้นหลัง
func textViewDidChange(descriptionField: UITextView) {
if descriptionField.text.isEmpty == false {
descriptionPlaceholder.text = ""
} else {
descriptionPlaceholder.text = descriptionPlaceholderText
}
}
จากคำแนะนำที่ดีที่นี่แล้วฉันสามารถรวบรวม subclass ที่เข้ากันได้กับ Interface-Builder ของเบาซึ่งต่อไปนี้UITextView
:
UITextField
รวมถึงข้อความตัวยึดกำหนดสไตล์เช่นเดียวกับที่ของtext
คุณสมบัติของฟิลด์คำแนะนำในการปรับปรุงใด ๆ ยินดีต้อนรับโดยเฉพาะอย่างยิ่งหากมีวิธีใดที่จะดึงสีตัวยึดตำแหน่งของ iOS โดยใช้โปรแกรมแทนที่จะเขียนโค้ดแบบยาก
Sw5 v5:
import UIKit
@IBDesignable class TextViewWithPlaceholder: UITextView {
override var text: String! { // Ensures that the placeholder text is never returned as the field's text
get {
if showingPlaceholder {
return "" // When showing the placeholder, there's no real text to return
} else { return super.text }
}
set { super.text = newValue }
}
@IBInspectable var placeholderText: String = ""
@IBInspectable var placeholderTextColor: UIColor = UIColor(red: 0.78, green: 0.78, blue: 0.80, alpha: 1.0) // Standard iOS placeholder color (#C7C7CD). See /programming/31057746/whats-the-default-color-for-placeholder-text-in-uitextfield
private var showingPlaceholder: Bool = true // Keeps track of whether the field is currently showing a placeholder
override func didMoveToWindow() {
super.didMoveToWindow()
if text.isEmpty {
showPlaceholderText() // Load up the placeholder text when first appearing, but not if coming back to a view where text was already entered
}
}
override func becomeFirstResponder() -> Bool {
// If the current text is the placeholder, remove it
if showingPlaceholder {
text = nil
textColor = nil // Put the text back to the default, unmodified color
showingPlaceholder = false
}
return super.becomeFirstResponder()
}
override func resignFirstResponder() -> Bool {
// If there's no text, put the placeholder back
if text.isEmpty {
showPlaceholderText()
}
return super.resignFirstResponder()
}
private func showPlaceholderText() {
showingPlaceholder = true
textColor = placeholderTextColor
text = placeholderText
}
}
ค่า SET ในมุมมองโหลด
txtVw!.autocorrectionType = UITextAutocorrectionType.No
txtVw!.text = "Write your Placeholder"
txtVw!.textColor = UIColor.lightGrayColor()
func textViewDidBeginEditing(textView: UITextView) {
if (txtVw?.text == "Write your Placeholder")
{
txtVw!.text = nil
txtVw!.textColor = UIColor.blackColor()
}
}
func textViewDidEndEditing(textView: UITextView) {
if txtVw!.text.isEmpty
{
txtVw!.text = "Write your Placeholder"
txtVw!.textColor = UIColor.lightGrayColor()
}
textView.resignFirstResponder()
}
ผมพยายามที่จะทำให้สะดวกรหัสจากClearlight 's คำตอบ
extension UITextView{
func setPlaceholder() {
let placeholderLabel = UILabel()
placeholderLabel.text = "Enter some text..."
placeholderLabel.font = UIFont.italicSystemFont(ofSize: (self.font?.pointSize)!)
placeholderLabel.sizeToFit()
placeholderLabel.tag = 222
placeholderLabel.frame.origin = CGPoint(x: 5, y: (self.font?.pointSize)! / 2)
placeholderLabel.textColor = UIColor.lightGray
placeholderLabel.isHidden = !self.text.isEmpty
self.addSubview(placeholderLabel)
}
func checkPlaceholder() {
let placeholderLabel = self.viewWithTag(222) as! UILabel
placeholderLabel.isHidden = !self.text.isEmpty
}
}
การใช้
override func viewDidLoad() {
textView.delegate = self
textView.setPlaceholder()
}
func textViewDidChange(_ textView: UITextView) {
textView.checkPlaceholder()
}
ทางออกหนึ่งเพิ่มเติม (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)
}
}
ผลลัพธ์
ทางออกที่ง่ายและรวดเร็วที่เหมาะกับฉันคือ:
@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
}
}
นี่คือสิ่งที่ฉันใช้สำหรับงานนี้เสร็จแล้ว
@IBDesignable class UIPlaceholderTextView: UITextView {
var placeholderLabel: UILabel?
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
sharedInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
sharedInit()
}
override func prepareForInterfaceBuilder() {
sharedInit()
}
func sharedInit() {
refreshPlaceholder()
NotificationCenter.default.addObserver(self, selector: #selector(textChanged), name: UITextView.textDidChangeNotification, object: nil)
}
@IBInspectable var placeholder: String? {
didSet {
refreshPlaceholder()
}
}
@IBInspectable var placeholderColor: UIColor? = .darkGray {
didSet {
refreshPlaceholder()
}
}
@IBInspectable var placeholderFontSize: CGFloat = 14 {
didSet {
refreshPlaceholder()
}
}
func refreshPlaceholder() {
if placeholderLabel == nil {
placeholderLabel = UILabel()
let contentView = self.subviews.first ?? self
contentView.addSubview(placeholderLabel!)
placeholderLabel?.translatesAutoresizingMaskIntoConstraints = false
placeholderLabel?.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: textContainerInset.left + 4).isActive = true
placeholderLabel?.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: textContainerInset.right + 4).isActive = true
placeholderLabel?.topAnchor.constraint(equalTo: contentView.topAnchor, constant: textContainerInset.top).isActive = true
placeholderLabel?.bottomAnchor.constraint(lessThanOrEqualTo: contentView.bottomAnchor, constant: textContainerInset.bottom)
}
placeholderLabel?.text = placeholder
placeholderLabel?.textColor = placeholderColor
placeholderLabel?.font = UIFont.systemFont(ofSize: placeholderFontSize)
}
@objc func textChanged() {
if self.placeholder?.isEmpty ?? true {
return
}
UIView.animate(withDuration: 0.25) {
if self.text.isEmpty {
self.placeholderLabel?.alpha = 1.0
} else {
self.placeholderLabel?.alpha = 0.0
}
}
}
override var text: String! {
didSet {
textChanged()
}
}
}
ฉันรู้ว่ามีหลายวิธีที่คล้ายกันนี้ แต่ประโยชน์จากวิธีนี้คือ:
รวดเร็ว 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 = "Placeholder"
textView.textColor = UIColor.lightGray
}
}
}
ก่อนอื่นเมื่อผู้ใช้เริ่มแก้ไขการโทร textViewDidBeginEditing แล้วตรวจสอบว่าสีของข้อความเทาหมายความว่าผู้ใช้ไม่ได้เขียนอะไรเลยจากนั้นตั้งค่าเป็น textview ไม่มีและเปลี่ยนสีเป็นสีดำสำหรับการส่งข้อความของผู้ใช้
เมื่อผู้ใช้ปลายทางแก้ไข textViewDidEndEditing คือการโทรและตรวจสอบว่าผู้ใช้ไม่ได้เขียนอะไรใน textview แล้วชุดข้อความเป็นสีเทาพร้อมข้อความ "PlaceHolder"
นี่คือวิธีของฉันในการแก้ปัญหานี้ ( Swift 4 ):
แนวคิดนี้คือการทำให้โซลูชันที่เป็นไปได้ง่ายที่สุดซึ่งอนุญาตให้ใช้ตัวยึดสีต่าง ๆ ปรับขนาดตามขนาดตัวยึดจะไม่เขียนทับdelegate
ขณะที่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) }
}
ฉันไม่รู้ว่าทำไมผู้คนถึงสับสนปัญหานี้มาก ... มันค่อนข้างตรงไปตรงมาและเรียบง่าย นี่คือ subclass ของ 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];
}`
นี่คือโซลูชันของฉันที่พร้อมใช้งานหากคุณกำลังทำงานกับหลายมุมมองข้อความ
func textViewShouldBeginEditing(textView: UITextView) -> Bool {
// Set cursor to the beginning if placeholder is set
if textView.textColor == UIColor.lightGrayColor() {
textView.selectedTextRange = textView.textRangeFromPosition(textView.beginningOfDocument, toPosition: textView.beginningOfDocument)
}
return true
}
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
// Remove placeholder
if textView.textColor == UIColor.lightGrayColor() && text.characters.count > 0 {
textView.text = ""
textView.textColor = UIColor.blackColor()
}
if text == "\n" {
textView.resignFirstResponder()
return false
}
return true
}
func textViewDidChange(textView: UITextView) {
// Set placeholder if text is empty
if textView.text.isEmpty {
textView.text = NSLocalizedString("Hint", comment: "hint")
textView.textColor = UIColor.lightGrayColor()
textView.selectedTextRange = textView.textRangeFromPosition(textView.beginningOfDocument, toPosition: textView.beginningOfDocument)
}
}
func textViewDidChangeSelection(textView: UITextView) {
// Set cursor to the beginning if placeholder is set
let firstPosition = textView.textRangeFromPosition(textView.beginningOfDocument, toPosition: textView.beginningOfDocument)
// Do not change position recursively
if textView.textColor == UIColor.lightGrayColor() && textView.selectedTextRange != firstPosition {
textView.selectedTextRange = firstPosition
}
}
สวิฟท์ 3.1
ส่วนขยายนี้ทำงานได้ดีสำหรับฉัน: https://github.com/devxoul/UITextView-Placeholder
นี่คือข้อมูลโค้ด:
ติดตั้งผ่านฝัก:
pod 'UITextView+Placeholder', '~> 1.2'
นำเข้าสู่ชั้นเรียนของคุณ
import UITextView_Placeholder
และเพิ่มplaceholder
คุณสมบัติให้กับคุณที่สร้างไว้แล้วUITextView
textView.placeholder = "Put some detail"
ตรงกันข้ามกับทุกคำตอบในโพสต์UITextView
นี้มีคุณสมบัติตัวยึดตำแหน่ง ด้วยเหตุผลที่เกินความเข้าใจของฉันมันถูกเปิดเผยใน IB เท่านั้นเช่น:
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="placeholder" value="My Placeholder"/>
</userDefinedRuntimeAttributes>
ดังนั้นหากคุณใช้สตอรีบอร์ดและตัวยึดแบบคงที่จะพอเพียงให้ตั้งค่าคุณสมบัติของผู้ตรวจสอบ
คุณยังสามารถตั้งค่าคุณสมบัตินี้ในรหัสเช่นนี้:
textView.setValue("My Placeholder", forKeyPath: "placeholder")
มีเมฆของมันเป็นสภาพอากาศนี้จะเข้าถึงได้ผ่านทาง API ส่วนตัวเป็นทรัพย์สินที่มีการสัมผัส
ฉันไม่ได้ลองส่งด้วยวิธีนี้ แต่ฉันจะส่งแบบนี้ในไม่ช้าและจะอัปเดตคำตอบตามนี้
UPDATE:
ฉันส่งรหัสนี้ในหลาย ๆ รุ่นโดยไม่มีปัญหาจาก Apple
UPDATE: สิ่งนี้จะทำงานใน Xcode ก่อน 11.2 เท่านั้น
UITextField
ไม่UITextView
โปรดอ่านคำถาม / คำตอบอย่างระมัดระวัง
ไม่มีคุณสมบัติดังกล่าวใน ios เพื่อเพิ่มตัวยึดตำแหน่งใน TextView โดยตรงคุณสามารถเพิ่มป้ายกำกับและแสดง / ซ่อนในการเปลี่ยนแปลงของ textView SWIFT 2.0 และตรวจสอบให้แน่ใจว่าได้ใช้ textviewdelegate
func textViewDidChange(TextView: UITextView)
{
if txtShortDescription.text == ""
{
self.lblShortDescription.hidden = false
}
else
{
self.lblShortDescription.hidden = true
}
}
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()
}
}
ฉันชอบโซลูชันของ @ nerdist จากนั้นฉันสร้างส่วนขยายไปที่UITextView
:
import Foundation
import UIKit
extension UITextView
{
private func add(_ placeholder: UILabel) {
for view in self.subviews {
if let lbl = view as? UILabel {
if lbl.text == placeholder.text {
lbl.removeFromSuperview()
}
}
}
self.addSubview(placeholder)
}
func addPlaceholder(_ placeholder: UILabel?) {
if let ph = placeholder {
ph.numberOfLines = 0 // support for multiple lines
ph.font = UIFont.italicSystemFont(ofSize: (self.font?.pointSize)!)
ph.sizeToFit()
self.add(ph)
ph.frame.origin = CGPoint(x: 5, y: (self.font?.pointSize)! / 2)
ph.textColor = UIColor(white: 0, alpha: 0.3)
updateVisibility(ph)
}
}
func updateVisibility(_ placeHolder: UILabel?) {
if let ph = placeHolder {
ph.isHidden = !self.text.isEmpty
}
}
}
ตัวอย่างเช่นในคลาส ViewController นี่คือวิธีที่ฉันใช้
class MyViewController: UIViewController, UITextViewDelegate {
private var notePlaceholder: UILabel!
@IBOutlet weak var txtNote: UITextView!
...
// UIViewController
override func viewDidLoad() {
notePlaceholder = UILabel()
notePlaceholder.text = "title\nsubtitle\nmore..."
txtNote.addPlaceholder(notePlaceholder)
...
}
// UITextViewDelegate
func textViewDidChange(_ textView: UITextView) {
txtNote.updateVisbility(notePlaceholder)
...
}
ตัวยึดตำแหน่งบน UITextview!
อัปเดต :
ในกรณีที่คุณเปลี่ยนข้อความของ textview ในรหัสอย่าลืมเรียกวิธี updateVisibitly เพื่อซ่อนตัวยึด:
txtNote.text = "something in code"
txtNote.updateVisibility(self.notePlaceholder) // hide placeholder if text is not empty.
เพื่อป้องกันไม่ให้ตัวยึดที่เพิ่มเข้ามามากกว่าหนึ่งครั้งส่วนตัวฟังก์ชั่นจะถูกเพิ่มในadd()
extension
ใน 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)
}
}
ฉันเขียนชั้นเรียนอย่างรวดเร็ว คุณต้องนำเข้าคลาสนี้ทุกครั้งที่ต้องการ
ฉันไม่สามารถเพิ่มความคิดเห็นได้เนื่องจากชื่อเสียง เพิ่มความต้องการผู้รับมอบสิทธิ์อีกหนึ่งคำตอบใน @clearlight
func textViewDidBeginEditing(_ textView: UITextView) {
cell.placeholderLabel.isHidden = !textView.text.isEmpty
}
คือความต้องการ
เพราะtextViewDidChange
ไม่ได้ถูกเรียกครั้งแรก
ไม่มีตัวยึดตำแหน่งใด ๆ สำหรับ textview คุณต้องใส่ป้ายกำกับข้างต้นเมื่อผู้ใช้ป้อนใน textview แล้วซ่อนมันหรือตั้งค่าตามค่าเริ่มต้นเมื่อผู้ใช้ป้อนลบค่าทั้งหมด
func setPlaceholder(){
var placeholderLabel = UILabel()
placeholderLabel.text = "Describe your need..."
placeholderLabel.font = UIFont.init(name: "Lato-Regular", size: 15.0) ?? UIFont.boldSystemFont(ofSize: 14.0)
placeholderLabel.sizeToFit()
descriptionTextView.addSubview(placeholderLabel)
placeholderLabel.frame.origin = CGPoint(x: 5, y: (descriptionTextView.font?.pointSize)! / 2)
placeholderLabel.textColor = UIColor.lightGray
placeholderLabel.isHidden = !descriptionTextView.text.isEmpty
}
//Delegate Method.
func textViewDidChange(_ textView: UITextView) {
placeholderLabel.isHidden = !textView.text.isEmpty
}
ฉันต้องส่งคิวเพื่อให้ข้อความตัวยึดของฉันปรากฏขึ้นอีกครั้งเมื่อการแก้ไขเสร็จสิ้น
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.text == "Description" {
textView.text = nil
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text.isEmpty {
DispatchQueue.main.async {
textView.text = "Description"
}
}
}
สวิฟท์:
เพิ่มของคุณ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
}
โปรดเพิ่มDelegate
ส่วนขยายการใช้ (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
}
}
}
วิธีการแก้ปัญหาของเราหลีกเลี่ยงการล้อเล่นกับUITextView
text
และtextColor
คุณสมบัติซึ่งมีประโยชน์หากคุณยังคงรักษาตัวนับ
มันง่าย:
1) การสร้างหุ่นในสตอรี่บอร์ดที่มีคุณสมบัติเช่นเดียวกับต้นแบบUITextView
UITextView
กำหนดข้อความตัวยึดให้กับข้อความจำลอง
2) จัดตำแหน่งขอบด้านบนซ้ายและขวาของทั้งสอง UITextViews.
3) วางหุ่นที่อยู่ด้านหลังต้นแบบ
4) แทนที่textViewDidChange(textView:)
ฟังก์ชั่นการมอบหมายของต้นแบบและแสดงดัมมี่ถ้าต้นแบบมีอักขระ 0 ตัว มิฉะนั้นแสดงหลัก
สิ่งนี้ถือว่าทั้งสองUITextViews
มีพื้นหลังโปร่งใส หากไม่มีให้วางจำลองไว้ด้านบนเมื่อมี 0 ตัวอักษรและกดด้านล่างเมื่อมี> 0 ตัวอักษร UITextView
นอกจากนี้คุณยังจะมีการตอบสนองต่อการแลกเปลี่ยนเพื่อให้แน่ใจว่าเคอร์เซอร์ที่เหมาะสมต่อไป
Swift 4, 4.2 และ 5
[![@IBOutlet var detailTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
detailTextView.delegate = self
}
extension ContactUsViewController : UITextViewDelegate {
public func textViewDidBeginEditing(_ textView: UITextView) {
if textView.text == "Write your message here..." {
detailTextView.text = ""
detailTextView.textColor = UIColor.init(red: 0/255, green: 0/255, blue: 0/255, alpha: 0.86)
}
textView.becomeFirstResponder()
}
public func textViewDidEndEditing(_ textView: UITextView) {
if textView.text == "" {
detailTextView.text = "Write your message here..."
detailTextView.textColor = UIColor.init(red: 0/255, green: 0/255, blue: 0/255, alpha: 0.30)
}
textView.resignFirstResponder()
}
[![}][1]][1]