iOS

UITextField clear button custom

삼쓰_웅쓰 2021. 10. 16. 23:48
반응형

UITextField 에서는 기본적으로 clear 버튼을 제공하는데요,

이걸 커스텀 하려면 어떻게 하는지, 이때 또 어떤 문제가 있었는지 알아보겠습니다 :)

 


 

기본 clear button

우선 기본적인 clear 버튼은 clearButtonMode를 통해 만들어줄 수 있습니다.

textfield.clearButtonMode = .whileEditing

 

이렇게 4가지 모드가 있는데 각각은 보시면 아시겠죠??

아무튼 이걸 설정해주면 이렇게 clear 버튼이 나타나고, 버튼을 눌러 clear까지 알아서 해줄 수가 있습니다.

 

clear button custom

문제는 저 clear 버튼을 커스텀 할 수가 없다는 겁니다.. (아니 🍎 쓰는김에 좀 더 쓰지...)
제 문제는 저 어두운 배경에서 clear 이 너무 안 보인다는 거 였어요... 

일단 결론부터 말씀드리면 저 버튼을 직접 건드릴 생각은 하면 안 되고 textField의 rightView를 직접 붙여줘서 처리해줘야 합니다.

그래도 다행히 rightView도 rightViewMode를 제공해서 clear 버튼처럼 어느 상황에 나타날지 처리해줄 수가 있어요!
대신, clear 기능은 직접 구현을 해야합니다... ㅠ

rightView는 overlayView를 지정해주는건데요, clearButton은 따로 지정해주기 전에 미리 내장되어있는 overlayView 에요,
그래서 rightView를 지정하고, rightViewMode를 통해서 rightView로 overlayView를 바꿔주면
기존에 내장되어 있던 clearButton(overlayView)은 나타나지 않습니다.

 

구현

큰 원리는 이렇구요,

저는 다른 cancel 이미지를 가지는 버튼을 만들어서 rightView에 붙이는 방식으로 처리를 했습니다.
이 부분은 말 그대로 버튼이나 원하는 뷰를 붙여서 만드는 거라서 원하는 형태로 커스텀 하시면 될 것 같아요.

저는 extension으로 이렇게 처리해봤어요

import UIKit

extension UITextField {
    
    func setClearButton(with image: UIImage, mode: UITextField.ViewMode) {
        let clearButton = UIButton(type: .custom)
        clearButton.setImage(image, for: .normal)
        clearButton.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
        clearButton.contentMode = .scaleAspectFit
        clearButton.addTarget(self, action: #selector(UITextField.clear(sender:)), for: .touchUpInside)
        self.rightView = clearButton
        self.rightViewMode = mode
    }
    
    @objc
    private func clear(sender: AnyObject) {
        self.text = ""
    }
}

 

문제

여기서 한 가지 사소한 문제가 발생하는데요, 기존에 clear 버튼의 동작과 조금 다르게 동작 하는 부분이 있습니다... ㅠㅠ

기존에 clear버튼은 whileEditing 모드일 때, textField의 text가 비어있을 때 clear 버튼이 보이지 않는데요, 
rightView는 whileEditing 모드여도, 그냥 firstResponder만 되어도 rightView가 나타납니다.
물론 clear를 해도 그대로 남아있죠...

사실 큰 문제는 아니라 그대로 써도 되지만.. 기존 clear 버튼처럼 동작하게 하기 위해 다음과 같이 추가해봤습니다.
결국 text가 비어있는지 계속 체크해서 확인해주는 방식이에요. (이게 최선인지는 모르겠습니다,,,)

import UIKit

extension UITextField {
    
    func setClearButton(with image: UIImage, mode: UITextField.ViewMode) {
        let clearButton = UIButton(type: .custom)
        clearButton.setImage(image, for: .normal)
        clearButton.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
        clearButton.contentMode = .scaleAspectFit
        clearButton.addTarget(self, action: #selector(UITextField.clear(sender:)), for: .touchUpInside)
        self.addTarget(self, action: #selector(UITextField.displayClearButtonIfNeeded), for: .editingDidBegin)
        self.addTarget(self, action: #selector(UITextField.displayClearButtonIfNeeded), for: .editingChanged)
        self.rightView = clearButton
        self.rightViewMode = mode
    }
    
    @objc
    private func displayClearButtonIfNeeded() {
        self.rightView?.isHidden = (self.text?.isEmpty) ?? true
    }
    
    @objc
    private func clear(sender: AnyObject) {
        self.text = ""
        sendActions(for: .editingChanged)
    }
}

 

조금이라도 도움이 되셨다면 좋겠네요.

감사합니다 :)

반응형