UITextField: force resignFirstResponder when tapped outside of it - ios

I have a static UITableView that contains a number of UITextFields. When the user taps outside of any of the text fields I'd like to I'd like to dismiss the keyboard.
At the top level of my UIViewController is a UITableView and a UITabBarItem. I believe I'll also have to handle taps on the status bar.
I am unsure as how I should register for touches on them (so that I can force any of the text fields to call resignFirstResponder.
I thought I might have to handle UIResponder's
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
for the table view and tab bar item but neither of them are UIControls so I can't use
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
UIWindow is also a UIResponder but again, I can't seem to get touch events for it.
Any help would be much appreciated,
CS

If you had one text field I'd add touches began into the UIViewController it belongs to and do it like this...
- (void)touchesBegan ... cant remember full name
{
if ([touches count] > 1) {
return;
}
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView self.view];
if (!CGRectContainsPoint(self.textField.frame, touchPoint)) {
//touch originated outside textField.
[textField resignFirstResponder];
}
}
If you have more than one text field then just do the CGRectContainsPoint check for each of them inside the if.

When you have a static UITableView it "eats" the touch events. So what I did was by subclassing UITableView and then added a delegate which reports touch events.

Related

Want Button to swallow all the touches

I am trying to build my own drop down list. I have created a custom view by creating subclass of UIButton. First time when button is clicked List will be displayed. Now I want that next time when it clicks anywhere outside that Button and list, this class should be notified. Or in other words I want this Button to swallow all the touches.
How could I achieve this?
Use touchesBegan method.
ex:
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if([touch View] != yourbutton)
{
//do what u want to do
}
}

How do I allow the user to add text the same way that snapchat does?

Where the user clicks on the screen and the keyboard and text field show up. Then when they are done it disappears and the text is saved. But I don't want the box to be around it I just want the words that the user typed to appear. I am somewhat a noob to Xcode, and I have been trying to figure this out for many days now. If you guys have any input that would be great!
Thanks in Advance
First you have to create a UiTextField or a UILabel.
In Snapchat the keyboard hides whenever you tap on the screen. Objective-C provides a methode to detect if the screen was touched.
Use - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
With resignFirstResponder you hide the keyboard from your label.
you have to implement -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event method, when method fired than
UITouch *touch = [touches anyObject];
float position = [touch locationInView:view];
and add UITextField at that point, and on return of UITextField create UILabel with the calculation of text size and add it to view at same position where UITextField was added and remove UITextField from superview.
Or for touch you also can use UITapGestureRecognizer

Enable / Disable Touch Events on UIImageView Object

I've read answers to many questions that dealt with enabling / disabling touch events, but nothing has worked for me, so I'm asking one of my own.
I have a UIImageView object (spot):
// in my view controller header file:
#property (nonatomic, strong) IBOutlet UIImageView *spot;
Then I have code relating to this object:
// in my view controller .m file:
#synthesize spot
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// handle when that spot is touched ...
}
And that works fine. For example, I can change the image displayed at the spot when the spot is clicked.
First I wanted to see how to disable touch events on the spot so I tried:
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
And that works fine. At certain points, depending on what I want to do, I was able to disable all touch events.
Then I added a button to this view controller and I want the button to be clickable ALWAYS, to have a touch event ALWAYS enabled for the button.
So now my approach to disabling touch events won't work because it's too heavy-handed. It wipes out all touch events anywhere in that view.
I want to disable ONLY the touch event on that spot. I tried:
spot.userInteractionEnabled = NO;
But that didn't work. The spot was still clickable. I also tried:
[spot1 setUserInteractionEnabled:NO];
Also didn't work. I'm quite confused as to why those don't work. My question is:
How can I disable touch events on just this one spot, this one UIImageView object?
EDIT: To address the question asked below, in the Interface Builder, in my .xib I have linked the UIImageView object to the property set in my header file. That's its Referencing Outlet.
Why do you want to disable touch for your spot? You can simply skip handling if the touch was from the spot.
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
if (CGRectContainsPoint(spot.frame, touchLocation))
return;
if (CGRectContainsPoint(button.frame, touchLocation)){
//do something
}
}

iOS - how to forward touches to the underlying uiview

I have 3 UIViews of the same size stacked on top of each other. The topmost is transparent and only used for detecting touches. The type of touch detected will determine which of the other two underlying views I want to receive the touch events. Once the topmost view is finished with the touch, I need to forward the touch events to the correct underlying view. How can I do that?
EDIT - I am adding my touch detection code. This is within MainViewController, whose view contains all 3 subviews.
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches)
{
if (touch.view == self.touchOverlay) {
CGPoint touchLocation = [touch locationInView:touch.view];
//do a bunch of math to determine which view should get the touches.
if (viewAshouldGetTouches) //forward to viewA
if (viewBshouldGetTouches) //forward to viewB
}
}
}
Make your two subviews setUserInteractionEnabled:NO and handle all touches in the parent. Then, depending on touch type, send the correct view a programatic touch event. Then you don't need your clear view on the top. Basically you will be coordinating touch events from the bottom up instead of going top->bottom->middle.
You'll have to do this by creating a UIView subclass for your top view and overriding the following method :
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
// UIView will be "transparent" for touch events if we return NO
return (point.y < MIDDLE_Y1 || point.y > MIDDLE_Y2);
}

Touches method in UIViewController and UIView

I'm working on iPad app. My UIViewController contains only a custom UIView with a size of 500wx500h.
I implemented the touches methods both in the UIViewController and the custom UIView in order to call the UIViewController touches methods when we touch all around the custom UIView and call the custom UIView touches methods when we touch inside it.
UIViewController touchesMoved :
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
NSLog(#"TEST"); // Added during edition
if (!CGRectContainsPoint(self.drawingView.frame, point)) {
NSLog(#"UIVIEWCONTROLLER");
}
}
Custom UIView touches Moved :
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"CUSTOM VIEW");
}
When I'm touching the custom UIView moving my finger, CUSTOM VIEW is logged until I removed the finger on the screen. On the other hand, when I'm touching outside of the custom UIView, the UIVIEWCONTROLLER is called only one time in the touchesMoved method.
Am I missing something wrong ?
EDIT : I added a log in my UIViewController touchesMoved method. When I touch inside the custom view, it logs the TEST during all the touching phase. But when I touch outside, I get the same behaviour.
add exclusiveTouch property to your view to disable multi touches
your view.exclusiveTouch=YES;
There is some likeliness that your self.view is intercepting touches and handling them, so they will not make it through to the view controller. You could try doing either of 2 things (or both) and see if it works:
self.view.exclusiveTouch = NO;
self.view.userInteractionEnabled = NO;
I would also try to call [super touchesMoved: touches withEvent: event];
Hope it helps.

Resources