How to highlight a UIView like Apple does

You can use a custom view like this for example:

class HighlightView: UIView {

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        DispatchQueue.main.async {
            self.alpha = 1.0
            UIView.animate(withDuration: 0.4, delay: 0.0, options: .curveLinear, animations: {
                self.alpha = 0.5
            }, completion: nil)
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        DispatchQueue.main.async {
            self.alpha = 0.5
            UIView.animate(withDuration: 0.4, delay: 0.0, options: .curveLinear, animations: {
                self.alpha = 1.0
            }, completion: nil)
        }
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        DispatchQueue.main.async {
            self.alpha = 0.5
            UIView.animate(withDuration: 0.4, delay: 0.0, options: .curveLinear, animations: {
                self.alpha = 1.0
            }, completion: nil)
        }
    }
}

Then you can use it instead of UIView and whenever you will click on it, it will change it's alpha value so it will look like a highlight.


I don't think there is an easy or definitive answer to that.

DISCLAIMER: All the code in this answer was written from the top of my head, so please excuse mistakes.

I would suggest doing something like this:

Proposal 1: decrease opacity for all the view's subviews, which would not affect color...

Objective C:

-(void)buttonTouched{
    for(UIView *subview in self.subviews){ 
        subview.alpha = 0.5;
    }
}

Swift:

func buttonTouched() {
    for subview in subviews {
        subview.alpha = 0.5
    }
}

Proposal 2 (not tested): try to cover all subviews by doing it kind of manually (drawback: you would have to set the colors back manually as well, which would be insane if it is not monochromatic):

Objective C:

-(void)buttonTouched{
    for(UIView *subview in self.subviews){

        if([subview respondsToSelector:@selector(setBackgroundColor:)]){ 
            //for generic views - changes UILabel's backgroundColor too, though
            subview.backgroundColor = [UIColor grayColor];
        }

        if([subview respondsToSelector:@selector(setTextColor:)]){ 
            //reverse effect of upper if statement(if needed)
            subview.backgroundColor = [UIColor clearColor];
            subview.textColor = [UIColor grayColor];
        }
    }
}

Swift:

func buttonTouched() {
    for subview in subviews {
        if subview.responds(to: #selector(setter: AVMutableVideoCompositionInstruction.backgroundColor)) {
            //for generic views - changes UILabel's backgroundColor too, though
            subview.backgroundColor = UIColor.gray
        }

        if subview.responds(to: #selector(setter: UILabel.textColor)) {
            //reverse effect of upper if statement(if needed)
            subview.backgroundColor = UIColor.clear
            subview.textColor = UIColor.gray
        }
    }
}

This is really bad design and will probably cause a lot of problems, but it could potentially help you. The example above needs a lot of improvement, I just want to give you a hint. You would have to revert the colors in the touchesEnded: method. Maybe it helps you...

Proposal 3: would be to overlay your whole view with a transparent view (if it is rectangular)

Objective C:

-(void)buttonTouched{
    UIView *overlay = [[UIView alloc]initWithFrame:self.bounds];
    overlay.backgroundColor = [[UIColor grayColor]colorWithAlphaComponent:0.5];
    [self addSubview: overlay];
}

Swift:

func buttonTouched() {
    let overlay = UIView(frame: bounds)
    overlay.backgroundColor = UIColor.gray.withAlphaComponent(0.5)
    addSubview(overlay)
}

You would have to remove it when the user releases the finger of course.

Proposal 4 : Another option would be to create a bitmap of your current view and modify the pixels to your liking, which is quite a bit of work, so I will omit code here.

Apple probably does a mix of the last two. When a button is touched it will go over the pixels and overlay a gray pixel over every pixel that has an alpha component.

I hope I could help.


I know this is an old question. But if someone is still searching for a generic touch highlighting solution, here is a little category I have created to address the problem.

https://github.com/mta452/UIView-TouchHighlighting

Usage:

Just import the category in your view controller and add the following line in viewDidLoad.

buttonView.touchHighlightingStyle = MTHighlightingStyleHollowDarkOverlay;

Different Highlighting Styles:

Screenshot