I am using the SWRevealViewController project by John Lluch for my application and I have run into one minor issue that I can't seem to get straight.
I am using the SWRevealViewController to access my apps options menu from anywhere in my app just by swiping to the right and the main view slides to reveal the menu behind it.
This is handled by a swipe gesture recognizer that is added to the main view. To improve UX, I create a button to cover the main view when it gets swiped out of the way so all the user has to do to close the menu is tap the small part of the view that is showing or grab the view and pull it back.
It works great except on one of my views in which the majority of the view is a UIScrollView. To get it to work I have to add the gesture recognizer to the UIScrollView as well as the super view. But for some reason, once the view is swiped out of the way, the swipe gesture recognizer stops responding. But this only happen on the view where the majority of the screen is a scroll view thus, what the user grabs to pull the screen back is the scroll view.
Hopefully that was understandable. Any light that you guys can shine on this will be very helpful.
-(void)viewDidAppear:(BOOL)animated {
// so the user can tap the button to show the menu
[menuButton addTarget:self.revealViewController action:#selector(revealToggle:) forControlEvents:UIControlEventTouchUpInside];
// so the user can swipe to show the menu
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
// so the user can swipe the scrollview to show the menu
[mainScrollView addGestureRecognizer:self.revealViewController.panGestureRecognizer];
self.revealViewController.delegate = self;
}
- (void)revealController:(SWRevealViewController *)revealController willMoveToPosition:(FrontViewPosition)position {
if (position == FrontViewPositionRight) {
//create the button so the use can tap to close the menu
returnButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[returnButton addTarget:self.revealViewController action:#selector(revealToggle:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:returnButton];
} else {
[returnButton removeFromSuperview];
returnButton = nil;
}
}
So I just discovered that this issue has already been addressed within the SWRevealViewController Project. This post pointed me in the right direction. They have added a tap gesture recognizer that has the behaviour I was creating with the dynamically created button.
Adding
[self.view addGestureRecognizer:self.revealViewController.tapGestureRecognizer];
removes the need for the button, thus allowing the view to respond to both recognizers.
Related
So, I'd like to receive touches from the status bar anywhere, any view, from the app. Well actually only specific views, like home screens and root view controllers say from a view of a tab view controller.
So my goal is to: hold down the status bar to dismiss the current view, like a back button.
The reason why I'm using this approach as a back button is because the app I am making is a utility, like fully functional apps within one app. Therefore I do not want to use up space on the navbar item to display a back button.
Other fissures would be nice, like swipe left/right or double tap, but mostly holding down. I've seen alternatives like using a UIScrollView and use the - scrollsToTop method. Hmm not what I am looking for.
Hope this can help you.
When you tap the top area, which has 44 height, the event would be triggered.
- (void)viewDidLoad{
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(navigationBack:)];
[self.view addGestureRecognizer:tapGesture];
}
- (void)navigationBack:(UITapGestureRecognizer *)tapGesture {
CGPoint p = [tapGesture locationInView:self.view];
if (CGRectContainsPoint(CGRectMake(0, 0, self.view.frame.size.width, 44), p)) {
NSLog(#"this where you put you navigation back event");
}
}
So I have a homepage view that people see when they first boot up the app, it has several different options. Yesterday I added a tutorial overlay, so the first time they open the app I have a view that is 0.5 alpha black and is fullscreen over the other view, this view has white text and arrows pointing to functions on the page. I attached a tap gesture recognizer to this view and its action is to call the next tutorial screen ( 3 in total). Afterwords they all are hidden and the app acts as normal. This all works, except even though my view is full screen, with User Interaction Enabled checked and a gesture tap recognizer, the gestures / touches on the sub view still work. So if I just tap some white space on the app the tutorial and tap gesture work as expected, cycle me through the pages etc and works. However if I accidentally press a sub view button or do a gesture from the subview it will do the action (take you to a new page or w/e)
So basically as far as I can tell my view despite being on top of the other and having a tap gesture recognizer attached to the view the sub views are still getting pressed, any ideas?
Check the tap event view before doing any operation..
- (IBAction)yourTapEvent:(UITapGestureRecognizer *)gestureRecognizer
{
UIView *piece = [gestureRecognizer view];
if(piece == (view on which you have added gesture))
{
//Do your necessary operation
}
}
try this it would help you to disable gesture on its subviews
- (void)tapAction:(UITapGestureRecognizer *) gestureRecognizer{
UIView *v = [gestureRecognizer view];// Guesture added view
NSArray *temp = [self.view subviews];
for (int i = 0; i<temp.count; i++) {
if([temp objectAtIndex:i]== v){
// Do your swipe tap action here
}
}
}
Strange issue i'm running into that is honestly really frustrating. I've created a side menu bar for my app that I insert using this function:
- (void)insertMenunOnView:(UIView*)view atPosition:(CGPoint)position
{
_menuButton.frame = CGRectMake(position.x, position.y, _menuButton.frame.size.width, _menuButton.frame.size.height);
[view addSubview:_menuButton];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissMenu)];
[view addGestureRecognizer:singleTap];
view.userInteractionEnabled = true;
for (UIButton *button in _buttonList)
{
[_backgroundMenuView addSubview:button];
}
_backgroundMenuView.frame = CGRectMake(view.frame.size.width, 0, 150, view.frame.size.height);
_backgroundMenuView.backgroundColor = [UIColor colorWithRed:0.09 green:0.15 blue:0.18 alpha:0.7f];
[view addSubview:_backgroundMenuView];
}
it is implemented here in my UITableViewController viewDidAppear method:
override func viewDidAppear(animated: Bool) {
sideBar.insertMenuOnView(self.view, atPosition: CGPointMake(100, 200))
}
If I do this, it renders my TableView useless. I can select the cells if I tap rapidly back and forth between multiple cells. After about ten seconds of doing this, the cell being tapped will initiate the appropriate segue.
No I tried this hoping I'd be able to get over this problem by changing the function to
- (void)insertMenunOnView:(UIWindow*)view atPosition:(CGPoint)position
{ //// do stuff
}
Guess what!? Now every single tableView in my entire app is behaving the same as the first! Takes about thirty to forty taps until the cell finally calls didSelectRowAtIndexPath
What on earth is going on?
Disable tap gesture on view when side menu is closed and enable it when side menu is open.
At present your tap gesture is overriding tap gesture of table view.
The issue is-
When you call sideBar.insertMenuOnView(self.view, atPosition: CGPointMake(100, 200))
this method is called
- (void)insertMenunOnView:(UIView*)view atPosition:(CGPoint)position
inside your dismissMenu event handler you should remove gesture recognizer
inside above method you are adding a gesture recognizer on the current view, when you are done with this view, then you are dismissing it, but the tap gesture still exists and is added over the current view. Now when you try to select any row of the table the touch is not passed to the table as it is intercepted by the layer above it (which of-course is tap gesture recognizer added over the current view.)
To resolve this issue you should remove the tap gesture recognizer from the current view inside your dismissMenu method. Doing so will pass your touches to the corresponding row of the tableView.
So I have a self created top bar controller that is being implemented in my other controllers views. I have a textfield on this top bar. I was wondering what the best approach to having the keyboard dismiss if the user clicks anywere outside the keyboard. I do have a tap gesture recognizer that performs the method dismisskeyboard. However, this only works if the user clicks on the top bar outside the keyboard. Is there a way to set it up so if the user clicks anywere on the screen, then this will dismiss the keyboard?
The approach I would describe is a hack but still works.
create a transparent UIButton with the frame of the view, like below:
UIButton* overlay = [UIButton buttonWithType:UIButtonTypeCustom];
overlay.frame = self.view.bounds;
overlay.backgroundColor = [UIColor clearColor];
[overlay addTarget:self action:#selector(hideOverlay:) forControlEvents:UIControlEventTouchDown];
[self.view.subviews[0] insertSubview:overlay belowSubview:self.textField];
Create a method hideOverlay to dismiss the keyboard and hide the transparent:
-(void)hideOverlay:(id)sender {
UIView* overlay = sender;
[overlay removeFromSuperview];
[self.textField resignFirstResponder];
}
You should ideally call the first block of code in textFieldDidBeginEditing: protocol method of UITextFieldDelegate and you should register your calling class accordingly.
You might try giving the text field a transparent inputAccessoryView, sized to fill the rest of the screen, that catches taps and dismisses the keyboard.
I'm using UIPageViewController in my application that shows all the images similar to a book. Its working fine.
What I want to do now:
I want to place a button on top left corner and on click it will show a pop over view controller which has a table view with 7 cells. Each cell will show different URL. On click of the table cell, it will push a view controller with web view.
What's the problem
The problem is that I placed the button on top left and created a segue to show popover. But on click of button it goes to previous page and on next clicks it will finally reach page 1. then in page 1, it will show the pop over. I didn't understand why is it happening like this.
And even after showing popover, its not showing next view with website.
How to do it?
The trick is that UIPageViewController's gesture recognizers take over that area. In particular, the tap handler; so your button only gets hit when the tap recognizer does not take it as meaning to go to the previous page.
Quickest solution is to set yourself to the delegate of its recognizers
for (UIGestureRecognizer *recognizer in pageViewController.gestureRecognizers)
recognizer.delegate = self;
and then implement the delegate telling them to let controls get touches
- (BOOL)gestureRecognizer:(UIGestureRecognizer *) __unused gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isKindOfClass:[UIControl class]])
return NO;
return YES;
}
which ought to sort you nicely.