In my case I have UIView and UITableView controller. What I want is to scroll the table view by swiping the UIView. I have added swipe up and swipe down gestures for the UIView. When I swipe on this view, scroll the table view along the direction of swipe. Is it posible?
Call this method from your viewDidLoad.
This method will disable the scrolling of the tableview to prevent manual scrolling.Assuming that you have 100 rows of height 30 and myview is the view on which have to perform the scrolling. Swipe gestures are added on myview,it is important to set the direction of the swipe
-(void)initialSetup
{
[self.tableView setScrollEnabled:NO];
int numberOfRows=100;
int rowHeight=30;
myview=[[UIView alloc]initWithFrame:CGRectMake(280, 0, 30, numberOfRows*rowHeight)];
[myview setBackgroundColor:[UIColor yellowColor]];
[self.view addSubview:myview];
UISwipeGestureRecognizer *swipeDown=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(motion:)];
[swipeDown setDirection:UISwipeGestureRecognizerDirectionDown];
[myview addGestureRecognizer:swipeDown];
UISwipeGestureRecognizer *swipeUp=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(motion:)];
[swipeUp setDirection:UISwipeGestureRecognizerDirectionUp];
[myview addGestureRecognizer:swipeUp];}
The below method will be called when a swipe gesture occurs either swipeUp or swipeDown.
When the method receives a swipeUp gesture it scrolls the last currently visible row in the tableview to the top
When the method receives a swipeDown it scrolls the first currently visible row to the bottom
-(void)motion:(UISwipeGestureRecognizer *)sender
{
if (sender.direction==UISwipeGestureRecognizerDirectionUp) {
[self.tableView scrollToRowAtIndexPath:[self.tableView.indexPathsForVisibleRows objectAtIndex:[self.tableView.indexPathsForVisibleRows count]-1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}else if(sender.direction==UISwipeGestureRecognizerDirectionDown)
{
[self.tableView scrollToRowAtIndexPath:[self.tableView.indexPathsForVisibleRows objectAtIndex:0 ] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
}
//let myView be the view from which you want to scroll your tableview(myTableview)
//now add the following lines in your viewdidload method
UISwipeGestureRecognizer * swipegesture = [[UISwipeGestureRecognizer alloc]init];
swipegesture =[myTableview.gestureRecognizers objectAtIndex:1];
[myView addGestureRecognizer:swipegesture];
Related
I have a UIImageView in UITableViewCell. I am trying to add Single Tap gesture to view it in full size and double tap gesture to like. Here is my code for that:
UITapGestureRecognizer *aSingleTapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(SingleTapGestureRecognizer:)] autorelease];
aSingleTapGesture.delegate = self;
aSingleTapGesture.numberOfTapsRequired = 1;
[cell.imgProductImage addGestureRecognizer:aSingleTapGesture];
UITapGestureRecognizer *aDoubleTapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTapGestureRecognizer:)] autorelease];
aDoubleTapGesture.delegate = self;
aDoubleTapGesture.numberOfTapsRequired = 2;
[cell.imgProductImage addGestureRecognizer:aDoubleTapGesture];
It only calls single tap gesture and double tap gesture was never being called. Than I used require to fail on single tap gesture.
[aSingleTapGesture requireGestureRecognizerToFail:aDoubleTapGesture];
Well, using this code I am able to call single and double tap gesture both, But the problem is the tableView:didSelectRowAtIndexPath: is also being called. I don't want to call didSelectRowAtIndexPath if my gestures are being called. As of my understanding it is being called because single tap gesture is waiting for double tap gesture mean while didSelectRowAtIndexPath is being called.
Any help please.
You can use UIButton instead of UIImageView in tableview cell. Use following code for getting single and double tap.
//add target for your UITableViewCell's button
[aBtnThumbObj addTarget:self action:#selector(btnThumbClickDouble:) forControlEvents:UIControlEventTouchDownRepeat];
[aBtnThumbObj addTarget:self action:#selector(btnThumbClickSingle:) forControlEvents:UIControlEventTouchUpInside];
-(void)btnThumbClickSingle:(UIButton*)sender
{
[self performSelector:#selector(singleTapOnButtonSelector:) withObject:sender afterDelay:0.2];
}
-(void)btnThumbClickDouble:(UIButton*)sender
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(singleTapOnButtonSelector:) object:sender];
//Your implementation for double tap
}
-(void)singleTapOnButtonSelector:(UIButton*)sender
{
//Your implementation for single tap
}
You can set selection style for your cell as
cell.selectionStyle = UITableViewCellSelectionStyleNone;
And then just don't implement your -tableViewDidSelectRowAtIndexPath method
These two lines of code work for me:
tapGesture.cancelsTouchesInView = YES;
tapGesture.delaysTouchesBegan = YES;
I have a view controller and I have created an another view in same view controller and added it as a sub view.When a button clicked the subview will appear and it takes half of the screen.How can I close the subview when user touched the superview(main view in background) ?
You can use a gesture recognizer and on a single tap action on the superview call removeFromSuperview on the subview.
In your viewDidLoad add something like this:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[singleTap setNumberOfTapsRequired:1];
[mainView addGestureRecognizer:singleTap];
And then add the function:
- (void) handleSingleTap: (id) sender
{
[secondView removeFromSuperView];
}
For more control of when you want the subview to be removed, you could override the mainViewController's responder method like so:
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[subview removeFromSuperView];
}
This way you can actually see where in the screen the user tapped, and respond accordingly.
I need to dismiss keyboard when touching outside of textfield. I have a main view controller view controller and another view controller embedded in the top right corner of the main view. It's embedded using container view (special object in IB).
The problem is that when I add gesture recogniser, the keyboard is dismissed but my another table view (in the center) is not receiving taps (it still scrolling but I can't select row). Table view is also an embedded view controller. This code is in my ViewDidLoad:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
And my dissmisKeyboard method:
-(void)dismissKeyboard
{
NSArray *childVc = [self childViewControllers];
for(id child in childVc)
{
if([child isKindOfClass:[MyTableViewController class]])
{
[child.tableVIew endEditing:YES];
}
}
}
How about?
-(void)dismissKeyboard
{
[self.textField resignFirstResponder];
}
In a tableview I have on every cell a UILongPressGestureRecognizer which I add like this:
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(TableCellLongPressed:)];
longPress.minimumPressDuration = 0.5f;
[cell addGestureRecognizer:longPress];
[longPress release];
Now I do have the following problem I want the user to be able to rearrange the cell in the tableview so I have a button that sets the tableView to EditMode like this:
[self.myTableView setEditing:!self.myTableView.editing animated:YES];
Now when the user tries to drag a cell and does not drag it far enough the longPress fires his action which is very annoying for the user cause another view gets pushed.
How can I pause or disable the UILongPressGestureRecognizer when the tableView is in EditMode?
You should implement the UIGestureRecognizerDelegate delegate for this method:
gestureRecognizer:shouldReceiveTouch:
In the method, check if you're editing the table and return NO if you are.
Tim
I want to call an action in two classes (a superview and a full screen subview) when the user single taps the screen. But, when I add a UITapGestureRecognizer to the subview, the one added to the superview is overridden. Is it possible to add a UITapGestureRecognizer to a subview without overriding the UITapGestureRecognizer added to the superview?
If so, how can I do this?
Thanks!
Edit:
From my main viewController "MyToolBerController", I'm adding the subview from another viewController as follows:
PhotoViewController *photoViewController = [[PhotoViewController alloc] initWithNibName:#"PhotoViewController" bundle:nil];
myPhotoView = photoViewController.view;
[self.view addSubview:myPhotoView];
I add the GestureRecognizer in the MyToolBerController like this:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTapFrom:)];
[singleTap setNumberOfTapsRequired:1];
singleTap.delegate = self;
[myPhotoView addGestureRecognizer:singleTap];
[singleTap release];
This all works fine, but I need to call a method in the PhotoViewController class when the view is tapped as well as in the MyToolBerController class.
When I add another UITapGestureRecognizer in the photoViewController, it overrides the UITapGestureRecognizer added in the superView.
Gesture recognizers can dispatch multiple actions when the gesture occurs. You can add the subview as another target of the gesture recognizer and only use a single UITapGestureRecognizer instance:
[tapRecognizer addTarget:theSubview action:#selector(whatever:)];
In your gesture recognizer selector method, pass the information along to the subview. There's no need to have multiple gesture recognizers for the same gesture. Something like:
- (IBAction)handleSingleDoubleTap:(UIGestureRecognizer *)sender
{
CGPoint tapPoint = [sender locationInView:sender.view.superview];
UIView *subview = [parentView viewWithTag:100];
[subview doSomethingWithPoint:tapPoint];
}
This of course means that your subview that needs to be notified should be given the tag 100 either in Interface Builder or in code when the view controller gets loaded.
Update based on Jonah's code:
So instead of retaining the view, retain the view controller:
PhotoViewController *photoViewController = [[PhotoViewController alloc] initWithNibName:#"PhotoViewController" bundle:nil];
self.myPhotoViewController = photoViewController;
Which means you need to declare it this way in the MyToolbarController header:
#property (nonatomic, retain) PhotoViewController *myPhotoViewController;
Then, when your gesture selector gets called, pass the message along to the view controller you retained. Something like:
- (IBAction)handleSingleTapFrom:(UIGestureRecognizer *)sender
{
CGPoint tapPoint = [sender locationInView:sender.view.superview];
[myPhotoViewController doSomethingWithPoint:tapPoint];
}
Of course the -doSomethingWithPoint: method is only for example. You can name and create any method you want that takes any parameter you want to pass in your PhotoViewController.
Let me know if you need further clarification.