iosquartz-graphicspaintcode

Best way to wire up a PaintCode button?


I have created a custom button in PaintCode. PC has lots of documentation on creating graphics, but not using them.

My method works but it has problems which I'll get to... I went the route of subclassing a UIButton which I placed in my storyboard. I then assigned it the class of my custom button, we'll call it customButton. Using this method you can connect an action in IB, and the highlighted state is handled by the touchesBegan and touchesEnded methods in tandem with a variable that toggles the highlighted view, but the problem is, the highlighted state is never displayed on quick touches.

customButton.m:

@interface customButton ()

@property BOOL isPressed;

@end

@implementation customButton

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

-(void) awakeFromNib {
    [super awakeFromNib];
    _buttonText = @"Post";
}

- (void)drawRect:(CGRect)rect
{
    [StyleKit drawCustomButtonWithFrame:rect pressed:_isPressed buttonText:_buttonText];
}

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    _isPressed = YES;
    [self setNeedsDisplay];
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [self sendActionsForControlEvents:UIControlEventTouchUpInside];
    _isPressed = NO;
    [self setNeedsDisplay];
}

My question: is there a better way to implement a button drawn with PaintCode? The issue with this one is that it doesn't always display the highlighted state, and feels kinda hacky. Surely there's a better way?


Solution

  • The best way to go about this is to override the highlighted property in UIControl. It is the most accurate indicator of the button's state. I am using swift, but it's trivial to translate to ObjC:

    class VectorizedButton: UIButton {
        override var highlighted: Bool {
            didSet {
                setNeedsDisplay()
            }
        }
    }
    

    Now, instead of passing in _isPressed, just pass in highlighted (or [self highlighted]).

    For the sake of completeness:

    - (void)setHighlighted:(BOOL)isHigh
    {
        [super setHighlighted:isHigh];
        [self setNeedsDisplay];
    }
    

    It seems there is a good article about this here.


    Complete code sample:

    NOTE I took it a step further, and highlight if the button is not enabled or highlighted.

    class VectorizedButton: UIButton {
    
        override var highlighted: Bool {
            didSet {
                setNeedsDisplay()
            }
        }
    
        // MARK: - Init & Dealloc
    
        required init(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override func awakeFromNib() {
            super.awakeFromNib()
    
            backgroundColor = UIColor.clearColor()
        }
    
        // MARK: - Private methods
    
        private var shouldHighlight: Bool {
            return highlighted || !enabled
        }
    
        // MARK: - Public methods
    
        override func drawRect(rect: CGRect) {
            StyleKit.drawMyButton(frame: bounds, highlighted: shouldHighlight)
        }
    
    }