Weekoding
[Swift] TextView PlaceHolder(Custom) 본문
Placeholder : 자리 표시자.
앱 개발 시 사용자에게 보다 편리한 UX를 제공하기 위해,
Text를 입력할 수 있는 컴포넌트에는 PlaceHolder가 보통 기본 속성으로 포함되어있다.
아래와 같은 모양의 UI를 많이 보았을 것이다.
내용을 입력하세요.. |
이렇게 TextField / TextView를 그냥 두기보다, Placeholder를 이용하여 사용자에게 해당 컴포넌트의 역할을 알려주는 것이다.
근데 Swift의 TextView에는 Placeholder가 없다..?🫠
공부를 하다가 교묘하게 Placeholder 모양새를 낼 수 있는 방법을 알아내어 포스팅 하게 되었다.
뚝딱뚝딱 Snapkit으로 UI를 간단하게 구성해보았다.(SnapKit 코딩은 이전 포스팅 참고)
위에 있는 컴포넌트가 TextView, 아래의 컴포넌트가 TextField이다.
TextField는 Placeholder 속성이 존재하여 바로 "Write me"라는 문구를 넣어 주었다.
self.txtField.placeholder = "Write me"
확실히 TextView는 Placeholer로 지시된 바가 없어, 덩그러니 놓여있는 느낌이다.
각 View의 크기는 내가 임의로 지정한 것이다. 이제 Field와 View의 차이점을 살펴보자.
📂 Before
정리해 보자면 대략 이렇다.
TextView | TextField | |
공통점 | • Text를 쓰고, 편집할 수 있다. | |
차이점 | • 여러줄 사용 가능 (줄의 개수 많아지면 자동으로 스크롤 제공) • Placeholder 없음 |
•한 줄만 사용 가능 • Placeholder 있음 |
⌘ How to Solve?
생각보다 대단한 로직이나 메소드를 사용하진 않는다. 일단 TextView의 Placeholder가 될 초기 값을 설정해주어야 한다.
//Custom PlaceHolder
self.txtView.text = "Write me First"
self.txtView.textColor = .systemGray3
해결 방법은 UITextViewDelegate를 이용하는 것이다.
extension ViewController: UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
guard txtView.textColor == .systemGray3 else { return }
txtView.text = nil
txtView.textColor = .label
}
func textViewDidEndEditing(_ textView: UITextView) {
if(txtView.text == ""){
txtView.text = "Write me First"
txtView.textColor = .systemGray3
}
}
}
TextView의 Delegate를 상속받은 후, DidBeginEditing / DidEndEditing의 함수를 이용하면 Placeholder 느낌을 낼 수 있다.
조건문이 잘못되면 Text 입력을 마침과 동시에 공백이 되어버린다던가, 글자색이 계속 옅은 색이되는 오류가 날 수 있다.
📂 After
글자 색상이 살짝 다른 것 빼고는 그럴싸하다고 생각한다!
다른 앱도 TextView를 사용할 때, 이런 식으로 Custom한 Placeholder를 사용하는 것 같다.
📂 전체 코드
import UIKit
import SnapKit
class ViewController: UIViewController{
let txtView = UITextView()
let txtField = UITextField()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .systemBackground
self.setView()
}
private func setView(){
self.setViewStyle()
[txtView, txtField].forEach( {view.addSubview($0)} )
self.txtView.snp.makeConstraints({
$0.height.equalTo(150)
$0.trailing.leading.equalToSuperview().inset(50)
$0.centerY.equalToSuperview().offset(-50)
})
self.txtField.snp.makeConstraints({
$0.height.equalTo(60)
$0.trailing.leading.equalToSuperview().inset(50)
$0.top.equalTo(txtView.snp.bottom).offset(30)
})
}
private func setViewStyle(){
self.txtView.delegate = self
self.txtView.backgroundColor = .systemGray5
self.txtView.font = .systemFont(ofSize: 20)
self.txtView.autocapitalizationType = .none //자동 대문자 방지
self.txtView.layer.cornerRadius = 12
//Custom PlaceHolder
self.txtView.text = "Write me First"
self.txtView.textColor = .systemGray3
self.txtField.backgroundColor = .systemGray5
self.txtField.font = .systemFont(ofSize: 20)
self.txtField.placeholder = "Write me"
self.txtField.layer.cornerRadius = 12
}
}
extension ViewController: UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
guard txtView.textColor == .systemGray3 else { return }
txtView.text = nil
txtView.textColor = .label
}
func textViewDidEndEditing(_ textView: UITextView) {
if(txtView.text == ""){
txtView.text = "Write me First"
txtView.textColor = .systemGray3
}
}
}
📌 마치며
다른 공부를 하다가 오랜만에 SnapKit을 쓰려고 하니까 머리가 조금씩 고장이 났었다,,
틈틈히 다시 공부 해야지!
오류 및 지적사항은 댓글로 남겨주시면 감사하겠습니다!
'공부 노트(Swift)' 카테고리의 다른 글
[Swift] Property Observer (0) | 2023.01.01 |
---|---|
[Swift] Property(프로퍼티) (0) | 2022.10.03 |
[Swift] HTTP 접근 허용하기(App Transport Security) (0) | 2022.07.26 |
[Swift] weak self, guard let self = self, self?. (0) | 2022.06.06 |
[Swift] 생명주기 정리( App / ViewController ) (0) | 2022.05.22 |