Floating Placeholder
- 입력창에 표시되는 placeholder가, 텍스트를 입력하면 위로 작아지며 떠오르는 효과
- 아무것도 입력하지 않으면 placeholder가 텍스트필드 안 중앙에 있음
- 사용자가 텍스트를 입력하거나 포커스가 생기면 placeholder가 작아지며 위로 이동 (위쪽 label처럼 보여짐)
- 텍스트가 사라지고 포커스도 없으면 다시 제자리로 내려옴
왜 사용할까?
- 사용자 경험 향상: 입력 필드가 어떤 의미인지 계속 볼 수 있음
- 공간 절약: 별도로 라벨을 만들지 않아도 됨
구현 방법
- UILabel + UITextField 조합
UILabel을 placeholder로 사용
UITextField에 포커스 또는 입력 여부에 따라 UILabel 위치 및 크기 조절
- 애니메이션 활용 (transform, alpha, constraints)
class FloatingTextField: UIView {
private let placeholderLabel = UILabel()
let textField = UITextField()
private var isFloating = false
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
fatalError()
}
private func setup() {
textField.borderStyle = .roundedRect
textField.addTarget(self, action: #selector(textChanged), for: .editingChanged)
textField.delegate = self
placeholderLabel.text = "이메일"
placeholderLabel.font = UIFont.systemFont(ofSize: 16)
placeholderLabel.textColor = .lightGray
placeholderLabel.translatesAutoresizingMaskIntoConstraints = false
addSubview(textField)
addSubview(placeholderLabel)
textField.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
placeholderLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8),
placeholderLabel.topAnchor.constraint(equalTo: topAnchor, constant: 18),
textField.topAnchor.constraint(equalTo: topAnchor),
textField.leadingAnchor.constraint(equalTo: leadingAnchor),
textField.trailingAnchor.constraint(equalTo: trailingAnchor),
textField.bottomAnchor.constraint(equalTo: bottomAnchor)
])
}
@objc private func textChanged() {
updatePlaceholder()
}
private func updatePlaceholder() {
let shouldFloat = !(textField.text?.isEmpty ?? true) || textField.isFirstResponder
guard shouldFloat != isFloating else { return }
isFloating = shouldFloat
UIView.animate(withDuration: 0.25) {
self.placeholderLabel.transform = isFloating ? CGAffineTransform(translationX: -5, y: -15).scaledBy(x: 0.75, y: 0.75) : .identity
}
}
}
extension FloatingTextField: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
updatePlaceholder()
}
func textFieldDidEndEditing(_ textField: UITextField) {
updatePlaceholder()
}
}