Objective-C - addToSubview but do not intercept touches - ios

Is there a way you can add a UIView without the view intercepting touches? I tried insertSubview: belowSubview
The reason I want to do this is because I'm adding a UITextField to a UITableViewCell's contentView. But I don't want the UITextField intercepting the touches when I select a row. I know I can set the UITextField userInteractionEnabled property to NO but this leads to a lot of micro management.

Override canBecomeFirstResponder to return NO.
See this info on the Responder Chain.

Related

Exclusive touch on UIControl

I have an UIButton and UISwitch. A user could touch both with one finger each at the same time and release - triggering 2 separate TouchUpInside #IBActions.
How can I tell a control that it's touches must be exclusive, without creating a subclass?
UIControl is subclass of UIView so you can directly set exclusiveTouch = true on any UI control.

UICollectionView didSelectItemAtIndexPath not called when tapped on UITextView

I have a UICollectionView with custom cells- They have a UITextView that mostly covers the entire cell. This presents a problem when using didSelectItemAtIndexPath. The only way to trigger it is by tapping outside the UITextView. I want it to trigger wherever in the cell you tap, whether there is a text view or not. How can this be done?
didSelectItemAtIndexPath is called when none of the subView of collectionViewCell respond to that touch. As the textView respond to those touches, so it won't forward those touches to its superView, so collectionView won't get it.
override hitTest:withEvent method of your collectionViewCell or CollectionView subclass and always return self from them.so it explicitly makes collectionView as first responder.
I would suggest to use UIGestureRecognizer for each cell and when it taped to send it to UITextView or whatever , perhaps there maybe a better solutions , but I would use this 1 because of simplicity reasons.
Do you override touchesEnded: withEvent: ?
I had the same problem today and I found that I have some customised logic in touchesEnded in one of collectionview's container views, and I didn't call
[super touchesEnded: withEvent:]
when I'm done with my customised logic in touchesEnded.
After adding the super call, everything is fine.
Select UITextView, in that specific case UICollectionViewCell, and switch to attribute inspector. The uncheck User interaction enabled and it should work fine.
I ran into this problem when I had a scroll view taking up my entire collection view cell. While all the solutions above probably work fine, I came up with my own elegant work-around. I put a 'select' label under my scroll view. Since the label is not part of the scroll view, it passes the tap event on to the collection view. It also serves as a nice indicator that an action is required of the user.
Just do this
textview.isUserInteractionEnabled = false

Touch events on subclass of UIView as a subview of UIScrollView

I have implemented my own custom subclass of UIView and overridden the drawRect: method.
In my custom view I also want the handle touches, so I also overridden touchesBegan, touchesMoved and touchesEnded.
This works fine but if the number of views on the screen increases then I have to use a UIScrollView as the root view of my UIViewController.
Once my custom UIView becomes the subview of UIScrollView, then it does not receive the touch events. Even though I move my finger within my custom UIView, the scroll view gets scrolled (all my touch events go to the UIScrollView).
How do I solve this problem?
There are several approaches you could try:
Try setting the below properties on the UIScrollView:
scrollView.delaysContentTouches = NO;
scrollView.canCancelContentTouches = NO;
See similar SO questions/answers here, here.
Implement hitTest:withEvent:. See here, here.
Use a UIGestureRecognizer. See here, here.
I would personally recommend using a UIGestureRecognizer, but it depends on your specific situation (any of these options may work fine for you).
Have a look at this response from another question: https://stackoverflow.com/a/4629821/193254
You'll have to subclass the scrollview too, and implement that hitTest: method.

UITextField subview of UIImageView is not responding to touch events

I have a UITextField that responds to touch events when it is added as a subview of self.view. When I add it as a subview of a UIImageView it does not respond to touch events any more. I make it a firstResponder and the field is active and takes keyboard input still. Any ideas what is wrong?
The docs for UIImageView state:
New image view objects are configured to disregard user events by default. If you want to handle events in a custom subclass of UIImageView, you must explicitly change the value of the userInteractionEnabled property to YES after initializing the object.
Try setting imgView.userInteractionEnabled = YES
If this doesn't work, I would try adding the UIImageView and the UITextField in a UIView instead. Anyway, this approach seems cleaner.

Managing events on a custom UIControl

I am subclassing UIControl to compose a custom control that contains different standard controls.
For this discussion let's assume that my custom UIControl contains a UIButton only.
What I would like to achieve is that clicking anywhere in the custom UIControl generates a click event for that custom UIControl. The standard behavior is that the UIButton will process and consume (i.e. not forward) the click event.
As subclassing UIButton is discouraged, I can't really find a straightforward way of achieving this.
Any suggestions?
I came up with a simple solution that doesn't need subclassing of the UIButton.
In the action method defined for the UIButton's TouchUpInside control event, I have added the following line of code:
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
This results in the TouchUpInside control event being called, when clicking anywhere in the custom UIControl.
UIViews have a method called -hitTest:withEvent: that the event system uses to crawl the view hierarchy and dispatch events to subviews. If you want a parent view to gobble up all events that might otherwise be dispatched to its subviews, just override the parent's -hitTest:withEvent: with something like the following:
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
if(CGRectContainsPoint([self bounds], point)){
return self;
}
return [super hitTest:point withEvent:event];
}
UIButton is designed to process touch events. You can either set userInteractionEnabled to NO to have the button not accept any touches, or you can use addTarget:action:forControlEvents: on the button to have it call a method on your class when the button is touched.
BTW, where is subclassing UIButton discouraged?
Often I find useful user interaction related tasks in UIResponder class, which is the super class of UIControl - UIButton.
Read about – touchesBegan:withEvent:, – touchesMoved:withEvent:, – touchesEnded:withEvent:, – touchesCancelled:withEvent: in http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIResponder_Class/Reference/Reference.html You may find ways to customize user interaction for your UIButton. By the way, I don't think there will be any problem subclassing UIButton, no matter what you've heard, as long as your implementation is correctly added to the super class implementation, or does responsibly override it altogether.

Resources