10

I have a container view completely covering another UIView. The container view has transparency along with a few other things (search bar, table view, etc). I want touch events to go through the container view and affect the view underneath when the event occurs in an area that is transparent.

I have been messing around with a subclass of a container view. I'm trying to get the pointInside: method to return YES or NO based on the above criteria (transparent container view). My problem is as far as I know I only have access to the container views subviews, not the view completely underneath the container view.

I have currently been using a very inefficient method of reading the touched pixels alpha. What would be the best way to go about doing this?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
i2Fluffy
  • 333
  • 2
  • 12

1 Answers1

11

If you just want touches to pass through your container view while still letting its subviews be able to handle touches, you can subclass UIView and override hitTest:withEvent: like this:

Swift:

class PassthroughView: UIView {

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        // Get the hit view we would normally get with a standard UIView
        let hitView = super.hitTest(point, with: event)

        // If the hit view was ourself (meaning no subview was touched),
        // return nil instead. Otherwise, return hitView, which must be a subview.
        return hitView == self ? nil : hitView
    }
}

Objective-C:

@interface PassthroughView : UIView
@end

@implementation PassthroughView

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    // Get the hit view we would normally get with a standard UIView
    UIView *hitView = [super hitTest:point withEvent:event];

    // If the hit view was ourself (meaning no subview was touched),
    // return nil instead. Otherwise, return hitView, which must be a subview.
    return hitView == self ? nil : hitView;
}

@end

Then have your container view be an instance of that class. Also, if you want your touches to pass through the above view controller's view, you will need to make that view controller's view also be an instance of that class.

TylerP
  • 9,600
  • 4
  • 39
  • 43
  • I have not been able to get your suggestion to work. Behind the container view I have a viewController that contains a specific view I would like the touches to go to. Any advice? – i2Fluffy Aug 11 '14 at 10:47
  • Hmmm, okay. I have a few questions then. (1) What do you mean by "affect the view underneath", exactly? (2) What do you mean when you say you want the touches to go to a specific view? (Are we not just talking about the view behind the container view?) (3) What is your view hierarchy like? (4) What do you mean by "transparency"? How are these transparent areas on your container view defined? (I assumed you just set the container view's background color to Clear Color and that the container view itself (not its subviews) was the transparent area.) Could you update your question with this info? – TylerP Aug 11 '14 at 15:40
  • Lets say I have ViewControllerA. Then on top of ViewControllerA I have a container view that contains ViewControllerB. I want touch events to pass through the container view if the area touched in ViewControllerB is transparent (alpha == 0).If that criteria is met I want the touch to affect a UIView property on ViewControllerA. By affect I mean I want the view to respond as if the touch went down directly on it.Yes, I just set my container view's background color to clear. The container view itself is the transparent area. Let me know if this is the worst design you have ever seen :) thanks. – i2Fluffy Aug 11 '14 at 21:40
  • When you say your container view contains ViewControllerB, do you mean your container view contains ViewControllerB's view? If so, then you want your touches to not only pass through your container view, but also ViewControllerB's view (and any other container view between your container view and ViewControllerB's view if you have any). To do that, you will want to make ViewControllerB's view (and any other container view in between if you have any) be of that same `UIView` subclass that I describe in my answer above. If that doesn't make sense, I can update my question. – TylerP Aug 12 '14 at 02:33
  • Ok, I think I understand what you are saying. What is the best way to do that without a bunch of copy and pasting? How do I take the subclass I made for my container view and insert it as a sub view of a search bar and a table view? Category? – i2Fluffy Aug 12 '14 at 04:05
  • 1
    I think you may misunderstand. You don't need to insert any more views than you already have. Just make your container view be that class and your ViewControllerB's view be that class as well. If you are using storyboards or xibs, you can do this by selecting a view and changing its class in the Attributes Inspector. You would do this for both your container view and ViewControllerB's view. Try that to see if it produces anything like what you want. If not, I may have to just delete my answer. :/ – TylerP Aug 12 '14 at 04:54
  • I definitely didn't undersand until your last comment lol. Thank you so much for your help! It worked! – i2Fluffy Aug 12 '14 at 05:18