I called the method,
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
[self.name resignFirstResponder];
[self.userName resignFirstResponder];
[self.mailId resignFirstResponder];
[self.password resignFirstResponder];
[self.reTypePassword resignFirstResponder];
}
for the purpose of resign first responder.it is working properly without using scrollview.but if i am using scrollview i cant able to use this method.why?
You can add a gesture recognizer if you need to use a scrollview.
Try this:
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(resignFirstResponder:)];
gestureRecognizer.delegate = self;
[scrollView addGestureRecognizer:gestureRecognizer];
-(void) resignFirstResponder:(UITapGestureRecognizer *) gesture
{
[self.name resignFirstResponder];
[self.userName resignFirstResponder];
[self.mailId resignFirstResponder];
[self.password resignFirstResponder];
[self.reTypePassword resignFirstResponder];
}
There are many more alternatives: See
UIScrollView prevents touchesBegan, touchesMoved, touchesEnded on view controller ,
UIScrollView touchesBegan
Related
I have applied gesture on whole view and I want to interact with table view within self.view.I have applied custom gesture.that is as follows:
#import "TouchEvent.h"
#import <UIKit/UIGestureRecognizerSubclass.h>
#implementation TouchEvent
#synthesize xInc=_inc;
#synthesize prev=_prev;
#synthesize diff=_diff;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self setState:UIGestureRecognizerStateBegan];
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self setState:UIGestureRecognizerStateCancelled];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
// A tap can have slight movement, but we're not interested
// in a tap. We want more movement. So if a tap is detected
// fail the recognizer.
if ([self state] == UIGestureRecognizerStatePossible) {
[self setState:UIGestureRecognizerStateBegan];
} else {
[self setState:UIGestureRecognizerStateChanged];
}
UIView *view = [self view];
CGPoint touchpoint = [touch locationInView:view];
CGPoint prevPoint=[touch previousLocationInView:view];
if (prevPoint.x<touchpoint.x)
[self setDiff:(touchpoint.x-prevPoint.x)];
else
[self setDiff:(prevPoint.x-touchpoint.x)];
NSLog(#"difference is: %f",self.diff);
NSLog(#"x is: %f",touchpoint.x);
[self setXInc:touchpoint.x];
[self setPrev:prevPoint.x];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self setState:UIGestureRecognizerStateEnded];
}
#end
and I m applying like this
- (void)viewDidLoad
{
NSArray *ary=[NSArray arrayWithObjects:#"Friends",#"Message",#"Chats",#"New Feeds",#"Photos",#"Notes", nil];
array=ary;
gestur=[[TouchEvent alloc] initWithTarget:self action:#selector(SLideTheView:)];
[self.view addGestureRecognizer:gestur];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)moveIt:(CGFloat)x_pos
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
[viewU setFrame:CGRectMake(x_pos, 0, 320, 460)];
[UIView commitAnimations];
}
-(void)SLideTheView:(TouchEvent*)gesture
{
CGPoint pt=[gesture locationInView:viewU];
if (pt.x>13&&pt.y>5&&pt.x<29&&pt.y<23)
{
[self slideView];
}
else
{
if (gesture.state==UIGestureRecognizerStateEnded)
{
if (viewU.frame.origin.x!=0) {
if (gesture.prev<gesture.xInc)
{
[self moveIt:270];
}
else
[self moveIt:0];
}
}
else
{
if (viewU.frame.origin.x!=0)
{
if (gesture.prev<gesture.xInc)
x=viewU.frame.origin.x+gesture.diff;
else
x=viewU.frame.origin.x-gesture.diff;
[viewU setFrame:CGRectMake(x, 0, 320, 460)];
}
}
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
label.text=[array objectAtIndex:[indexPath row]];
[self slideView];
}
the running image is as follows:
you can use requireGestureRecognizerToFail: to able to recognize two or more gesture recognizers on same view see example code here
edit
so you can refer this one
the method to be referenced is - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
refer this question for more
//add gesture to mapview-for single touch
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(SLideTheView:)];
[self.view addGestureRecognizer:tap];
tap.numberOfTapsRequired = 1;
//add another gesture to terminate first one
UITapGestureRecognizer *secondGest= [[UITapGestureRecognizer alloc] init];
[tableview addGestureRecognizer:secondGest];
[tap requireGestureRecognizerToFail:secondGest];
[secondGest release];
[tap release];
I've got a bit of a doubt with UITextViews. I use to put UITextFields, and remove the keyboard by tapping outside with the faithful old:
-(void)touchesEnded: (NSSet *)touches withEvent: (UIEvent *)event {
for (UIView* view in self.view.subviews) {
if ([view isKindOfClass:[UITextField class]])
[view resignFirstResponder];
}
}
I have this UITextView which is set on my view (and actually is self.myTV, to be precise), and I do the following
-(void)touchesEnded: (NSSet *)touches withEvent: (UIEvent *)event {
for (UIView* view in self.view.subviews) {
if ([view isKindOfClass:[UITextView class]])
[view resignFirstResponder];
}
}
Same as above, save for the different class...
Well it doesn't seem to work. Anyone has a suggestion?
An easy way to resign first responder for any subview that is currently the first responder is:
[self.view endEditing:NO];
Or if you want to force the first responder to resign without asking it first:
[self.view endEditing:YES];
The problem is that UITextView is not FirstResponder in your case as per the subview hierarchy of your app.
I would suggest you to categorize UIView to find the first responder as under:
This category on UIView, which calls on the UIWindow and traces for the first responder.
#implementation UIView (FindAndResignFirstResponder)
- (BOOL)findAndResignFirstResponder
{
if (self.isFirstResponder) {
[self resignFirstResponder];
return YES;
}
for (UIView *subView in self.subviews) {
if ([subView findAndResignFirstResponder])
return YES;
}
return NO;
}
#end
I have a view in which I have several large buttons which I set up like this:
SwipeButton* btn = [[[SwipeButton alloc] initWithFrame:CGRectMake(55, 0, 300, 50)] autorelease];
btn.tag = k;
[btn setBackgroundImage:[UIImage imageNamed:[NSString stringWithFormat:#"titleBackground.png"]]
forState:UIControlStateNormal];
[btn addTarget:self
action:#selector(indexAction:)
forControlEvents:UIControlEventTouchUpInside];
I would like to be able to either touch these buttons and then fire the indexAction method, or - if a swipe was recognised - to fire another method.
I thought I subclass UIButton to have swipes come through, but this isn't really a solution as now both swipes and clicks are recognised, so BOTH methods fire.
Is there a way around this? How can I prioritise the swiping and only allow the touchupinside if there was NO SWIPE?
Any help would be very much appreciated.
Here is how I subclassed the UIButton:
#import "SwipeButton.h"
#implementation SwipeButton
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
[self.superview touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
[self.superview touchesMoved:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
[self.superview touchesEnded:touches withEvent:event];
}
#end
I don't think that you need to subclass UIButton class. Why don't you try something like this:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [UIImage imageNamed:#"picture_0.png"];
[button setImage:image forState:UIControlStateNormal];
[button setFrame:CGRectMake((applicationFrame.size.width - image.size.width)/2, applicationFrame.size.height/2, image.size.width, image.size.height)];
[button addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
UISwipeGestureRecognizer *recognizer;
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
[recognizer setDirection:UISwipeGestureRecognizerDirectionRight];
[recognizer setDelegate:self];
[[self view] addGestureRecognizer:recognizer];
[recognizer release];
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
[recognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[recognizer setDelegate:self];
[[self view] addGestureRecognizer:recognizer];
[recognizer release];
Then you create the methods to handle taps and swipes on the button:
// Prevent recognizing touches on the slider
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIButton class]]) {
return YES;
}
return NO;
}
-(void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {
if ([recognizer direction] == UISwipeGestureRecognizerDirectionLeft) {
// Handle left swipe
NSLog(#"left swipe");
} else {
// Handle right swipe
NSLog(#"right swipe");
}
}
- (void)buttonTapped:(id)sender {
NSLog(#"button pressed");
}
First of the three previous method is declared in a protocol, so don't forget to say that your class is implementing that protocol:
#interface MyViewController : UIViewController <UIGestureRecognizerDelegate>
It works, I just tried it myself. Hope it helps! ;)
Take a look at the UIGestureRecognizer documentation and related examples (e.g.).
I am using this method
- (void)tableView:(UITableView *)tableView touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
if ([myPickerView isFirstResponder] && [touch view] != myPickerView) {
[myPickerView resignFirstResponder];
}
[super touchesBegan:touches withEvent:event];
}
but my tableView does not respond to touches (applied to the view works, but this is covered by the tableView!)
If this is not possible - is there any other possibility to capture "out of window" touches?
There is no such delegate method as tableView:touchesBegan:withEvent:. If you want to override -touchesBegan:withEvent: for your UITableView, you will need to subclass UITableView. Most problems like this are often better implemented with a UIGestureRecognizer. In the above, I'd probably use a UITapGestureRecognizer.
I found the simplest way to do this is to add a gesture recognizer to the UITableViewController's view.
I put this code in the UITableViewController's viewDidLoad:
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[self.view addGestureRecognizer:tap];
And implemented the event handler:
- (void)handleTap:(UITapGestureRecognizer *)recognizer
{
// your code goes here...
}
EDIT:
You could also add the gesture recognizer to the tableview, just change [self.view addGestureRecognizer:tap]; to [self.tableView addGestureRecognizer:tap];
Here is a UITableView subclass solution that worked for me. Make a subclass of UITableView and override hitTest:withEvent: as below:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
static UIEvent *e = nil;
if (e != nil && e == event) {
e = nil;
return [super hitTest:point withEvent:event];
}
e = event;
if (event.type == UIEventTypeTouches) {
NSSet *touches = [event touchesForView:self];
UITouch *touch = [touches anyObject];
if (touch.phase == UITouchPhaseBegan) {
NSLog(#"Touches began");
}
}
return [super hitTest:point withEvent:event];
}
How can I hide the keyboard on ScrollView touch event...
Scenario is like that...
->View ->ScrollView ->Textfield
I want to hide the keyboard on touch of scrollView. I tried to override the class for scrollview but still i can't do it.
Doing like this will help:
#interface MyClass <UIScrollViewDelegate> {
}
#implementation
- (void)viewDidLoad {
yourScrollView.delegate = self;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[myTextField resignFirstResponder];
}
If you really want to handle the touch event, then you need to subclass the UIScrollView and override the method:
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view {
}
More about UIScrollView touch
This is what worked for me
in your viewController's viewDidLoad-method
UITapGestureRecognizer *tapScroll = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapped)];
tapScroll.cancelsTouchesInView = NO;
[viewScroller addGestureRecognizer:tapScroll];
where viewScroller is your scroller. In the tapped-method we have
- (void) tapped {
[self.view endEditing:YES];
}
Don't know why but the above did not work for me...even though it should
Try this:
Add gesturerecognizer for scrollview,
UITapGestureRecognizer *tapScroll = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped)];
tapScroll.cancelsTouchesInView = NO;
[yourScrollview addGestureRecognizer:tapScroll];
[tapScroll release];
Resign your keyboard in (tapped:) method.
Please, take a look at this answer, This is the easiest one I found.
UitextField resignFirstResponder does not work in scroll view
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
[self.view endEditing:YES];
return YES;
}