Highlighting a UIView similar to UIButton

11,131

Solution 1

setHighlighted isn't an animatable view property. Plus, you're saying two opposite things: you setHighlighted to YES and NO in the same breath. The result will be that nothing happens because there's no overall change.

Use the completion handler or delayed performance to change the highlight later.

EDIT:

You say "tried both but neither worked." Perhaps you need clarification on what I mean by delayed performance. I just tried this and it works perfectly:

- (void) tapped: (UIGestureRecognizer*) g {
    label.highlighted = YES;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        label.highlighted = NO;
    });
}

The label must have a different textColor vs its highlightedTextColor so that something visible happens.

Solution 2

Swift 4

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)
        }
    }
}

Just play around with the duration and animations as you like. In the end you can use it instead of UIView and whenever you will click on it, it will change its alpha value so it will look like a highlight.

Solution 3

Simple solution is override tap gesture regognizer like below:

Swift 4.x

class TapGestureRecognizer: UITapGestureRecognizer {
    var highlightOnTouch = true

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        super.touchesBegan(touches, with: event)

        if highlightOnTouch {
            let bgcolor = view?.backgroundColor
            UIView.animate(withDuration: 0.1, delay: 0, options: [.allowUserInteraction, .curveLinear], animations: {
                self.view?.backgroundColor = .lightGray
            }) { (_) in
                UIView.animate(withDuration: 0.1, delay: 0, options: [.allowUserInteraction, .curveLinear], animations: {
                    self.view?.backgroundColor = bgcolor
                })
            }
        }
    }

}
Share:
11,131

Related videos on Youtube

Jonas Gardner
Author by

Jonas Gardner

Updated on June 04, 2022

Comments

  • Jonas Gardner
    Jonas Gardner almost 2 years

    I have a UIView with a number of subviews and a Tap gesture recognized associated and I want to mimic it having a 'touch' effect. That is, when the tap happens, I want to show the container view to have a different background color and the text of any subview UILabels to also look highlighted.

    When I receive the tap event from UITapGestureRecognizer, I can change the background color just fine and even set the UILabel to [label setHighlighted:YES];

    For various reasons, I cannot change the UIView to UIControl.

    But if I add some UIViewAnimation to revert the highlighting, nothing happens. Any suggestions?

        - (void)handleTapGesture:(UITapGestureRecognizer *)tapGesture {
          [label setHighlighted:YES]; // change the label highlight property
    
    [UIView animateWithDuration:0.20 
                              delay:0.0 
                            options:UIViewAnimationOptionCurveEaseIn
                         animations:^{
                             [containerView setBackgroundColor:originalBgColor];          
                             [label setHighlighted:NO]; // Problem: don't see the highlight reverted
                         } completion:^(BOOL finished) {                         
                             // nothing to handle here
                         }];    
    }
    
    • Peter Kazazes
      Peter Kazazes about 12 years
      Why not just make it a UIButton?
    • Jonas Gardner
      Jonas Gardner about 12 years
      Because it is not a codebase I own and there's other dependencies so I have to leave it as UIView.
    • Tayyab Akram
      Tayyab Akram over 7 years
      Have a look at this library: github.com/mta452/UIView-TouchHighlighting
  • Jonas Gardner
    Jonas Gardner about 12 years
    Tried both but neither worked.. I may have to figure out an another creative way to do this or go about rewiring the existing codebase to use UIControl.
  • Ryan
    Ryan about 4 years
    when is highlightOnTouch set to false?
  • SPatel
    SPatel about 4 years
    let gesture = TapGestureRecognizer( :_:) gesture. highlightOnTouch = false
  • Ryan
    Ryan about 4 years
    oh, sorry, I was misunderstood. I thought it was a variable to reset the background color, but it just a variable to enable/disable this feature.