I have a small UITableView that is hidden when the view is loaded. When i click on "SHOW" UIButton, the UITableView is made visible by myTableView.hidden=NO;
I want to hide UITableView when a user touches outside its frame. Thanks for any help!
Best Approach
Simple.Before show up the UITable View add one more grayed out/Transparent view then add tap gesture recogniser on it to hide it . That's it.
Show Overlay View first - alpha will be 0.5f and background color should be clear color.
show the table view.
NOTE: over lay view should have tap recogniser which will hide the overlay and table view
in View did load
UITapGestureRecognizer *tapRecog = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(overlayDidTap:)];
[myOverLayView addGestureRecognizer:tapRecog];
- (void)overlayDidTap:(UITapGestureRecognizer *)gesture
{
//hide both overlay and table view here
}
Bad Approach
We should not add tap recogniser on main view itself. Because it may have lots of
controls inside of it. so when user tap on it. it will perform its operation. So to avoid
it we can simulate the same behaviour by above approach
You can get touch position by this:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapGestureCaptured:)];
[self.view addGestureRecognizer:singleTap];
- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
CGPoint touchPoint=[gesture locationInView:self.View];
}
Then just check if the point is in tableview frame. If not then hide the tableview. Hope this help. :)
Subclass UITableView, override pointInside:withEvent:. It is templated for this reason.
Something like:
-(BOOL)pointInside:(CGPoint) point withEvent:(UIEvent*) event
{
BOOL pointIsInsideTableView = [super pointInside:point withEvent:event];
BOOL pointIsOutsideTableView = // Some test
return pointIsInsideTableView || pointIsOutsideTableView;
}
So you can catch the touch in table view implementation, where it belongs logically in this case.
Related
i want to use one common tap gesture for show/hide slider view in view controller with multiple View controller classes.
please provide solution how to implement this for ios .
slider view will show / hide by tap of view of View Controller.
and slider view contain tableview so tableview cell also be select when user click on tableview cell in ios.
is there any way to create a Abstract class for that.
thanks in advance.
You can add tapgesture to main content view of VC like,
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handleTap:)];
self.view.userInteractionEnabled = YES;
[self.view addGestureRecognizer:recognizer];
And hanlde tap in method like,
-(void)handleTap : (UITapGestureRecognizer*)recognizer {
NSLog(#"tap detect");
}
Hope this will help :)
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.
I have a UITableView with a couple of UITableViewCells in it. Because I only have a couple of cells, there is an area of the table view that's not covered by the cells. And I want to do something when the empty area is tapped.
I tried adding a UITapGestureRecognizer on the table view. It detects the tapping on the empty area, but then the cells fail to respond to tapping. I tried adding the tap gesture recognizer on the super view of the table view, but the result is the same.
There must be a way to do this, but I can't quite figure it out yet. Is there any way to achieve what I want to do?
Try this:
initialize and add the UITapGestureRecognizer to your tableView:
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tap:)];
gr.delaysTouchesBegan = YES;
gr.delegate = self;
[_tableView addGestureRecognizer:gr];
implement the gesture recognizer delegate method:
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
CGPoint tapPoint = [gestureRecognizer locationInView:_tableView];
UIView * clickedView = [_tableView hitTest:tapPoint withEvent:nil];
NSString *viewClassName = NSStringFromClass(clickedView.class);
return ![viewClassName hasPrefix:#"UITableViewCell"];
}
this way every tap you do outsude cells (but inside the tableview) will be recognized with your UITapGestureRecognizer
The last line: return ![viewClassName hasPrefix:#"UITableViewCell"];
should be changed to return [viewClassName hasPrefix:#"UITableView"]; since the cell you are clicking doesn't have to be a UITableViewCell, but a UIView or some other custom view
I'm new to iOS so I'm getting problem with scroll view.
My scroll view having image views as subviews. Whenever I'm trying to touch image inside scroll view, scroll view touch is getting enable instead of subview.
How to resolve this problem?
Thanks
Add a Tap gesture recognizer to the scroll view for enabling touch inside scroll view:
UITapGestureRecognizer *singlTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(methodName:)];
singlTap.cancelsTouchesInView = NO;
[scrollViewName addGestureRecognizer:singlTap];
then write your code in specified method.
-(void)methodName:(UITapGestureRecognizer *)gesture
{
//your code here
}
Thats all
I am hoping someone will be able to help me with a problem that is doing my head in at the moment!
Given the following view hierarchy
I want to be able to detect swipe gestures on my custom UITableViewCell.
I have subclassed the UIScrollView and have a hitTest:withEvent: method that checks whether I am touching the tableview cell (or its content) or not, in which case I set the following scroll view properties:
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* result = [super hitTest:point withEvent:event];
if ([result.superview isKindOfClass:[UITableViewCell class]] || [result.superview tag] == SUBVIEW_TAG)
{
self.canCancelContentTouches = NO;
self.delaysContentTouches = YES;
} else {
self.canCancelContentTouches = YES;
self.delaysContentTouches = NO;
}
return result;
}
I have also implemented:
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
if (view.tag == SUBVIEW_TAG || [[view superview] isKindOfClass:[UITableViewCell class]])
return NO;
return YES;
}
And am returning NO in case the view being touched is the table view cell.
These methods are all getting called and performing their actions as expected, but I am still unable to stop the UIScrollView from "hogging" the swipe gesture.
The interesting thing is that if I include the UIView that contains the tableview and cell on both of the methods above (the one with SUBVIEW_TAG) it works perfectly so I am guessing it must be something to do with the fact that UITableView inherits from UIScrollView.
My main goal is to be able to swipe on the cell to reveal more options for the cell. A horizontal swipe anywhere else on that view would be captured by the scroll view and shift the content horizontally as per its normal behaviour.
Any ideas would be very much appreciated!
Thanks!
Rog
I had a similar problem with a swipe detect for a component inside a scrollview and I was able to resolve it with
[scrollView.panGestureRecognizer requireGestureRecognizerToFail:swipeGesture]
Where scrollView is the scroll view object that acts like container and swipeGesture is the component swipe gesture object inside scrollview.
So, you can define a swipe for the cell object like this (for right swipe in the example, custom it as you want)
UISwipeGestureRecognizer* rightSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(yourMethod)];
[rightSwipeRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[cell addGestureRecognizer:rightSwipeRecognizer];
and then do
[scrollView.panGestureRecognizer requireGestureRecognizerToFail:rightSwipeRecognizer]
The documentation of requireGestureRecognizerToFail says:
This method creates a relationship with another gesture recognizer
that delays the receiver’s transition out of
UIGestureRecognizerStatePossible. The state that the receiver
transitions to depends on what happens with otherGestureRecognizer:
If otherGestureRecognizer transitions to
UIGestureRecognizerStateFailed, the receiver transitions to its normal
next state.
if otherGestureRecognizer transitions to
UIGestureRecognizerStateRecognized or UIGestureRecognizerStateBegan,
the receiver transitions to UIGestureRecognizerStateFailed.
An example where this method might be called is when you want a
single-tap gesture require that a double-tap gesture fail.
Availability Available in iOS 3.2 and later.
Hope helps!
The solution is pretty simple. All you need to do is add UIScrollView inside you UITableViewCell. It will prevent "hogging" effect during swipe gesture.