When multiple uiviews are stacked, for example, when a button is overwritten by a uiview, how can we achieve this if we want to trigger the corresponding event of the button when we click the top-level uiview, several methods can be thought of at first:
1. Set the userinteractionenabled attribute of all uiviews on the top of the button to No. What should I do if uiview has its own interactive events? The userinteractionenabled parameter cannot be set dynamically. It is useless to set its no after clicking it.
2. uiview takes the initiative to trigger the following Button clicking after receiving the click event. There are three things in this case. It is impractical if the button does not have the exchange effect during the clicking process or when multiple layers of uiview are selected, layer-by-layer downloading? How can I deal with other double-click, triple-click, or other gestures?
I have been entangled in the previous two methods, and also reminded the nsarray * passthroughviews attribute of uipopovercontroller, because for uipopovercontroller, control events set to its passthoughviews attribute can be completely transparent from uidimmingview. However, it is hard to see the source code of uipopovercontroller, and Google finally found the method of uiview:
-(Uiview *) hittest :( cgpoint) Point withevent :( uievent *) event; // recursively cballs-pointinside: withevent:. Point is in the specified er's Coordinate System
As long as the hittest method of the top-level uiview is implemented, a lower-level button instance is returned in some cases, that is, the event of that button is revealed. For example, when you click this button, no matter how many layers of the button in the uiview can be dug out.
First look:
The three figures are:
1. As you can see, the button is partially covered by a translucent red view.
2. You can click the hidden button to see the effect of the button being clicked but not lifted.
3. In the red view, clicking the button to hide the part also triggers the corresponding event of the button and has an intermediate effect. That is to say, the button passes through.
Let's look at the code implementation. There are two parts of the Code: viewcontroller and customcontroller.
Original link: http://unmi.cc/uiview-event-passthrough, from: yeye Huang Ying unmi blog
Viewcontroller. h
//// ViewController.h //// Created by Unmi on 11/15/11.// Copyright (c) 2011 http://unmi.cc. All rights reserved.// #import <UIKit/UIKit.h> @interfaceViewController : UIViewController{} @end
Viewcontroller. h
//// ViewController.m//// Created by Unmi on 11/15/11.// Copyright (c) 2011 http://unmi.cc. All rights reserved.// #import "ViewController.h"#import "CustomView.h" @implementationViewController{ UIButton*passthroughButton;} #pragma mark - View lifecycle - (void)viewDidLoad{ [superviewDidLoad]; passthroughButton = [UIButtonbuttonWithType:UIButtonTypeRoundedRect]; [passthroughButton setTitle:@"Passthrough"forState:UIControlStateNormal]; [self.view addSubview:passthroughButton]; passthroughButton.frame = CGRectMake(20, 50, 120, 28); [passthroughButton release]; CustomView *customView = [[CustomView alloc] initWithFrame:CGRectMake(80, 10, 300, 200)]; customView.backgroundColor = [UIColorcolorWithRed:1 green:0 blue:0 alpha:.5]; customView.passthroughViews = [NSArrayarrayWithObject:passthroughButton]; [self.view addSubview:customView]; [customView release];} - (void)dealloc { [superdealloc];}@end
Customview. h
//// CustomView.h// TestPopover//// Created by Unmi on 2/19/12.// Copyright (c) 2012 http://unmi.cc. All rights reserved.// #import <UIKit/UIKit.h> @interfaceCustomView : UIView@property(nonatomic,copy) NSArray *passthroughViews;@end
Customview. m
//// CustomView.m//// Created by Unmi on 2/19/12.// Copyright (c) 2012 http://unmi.cc. All rights reserved.// #import "CustomView.h" @interfaceCustomView()-(BOOL) isPassthroughView: (UIView*) view;@end @implementationCustomView{ BOOLtestHits;} @synthesizepassthroughViews=_passthroughViews; -(UIView*) hitTest:(CGPoint)point withEvent:(UIEvent*)event{ if(testHits){ returnnil; } if(!self.passthroughViews || (self.passthroughViews &&self.passthroughViews.count == 0)){ returnself; }else { UIView*hitView = [superhitTest:point withEvent:event]; if(hitView == self) { //Test whether any of the passthrough views would handle this touch testHits =YES; CGPoint superPoint = [self.superview convertPoint:point fromView:self]; UIView*superHitView = [self.superview hitTest:superPoint withEvent:event]; testHits =NO; if([self isPassthroughView:superHitView]) { hitView = superHitView; } } returnhitView; }} - (BOOL)isPassthroughView:(UIView*)view { if(view == nil) { returnNO; } if([self.passthroughViews containsObject:view]) { returnYES; } return[self isPassthroughView:view.superview];} -(void) dealloc{ self.passthroughViews =nil;} @end
The key is to understand the role of the hittest method. For details, refer:
1. http://blog.sina.com.cn/s/blog_677089db01012wpg.html
2. https://github.com/werner77/WEPopover