Swift에서 UITextView에 자리 표시자 텍스트를 추가하시겠습니까?
holder이 in in에 홀더를 해야 하나요?UITextView
하면 '아예'로할 수 것과 UITextField
、 。Swift
Swift 4용으로 업데이트됨
UITextView
에 플레이스홀더 속성을 및 해야 합니다.UITextViewDelegate
아래의 # #중 하나를 것을 합니다.원하는 동작에 따라 아래 솔루션 #1 또는 #2 중 하나를 사용할 것을 권장합니다.
「: 」를 합니다.UITextViewDelegate
하여 "Setting"을 설정합니다.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에서는 텍스트 뷰가 로드되는 즉시 텍스트 뷰가 선택되도록 하고 싶었기 때문에 위의 코드에 텍스트 뷰 선택을 포함시켰습니다.이 동작이 바람직하지 않고 뷰 로드 시 텍스트뷰를 선택하지 않을 경우 위의 코드 청크에서 마지막 두 줄을 삭제하십시오.)
런음음 the 를 활용해주세요.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
홀더가되어 있는 하지 않도록 주의: "CHANGE" (CHANGE: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)
}
}
}
부동 자리 표시자
텍스트 뷰의 문자 수에 대한 변경을 추적하여 텍스트 뷰 위에 자리 표시자 레이블을 배치하고 글꼴, 색상을 설정하고 자리 표시자 가시성을 관리하는 것은 간단하고 안전하며 신뢰할 수 있습니다.
업데이트: 23년 2월 10일 @RakshithaMurangaRodrigo에 의한 제안 통합 코멘트
Swift 5:
class NotesViewController : UIViewController {
@IBOutlet var textView : UITextView!
var placeholderLabel : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
textView.delegate = self
placeholderLabel = UILabel()
placeholderLabel.text = "Enter some text..."
placeholderLabel.font = .italicSystemFont(ofSize: (textView.font?.pointSize)!)
placeholderLabel.sizeToFit()
textView.addSubview(placeholderLabel)
placeholderLabel.frame.origin = CGPoint(x: 5, y: (textView.font?.pointSize)! / 2)
placeholderLabel.textColor = .tertiaryLabel
placeholderLabel.isHidden = !textView.text.isEmpty
}
}
extension NotesViewController : UITextViewDelegate {
func textViewDidChange(_ textView: UITextView) {
placeholderLabel?.isHidden = !textView.text.isEmpty
}
func textViewDidEndEditing(_ textView: UITextView) {
placeholderLabel?.isHidden = !textView.text.isEmpty
}
func textViewDidBeginEditing(_ textView: UITextView) {
placeholderLabel?.isHidden = true
}
}
신속:
텍스트 뷰를 프로그래밍 방식으로 추가하거나 Interface Builder를 통해 추가합니다(마지막인 경우).
@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
}
}
말씀드리지만, 가가 to to to to to to to to to to to to to와 .nil
저는 이미 그것을 시도했지만, 그것은 효과가 없습니다. 값을 스타일로 다시 합니다. 왜냐하면 이 조건이기 때문입니다.이것은 체크인 조건이기 때문입니다.textViewDidBeginEditing
.
도 언급하지 .NSTextStorageDelegate
UITextViewDelegate
텍스트뷰 설정 등text
대리 메서드는 호출되지 않으므로 사용자가 직접 자리 표시자의 가시성을 설정해야 합니다.
,에서는NSTextStorageDelegate
의 »textStorage(_:didProcessEditing:range:changeInLength:)
어떠한 됩니다.뭇매를 맞다
textView.textStorage.delegate = self
(인)UITextView
이 위임 속성은 다음과 같습니다.nil
디폴트 동작에는 영향을 주지 않습니다.)
을 것 combine combine combine combine combine combine combine combine combine combine combine combine combine.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
}
}
}
private( 완료)라고 하는 프라이빗에 주의해 .PlaceholderLabel
홀더 라벨을 할 수 있는 홀더 라벨은 플레이스 홀더 라벨을 사용하는 이 있습니다이것은, FD를 사용하는 것보다 훨씬 「신속한」 것입니다.tag
★★★★★★★★★★★★★★★★★★.
을 사용해도 할 수 .UITextView
다른 사람에게요
텍스트 보기의 클래스를 변경할 필요도 없습니다.을 모든 플레이스 홀더에 할 수 .UITextView
인터페이스 빌더
의 실장은 생략했습니다.placeholderColor
할 수 , 이 은 "Calculated "와 하여 몇 만 더 할 수 .placeholder
.
중 몇으로 다음과 인터페이스 빌더 할 수 .UITextView
명령어 우이 , ,:
- 가능한 텍스트가 포함되어 있습니다.이 「 」의 .
UITextField
. - 추가 서브뷰나 제약이 필요 없습니다.
- View Controller의 위임이나 기타 동작이 필요하지 않습니다.
- 알림이 필요 없습니다.
- 를 보고 합니다.
text
★★★★★★★★★★★★★★★★★★.
특히 iOS의 플레이스 홀더 색상을 하드 코딩하지 않고 프로그램적으로 끌어낼 수 있는 방법이 있다면 어떤 개선 제안도 환영입니다.
Swift 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 https://stackoverflow.com/questions/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
}
}
두 가지 다른 텍스트 보기를 사용하여 이 작업을 수행했습니다.
- 자리 표시자로 사용되는 배경의 하나.
- 사용자가 실제로 입력하는 포그라운드(투명 배경)의 하나.
사용자가 전경 뷰에 내용을 입력하기 시작하면 배경의 자리 표시자가 사라집니다(사용자가 모든 내용을 삭제하면 다시 나타납니다).따라서 단일 줄 텍스트 필드의 자리 표시자와 동일하게 작동합니다.
여기 제가 사용한 코드가 있습니다.descriptionField는 사용자가 입력하는 필드이고 descriptionPlaceholder는 백그라운드에서 입력하는 필드입니다.
func textViewDidChange(descriptionField: UITextView) {
if descriptionField.text.isEmpty == false {
descriptionPlaceholder.text = ""
} else {
descriptionPlaceholder.text = descriptionPlaceholderText
}
}
나는 클리어라이트의 대답으로 코드를 편리하게 하려고 노력했다.
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()
}
이게 내가 이 일을 완수하기 위해 사용하는 것이다.
@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).isActive = true
}
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()
}
}
}
이와 유사한 접근법이 몇 가지 있다는 것을 알지만, 이 접근법의 이점은 다음과 같습니다.
- IB에서 자리 표시자 텍스트, 글꼴 크기 및 색상을 설정합니다.
- IB에서 "Scroll View에 스크롤 가능한 콘텐츠가 모호합니다"라는 경고가 더 이상 표시되지 않습니다.
- 자리 표시자 표시/숨김에 애니메이션을 추가합니다.
신속:
를를 add add add add add 를 추가하다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
}
}
}
뷰 로드에서의 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()
}
또 하나의 솔루션 (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)
}
}
결과
는 pod pod를 할 수 .IQKeyboardManagerSwift
.
- .
IQTextView
TextView
를 누릅니다 - .
IQKeyboardManagerSwift
- 으로 꼭 한 콘센트를 .
textView
[/ // 를 - 주다
textView
일부 검사
다음과 같은 간단한 솔루션을 이용할 수 있습니다.
@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
}
}
스위프트 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
}
}
}
처음에 사용자가 textViewDidBeginiting 호출을 편집하고 text 회색의 색상이 사용자가 아무것도 쓰지 않았음을 의미하는지 확인한 후 textview nero로 설정하고 사용자가 문자를 보낼 때 색상을 검은색으로 변경합니다.
사용자가 textViewDidEndedEditing을 호출하여 textview에 아무것도 쓰지 않았는지 확인한 후 "PlaceHolder" 텍스트와 함께 회색으로 설정됩니다.
이 문제를 해결하는 방법(Swift 4):
를 사용할 수 있고, 홀더 크기에 를 조정할 수 , holders size size른 aa a a a a a a a a a a, the the a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a를 덮어쓰지 않는 가장 간단한 솔루션을 만드는 것이 였습니다.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) }
}
신속한 회답
여기 자리 표시자를 애니메이션으로 만드는 커스텀 클래스가 있습니다.
class CustomTextView: UITextView {
// MARK: - public
public var placeHolderText: String? = "Enter Reason.."
public lazy var placeHolderLabel: UILabel! = {
let placeHolderLabel = UILabel(frame: .zero)
placeHolderLabel.numberOfLines = 0
placeHolderLabel.backgroundColor = .clear
placeHolderLabel.alpha = 0.5
return placeHolderLabel
}()
// MARK: - Init
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
enableNotifications()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
enableNotifications()
}
func setup() {
placeHolderLabel.frame = CGRect(x: 8, y: 8, width: self.bounds.size.width - 16, height: 15)
placeHolderLabel.sizeToFit()
}
// MARK: - Cycle
override func awakeFromNib() {
super.awakeFromNib()
textContainerInset = UIEdgeInsets(top: 8, left: 5, bottom: 8, right: 8)
returnKeyType = .done
addSubview(placeHolderLabel)
placeHolderLabel.frame = CGRect(x: 8, y: 8, width: self.bounds.size.width - 16, height: 15)
placeHolderLabel.textColor = textColor
placeHolderLabel.font = font
placeHolderLabel.text = placeHolderText
bringSubviewToFront(placeHolderLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
// MARK: - Notifications
private func enableNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(textDidChangeNotification(_:)), name: UITextView.textDidChangeNotification , object: nil)
}
@objc func textDidChangeNotification(_ notify: Notification) {
guard self == notify.object as? UITextView else { return }
guard placeHolderText != nil else { return }
UIView.animate(withDuration: 0.25, animations: {
self.placeHolderLabel.alpha = (self.text.count == 0) ? 0.5 : 0
}, completion: nil)
}
}
왜 사람들이 이 문제를 그렇게 복잡하게 만드는지 모르겠어요.그것은 꽤 간단하고 간단하다.다음은 요청된 기능을 제공하는 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
}
}
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()
}
}
스위프트 3.1
이 확장은 저에게 있어서 매우 효과적이었습니다.https://github.com/devxoul/UITextView-Placeholder
코드 스니펫을 다음에 나타냅니다.
팟을 통해 설치:
pod 'UITextView+Placeholder', '~> 1.2'
클래스로 가져오기
import UITextView_Placeholder
리리 and and를 추가한다.placeholder
한 「」의 .UITextView
textView.placeholder = "Put some detail"
★★★★★★★★★★★★... 번째 는 ( ( ) )입니다.UITextView
) 。
편집이 완료되면 자리 표시자 텍스트를 다시 표시하기 위해 큐를 디스패치해야 했습니다.
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"
}
}
}
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]
이 게시물의 모든 답변과 달리UITextView
플레이스 홀더 속성이 있습니다.제가 이해할 수 없는 이유로 IB에서만 노출됩니다.
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="placeholder" value="My Placeholder"/>
</userDefinedRuntimeAttributes>
따라서 스토리보드를 사용하고 있으며 정적 플레이스홀더로도 충분할 경우 인스펙터에 속성을 설정합니다.
이 속성은 다음과 같이 코드로 설정할 수도 있습니다.
textView.setValue("My Placeholder", forKeyPath: "placeholder")
날씨가 흐려져 있기 때문에 개인 API를 통해 접근합니다.
저는 이 방법으로 제출해 본 적이 없습니다.하지만 곧 이 방법으로 제출하고 그에 따라 이 답변을 업데이트하겠습니다.
갱신:
저는 이 코드를 Apple에서 문제없이 여러 릴리스로 발송했습니다.
업데이트: 이 기능은 Xcode 11.2 이전에서만 작동합니다.
스위프트 5.2
스탠드아론 클래스
어디서든 사용할 수 있는 클래스를 원하는 경우 이 옵션을 사용하십시오.
import UIKit
class PlaceHolderTextView:UITextView, UITextViewDelegate{
var placeholderText = "placeholderText"
override func willMove(toSuperview newSuperview: UIView?) {
textColor = .lightText
delegate = self
}
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.text == placeholderText{
placeholderText = textView.text
textView.text = ""
textView.textColor = .darkText
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text == ""{
textView.text = placeholderText
textColor = .lightText
}
}
}
서의 열쇠는 '열쇠'입니다.willMove(toSuperView:)
수 in ).ViewDidLoad/View가 표시됩니다.
서드파티 라이브러리를 추가할 필요가 없습니다.아래 코드를 사용하세요...
class SubmitReviewVC : UIViewController, UITextViewDelegate {
@IBOutlet var txtMessage : UITextView!
var lblPlaceHolder : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
txtMessage.delegate = self
lblPlaceHolder = UILabel()
lblPlaceHolder.text = "Enter message..."
lblPlaceHolder.font = UIFont.systemFont(ofSize: txtMessage.font!.pointSize)
lblPlaceHolder.sizeToFit()
txtMessage.addSubview(lblPlaceHolder)
lblPlaceHolder.frame.origin = CGPoint(x: 5, y: (txtMessage.font?.pointSize)! / 2)
lblPlaceHolder.textColor = UIColor.lightGray
lblPlaceHolder.isHidden = !txtMessage.text.isEmpty
}
func textViewDidChange(_ textView: UITextView) {
lblPlaceHolder.isHidden = !textView.text.isEmpty
}
}
IOS에는 TextView에 플레이스홀더를 직접 추가하는 속성이 없습니다.라벨을 추가하고 textView 변경 내용을 표시/숨길 수 있습니다.SWIFT 2.0을 사용하여 textview 위임장을 구현하십시오.
func textViewDidChange(TextView: UITextView)
{
if txtShortDescription.text == ""
{
self.lblShortDescription.hidden = false
}
else
{
self.lblShortDescription.hidden = true
}
}
@nerdistist ner @ @ @ @ @ @ @ @ @ 。으로, 저는 '연장', '연장', '연장', '연장'으로.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 플레이스홀더!
갱신:
텍스트 뷰의 코드 텍스트를 변경할 경우 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)
}
}
신속한3:
import UIKit
클래스 커스텀Text View: UIText View {
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 answer에 딜러 니즈를 1개 추가합니다.
func textViewDidBeginEditing(_ textView: UITextView) {
cell.placeholderLabel.isHidden = !textView.text.isEmpty
}
필요.
textViewDidChange
first (처음이라고 불리지 않음)
텍스트 보기에 사용할 수 있는 자리 표시자가 없습니다.사용자가 텍스트 뷰에 입력할 때 라벨을 붙인 다음 사용자가 입력할 때 라벨을 숨기거나 기본값으로 설정해야 합니다. 모든 값을 제거합니다.
언급URL : https://stackoverflow.com/questions/27652227/add-placeholder-text-inside-uitextview-in-swift
'programing' 카테고리의 다른 글
T-SQL에는 문자열을 연결하는 집약 기능이 있습니까? (0) | 2023.04.23 |
---|---|
iOS에서 이메일 주소가 유효한지 확인합니다. (0) | 2023.04.23 |
가장 일반적인 SQL 안티 패턴은 무엇입니까? (0) | 2023.04.23 |
"이 디렉토리 또는 페이지를 볼 수 있는 권한이 없습니다"를 디버깅하는 방법 (0) | 2023.04.23 |
산점도 점의 레이블을 이름으로 지정하는 방법은 무엇입니까? (0) | 2023.04.23 |