How to ignore touch events and pass them to another subview's UIControl objects?
Probably the best way to do this is to override hitTest:withEvent:
in the view that you want to be ignoring touches. Depending on the complexity of your view hierarchy, there are a couple of easy ways to do this.
If you have a reference to the view underneath the view to ignore:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = [super hitTest:point withEvent:event];
// If the hitView is THIS view, return the view that you want to receive the touch instead:
if (hitView == self) {
return otherView;
}
// Else return the hitView (as it could be one of this view's buttons):
return hitView;
}
If you don't have a reference to the view:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = [super hitTest:point withEvent:event];
// If the hitView is THIS view, return nil and allow hitTest:withEvent: to
// continue traversing the hierarchy to find the underlying view.
if (hitView == self) {
return nil;
}
// Else return the hitView (as it could be one of this view's buttons):
return hitView;
}
I would recommend the first approach as being the most robust (if it's possible to obtain a reference to the underlying view).
Pass touch to other viewcontroller that is clear
I would prefer to use a TapGestureRecognizer and then to decide what to do in certain coordinates:
Inside viewDidLoad of your topmost viewController:
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.didRecognizeTapGesture(gesture:)))
self.view.addGestureRecognizer(tapGesture)
Add a method inside the same controller:
func didRecognizeTapGesture(gesture: UITapGestureRecognizer)
{
let point = gesture.location(in: gesture.view)
if(gesture.state == UIGestureRecognizerState.ended) {
let desiredFrame = CGRect(...) //e.g the portion of screen, where you need to make exceptional touch event
if(desiredFrame.contains(point)) {
print("... Caught a gesture")
}
}
}
How to prevent UIView passing touch events to UIView's superview?
Make use of:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
int the UIGestureRecognizerDelegate
return YES if you should receive touch NO if not, based on what ever logic you want to apply. You have the UITouch and UIGestureRecognizer which both contain lots of useful information.
Remember to set delegate of UIGestureRecognizer to self.
How can a UIControl pass all touch events on to the next object in the responder chain?
Might want to take a look at this post that shows ways to synthesize touch events. It stopped working for a while, though. Revisiting it just now it looks like he's updated it for 3.0 support so it might work for you. A caveat is that it might not be legit for a shipping app.
An easier way is to break out the method that does the work (let's call it bigButtonWork
) when the big button gets tapped and make it public. Then the big button tap handler just calls this routine. When the small button gets tapped you can choose inside its handler to do its own thing or call bigButtonWork
instead.
But I'm guessing you want it to simulate the big button actually getting pushed (complete with highlights and state changes) so you may have to go the synthesized event route.
iOS: How to forward touch events from subview to superview?
Overriding (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
in your UIView and always returning NO should do the trick.
Define custom touch area in custom UIControl object
You can override UIView's pointInside:withEvent:
to reject unwanted touches.
Here's a method that checks if the touch occurred in a ring around the center of the view:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
UITouch *touch = [[event touchesForView:self] anyObject];
if (touch == nil)
return NO;
CGPoint touchPoint = [touch locationInView:self];
CGRect bounds = self.bounds;
CGPoint center = { CGRectGetMidX(bounds), CGRectGetMidY(bounds) };
CGVector delta = { touchPoint.x - center.x, touchPoint.y - center.y };
CGFloat squareDistance = delta.dx * delta.dx + delta.dy * delta.dy;
CGFloat outerRadius = bounds.size.width * 0.5;
if (squareDistance > outerRadius * outerRadius)
return NO;
CGFloat innerRadius = outerRadius * 0.5;
if (squareDistance < innerRadius * innerRadius)
return NO;
return YES;
}
To detect other hits on more complex shapes you can use a CGPath
to describe the shape and test using CGPathContainsPoint
. Another way is to use an image of the control and test the pixel's alpha value.
All that depends on how you build your control.
How to add touch event for custom uicontrol and controller?
Use delegates, add a protocol in your UIControl that needs to be implemented in your ViewController.
This way you can detect if a button is clicked in your UIControl and invoke a specific function in your VC.
For Example:
//YourUIControl.Swift
protocol YourUIControlDelegate {
func didTapFirstButton()
}
class YourUiControl : UIView { //I'm assuming you create your UIControl from UIView
var delegate : YourUIControlDelegate?
//other codes here
.
.
.
@IBAction func tapFirstButton(_ sender: AnyObject) {
if let d = self.delegate {
d.didTapFirstButton()
}
}
}
//YourViewController.Swift
extension YourViewController : UIControlDelegate {
func didTapFirstButton() {
//handle first button tap here
}
}
Make UIControl only accept swipe gestures and pass along touch/tap gestures
This question is similar to yours. Subclass your UIControl
and override - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
and call its super
variant to pass it up to its view.
Pass touch events to one of multiple options
By default, UIImageView
overrides the value of the userInteractionEnabled
property to NO
(see http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImageView_Class/Reference/Reference.html
#//apple_ref/occ/instp/UIImageView/userInteractionEnabled). This is what is causing your UIImageViews
to not receive touch events, and so they are accepted by the board superview.
To make it so your UIImageViews
receive touch events, just set the userInteractionEnabled
property to YES
.
Related Topics
Getting List of Files in Documents Folder
Customize Uitableview Header Section
Subclass Uiapplication With Swift
How to Iterate For Loop in Reverse Order in Swift
Getting All Cookies from Wkwebview
Xcode 9 Error: "Iphone Has Denied the Launch Request"
How to Change Multiplier Property For Nslayoutconstraint
Uinavigationbar Custom Back Button Without Title
How to Detect If App Is Being Built For Device or Simulator in Swift
Enabling Auto Layout in iOS 6 While Remaining Backwards Compatible With iOS 5
How Does View Controller Containment Work in iOS 5
Fatal Error: Use of Unimplemented Initializer 'Init(Coder:)' For Class
Create Thread Safe Array in Swift
Ios 6: How to Restrict Some Views to Portrait and Allow Others to Rotate
How to Use Protocol as Associatedtype in Another Protocol in Swift