21


basically I need an image button, specifically a custom object that:
1) calls a controller's action when tapped
2) encapsulates custom data
3) is automatically moved by wrapper view (not relevant)

Well, I got all this with a subclass of UIControl (since subclassing UIButton is not recommended and subclassing UIImageView makes difficult to manage the point 1). But now what is the correct way to highlight it? I would like to highlight the control when tapped in any way (even a simple momentary reduction of alpha).

With beginTrackingWithTouch and endTrackingWithTouch I can't recognize the only UIControlEventTouchUpInside event.

A view animation in the controller? It seems to me a rough solution

Is there a simple and immediate solution?

Thanks :(

qfwfq
  • 976
  • 11
  • 30

3 Answers3

40

I think UIControls automatically set their highlighted property correctly, based solely on touch events. What you need is to override -setHighlighted: method to implement a specific algorithm:

- (void) setHighlighted: (BOOL) highlighted {
    [super setHighlighted: highlighted];
    // Only as an example. Caution: looks like a disabled control
    self.alpha = highlighted ? 0.5f : 1.0f;
}
Costique
  • 23,712
  • 4
  • 76
  • 79
  • 9
    If you have any subviews, don't forget to set mySubview.userInteractionEnabled = NO (otherwise the tap won't be registered and no highlight will be triggered). – Lukas Kalinski Apr 23 '14 at 19:22
24

In the interests of keeping this answer up-to-date, here is the Swift version (of Costique's answer).

override var isHighlighted: Bool {
    didSet {
        alpha = self.isHighlighted ? 0.6 : 1.0 // Sets alpha to 0.6 if highlighted, or 1.0 if it's not.
    }
}

You may also like to fade the dimming of the UIControl. To do this, simply place the alpha assignment in an animation block, like this

override var isHighlighted: Bool {
    didSet {
        UIView.animate(withDuration: 0.25) {
            self.alpha = self.isHighlighted ? 0.6 : 1.0
        }
    }
}
djds23
  • 91
  • 1
  • 7
Loic Verrall
  • 985
  • 15
  • 25
  • 1
    I found that using `didSet` caused by touches to be delayed. `set(highlighted) {` worked better - but only if I didn't call super – Sam Oct 12 '16 at 18:32
0

To highlight subviews of UIControl properly you can use custom tint color. To enable this, somewhere in init methods or awakeFromNib you should change image rendering mode to always template:

self.imageView.image = [self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
self.backgroundImageView.image = [self.backgroundImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
self.tintColor = [UIColor zst_blueColor]; // Use custom instead of system-defined color

So instead of changing alpha value we can change tint color and it will change its UIImageView subviews automatically. In the setHighlighted: method you can change text and tint color to a darker color:

- (void)setHighlighted:(BOOL)highlighted
{
    [super setHighlighted:highlighted];
    UIColor *tintColor = highlighted ? [UIColor zst_darkerBlueColor] : [UIColor zst_blueColor];
    self.tintColor = tintColor;
    self.titleLabel.textColor = tintColor;
}
irmco
  • 924
  • 10
  • 13