How to drag down to dismiss a modal with ObjectC - ios

I want to dismiss a modal view with dragging down photo like twitter app's photo views.
I found same issue, but it written in Swift.
I need Object-C version.

You can use UISwipeGestureRecognizer (Down) to achieve the behaviour.
Add gesture to the model view using below code:
UISwipeGestureRecognizer *downGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(downGestureHandler:)];
[gestureRecognizer setDirection:(UISwipeGestureRecognizerDirectionDown)];
[self.view addGestureRecognizer: downGestureRecognizer];
The method to dismiss the model view:
-(void) downGestureHandler:(UISwipeGestureRecognizer *)recognizer {
//Code to dismiss model view with animation
}

Related

Implementing swipe gesture in xCode obj. C

I am fairly new at programming in objective c and am trying to implement swipe gestures to swipe between view controllers on an app I am creating in xcode. I'm trying to make it so when I swipe left, it switches to another view controller that I have named "SecondViewController". I have created the outlet and action for my gesture in my .h file, and in my .m file I have added the following code:
- (IBAction)swipeLeft:(id)sender {
ViewController *SecondViewController = [[ViewController alloc] init];
[self presentViewController:SecondViewController animated:YES
completion:nil];
Whenever I run the app, nothing happens when I swipe. Is there something that I have not yet done that I need to do to make this work?
There are basically four Swipe Gesture is available:
UISwipeGestureRecognizerDirectionRight
UISwipeGestureRecognizerDirectionLeft
UISwipeGestureRecognizerDirectionUp
UISwipeGestureRecognizerDirectionDown
You can use any of it as per your requirement. To adding any of above gesture, you can alloc Gesture and then add it to your particular view. So as soon as you swipe detected, it will call relevant method.
For Example for Right and Left gesture:
UISwipeGestureRecognizer *gestureRecognizerRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeHandlerRight:)];
[gestureRecognizerRight setDirection:(UISwipeGestureRecognizerDirectionRight)];
[self.view addGestureRecognizer:gestureRecognizerRight];
UISwipeGestureRecognizer *gestureRecognizerLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeHandlerLeft:)];
[gestureRecognizerLeft setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[self.view addGestureRecognizer:gestureRecognizerLeft];
-(void)swipeHandlerRight:(id)sender
{
}
-(void)swipeHandlerLeft:(id)sender
{
}

Setting up Tap Gesture on UIView on an NSObject, even if delegate is set on View Controller doesn't work

in VideoPlayer.h:
#interface VideoPlayer : NSObject <UIGestureRecognizerDelegate>
#property (nonatomic, retain) UIView *playerView;
in VideoPlayer.m custom init method:
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(userDidTapScreen:)];
tgr.delegate = self; // tried with and without
tgr.cancelsTouchesInView = NO; // tried with and without
[self.playerView addGestureRecognizer:tgr];
....
- (void)userDidTapScreen:(UITapGestureRecognizer *)tap {
NSLog(#"user tapped");
}
Because this object is part of an SDK, we don't have a view controller. But even if I set the delegate in the View Controller of a project using the SDK, I still have no luck. If I had another view as a subView to self.playerView, the tap gesture works on that view, even if I'm still adding gesture to self.playerView. I have removed all subviews to make sure nothing is blocking and when I do that, still no luck. I know that typically view controllers handle this and if I put all the tap gesture code in the view controllers, it works, but if I only set the view controller as the delegate and that's the only gesture code on the view controller, it doesn't work.
When added to a project's view controller:
VideoPlayer *player = [[VideoPlayer alloc] initWithFrame:CGRectMake(10, 100, 320, 200)];
[self.view addSubview:player.playerView];
UITapGestureRecognizer * recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
recognizer.delegate = self;
[player.playerView addGestureRecognizer:recognizer];
This isn't ideal for our SDK. I think we could tell anyone using it to set delegate in their view controller, but that doesn't even work when that's the only line in the view controller.
Any help would be greatly appreciated. I've done a lot of tap gestures both in code and through IB and never this problem.

Close keyboard when view is pressed - Obj C

I have a function that populates a few fields into the self.view.window view. Now if I run:
/* HIDE KEYBOARD WHEN CLICKED AWAY */
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
gestureRecognizer.cancelsTouchesInView = NO; //so that action such as clear text field button can be pressed
[self.view addGestureRecognizer:gestureRecognizer];
within my viewDidLoad it works great. But lets say I click a cell -> calls function -> displays using: [self.view.window addSubview:self.DatePicker];
MygestureRecognizer will not longer work. I assume that is because of sending it to the window. My question is, how can I get that to work?
UPDATE:
The reason I am adding to the window is because I need to give it a fixed like property and that did the trick for me. For instance in CSS you are able to do position:fixed;
I figured out a cheap workaround but if you have a better idea please let me know.
Because I have cells that are populated in a uitableview I am listening for a specific cell that is clicked. So what I did is just create a gesture container and add that to the view.window on that specific cell that I listened for and that did the charm.
[self.view.window addGestureRecognizer:self.gestureRecognizer];
ADD TAP GESTURE ON VIEW
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapBehind:)];
recognizer.delegate = self;
[recognizer setNumberOfTapsRequired:1];
recognizer.cancelsTouchesInView = NO; //So the user can still interact with controls in the modal view
[self.view.window addGestureRecognizer:recognizer];
handleTapBehind Method :
- (void)handleTapBehind:(UITapGestureRecognizer *)sender
{
[self.view.window removeGestureRecognizer:sender];
// Dismiss Your Keyboard HERE
}

SWRevealViewController add gesture to entire front view

Right now I am using SWRevealViewController class in my project.
The basic functionality allows me to swap front view by pressing navigation bar button. But I want to add gesture to entire view.
I can add this code and it works for my button.
[self.startTestButton addGestureRecognizer:self.revealViewController.panGestureRecognizer];
But it just works for the one UI element. So I can't add, for example, other UI element to this gesture.
This code below shows how panGestureRecognizer method has been written:
- (UIPanGestureRecognizer*)panGestureRecognizer
{
if ( _panGestureRecognizer == nil )
{
SWDirectionPanGestureRecognizer *customRecognizer =
[[SWDirectionPanGestureRecognizer alloc] initWithTarget:self action:#selector(_handleRevealGesture:)];
customRecognizer.direction = SWDirectionPanGestureRecognizerHorizontal;
customRecognizer.delegate = self;
_panGestureRecognizer = customRecognizer ;
}
return _panGestureRecognizer;
}
To add the gesture recognizer to the whole view just add it to the whole view instead of just a single button. I'm using SWRevealViewController and my main view is a UITableView so to get the gesture recognizer to work on the whole view I have this in the viewDidLoad method of my UIViewController:
[self.tableView addGestureRecognizer: self.revealViewController.panGestureRecognizer];
So, just add the recognizer to the view you like. For most UIViewContollers this will be self.view.
Obviously if any controls or subviews of the view have their own gesture recognisers, these will take precedence of the one on the top level view, such that the panning will only work in the areas not occupied by those subviews.
//UPD:
Seems my previous solution is a overkill, you just could call getter to get the default behaviour. I.e.
[revealViewController panGestureRecognizer];
// old solution
You could also add SWRevealViewController's panGestureRecognizer to it's own view, for example in a subclass of SWRevealViewController you may have:
- (void)viewDidLoad
{
[super viewDidLoad];
// adds gesture recognizer to the whole thing
[self.view addGestureRecognizer:self.panGestureRecognizer];
}
If you're using a navigation controller and try to add the gesture recognizer to self.view, the gesture won't respond when swiping on the navigation bar. What I did was go into SWReaveal Classes and add a second gesture recognizer. So now I add one recognizer to self.view and one to the navigation bar. Works perfectly. I can share code if you need it but it shouldn't be too hard
To add Gesture on entire front view using SWRevealViewController using storyboard, we have to add
SWRevealViewController *revealController = [self revealViewController];
[revealController panGestureRecognizer];
[revealController tapGestureRecognizer];
in the the FirstViewController of the app. Add Action and Target to the Navigation bar button like
_sidebarButton.target = self.revealViewController;
_sidebarButton.action = #selector(revealToggle:);
// Set the gesture
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
In the SWRevealViewController.h add following method like
- (UITapGestureRecognizer*)tapGestureRecognizer;
- (BOOL)revealControllerTapGestureShouldBegin:(SWRevealViewController *)revealController;
In the SWRevealViewController.m add
- (UITapGestureRecognizer*)tapGestureRecognizer
{
if ( _tapGestureRecognizer == nil )
{
UITapGestureRecognizer *tapRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(_handleTapGesture:)];
tapRecognizer.delegate = self;
[_contentView.frontView addGestureRecognizer:tapRecognizer];
_tapGestureRecognizer = tapRecognizer ;
}
return _tapGestureRecognizer;
}
- (void)_handleTapGesture:(UITapGestureRecognizer *)recognizer
{
NSTimeInterval duration = _toggleAnimationDuration;
[self _setFrontViewPosition:FrontViewPositionLeft withDuration:duration];
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if ( _animationQueue.count == 0 )
{
if ( gestureRecognizer == _panGestureRecognizer )
// return [self _panGestureShouldBegin];
return ( gestureRecognizer == _panGestureRecognizer && _animationQueue.count == 0) ;
if ( gestureRecognizer == _tapGestureRecognizer )
return [self _tapGestureShouldBegin];
}
return NO;
}
In case of xib you can direct use
https://github.com/John-Lluch/SWRevealViewController
On Swift
self.revealViewController().frontViewController.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
If you are using a navigation controller for your front view you can add the pan gesture to the nav controller's view like this
[self.navigationController.view addGestureRecognizer: self.revealViewController.panGestureRecognizer];
That way you can also swipe on the navigation bar without altering any classes of the SWReveal controller.

UIBarButtonItem's action is not called when in a view with a UIGestureRecognizer

I have a simple UIViewController derived controller which has UITextFields.
Also using IB, I placed a UIToolbar and two UIBarButtonItems. I Ctrl-Drag to add actions to the buttons.
- (IBAction)cancel:(id)sender { ... }
- (IBAction)save:(id)sender { ... }
If I run the code, the actions get called.
The problem: I wanted to implement the tap on background to resignFirstResponder paradigm, so I added a UITapGestureRecognizer on the root view:
- (void)viewDidLoad {
...
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
}
When I have the gesture recognizer, the actions of the UIBarButtonItems are not called
How can I have it both ways?
Thanks for any explanations that could help me implement this.
I resolved the problem by adding another view and setting the gesture recognizer on that view instead of the root view.
But I still would like to know the explanation to why the gesture recognizer would "eat" the action of the UIBarButtonItem.

Resources