Custom Clear Button for UITextField

Too many times I've found myself needing the clear button for a text field to be in a slightly different spot, or a slightly different color.

Thus begins the dreaded context switch from Xcode to Pixelmator or <Image Editor of Choice>, in an attempt to re-create the clear button in the right dimensions and colors.

Forget that noise. Just use this (as of Swift 1.2):

class ClearView : UIView {

    var textField : UITextField? {
        didSet {
            self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "clearButtonPressed:"))

    var buttonBackgroundColor = Colors.gray(210)
    var buttonXColor = Colors.gray(40)

    let X_PADDING_PERCENT : CGFloat = 0.3
    let LINE_WIDTH : CGFloat = 2.0

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = UIColor.clearColor()

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.backgroundColor = UIColor.clearColor()

    @objc private func clearButtonPressed(sender: AnyObject) {
        if let tf = self.textField {
            tf.text = ""

    override func drawRect(rect: CGRect) {
        let dotStartPoint = CGPointZero


        // Background
        UIBezierPath(roundedRect: self.bounds, cornerRadius: self.bounds.size.width / 2.0).fill()


        // First slash: \
        let firstSlash = UIBezierPath()

        // Give the 'X' a bit of padding from the bounds
        let slashPadding = self.bounds.size.width * X_PADDING_PERCENT

        // Start in the upper-left
        var topLeft = CGPointMake(self.bounds.origin.x + slashPadding, self.bounds.origin.y + slashPadding)
        // Slide down, and to the right
        topLeft.x = self.bounds.origin.x + self.bounds.size.width - slashPadding
        topLeft.y = self.bounds.origin.y + self.bounds.size.height - slashPadding

        // Create a copy of the first slash: \
        let secondSlash = UIBezierPath(CGPath: firstSlash.CGPath)
        // Mirror the slash over the Y axis: /
        let mirrorTransform = CGAffineTransformMakeScale(1.0, -1.0);
        // And translate ("move") the path to intersect the first slash
        let translateOverY = CGAffineTransformMakeTranslation(0.0, self.bounds.size.height)

    private func styleBezierPath(path: UIBezierPath) {
        path.lineWidth = LINE_WIDTH
        path.lineCapStyle = kCGLineCapRound

As it's a UIView, it will scale to the size you want, can be layered on top of other views, accepts UITapGestureRecognizer instances, etc.

You use it like:

let CLEAR_BUTTON_SIZE : CGFloat = 14  
let BUTTON_PADDING : CGFloat = 8

let clearView = ClearView(frame: CGRectMake(BUTTON_PADDING / 2.0, BUTTON_PADDING / 2.0, CLEAR_BUTTON_SIZE, CLEAR_BUTTON_SIZE))  
clearView.textField = textField

textField.rightViewMode = .WhileEditing;  
textField.rightView = clearView  

And you get:

Example Clear Button

Note that in this case, I have a dark background and thus a lighter clear button. This is the default in the code above, but you can easily style it however you'd like:

clearView.buttonBackgroundColor = Colors.rgb(34, 83, 120)  
clearView.buttonXColor = UIColor.whiteColor()  


It scales to any size you'd like, and you can cut out the textField property if you want to code in your own custom behavior when the view is tapped.

comments powered by Disqus