I've subclassed th UIScrollView and overriden the touchesShouldCancelInContentView: method the following way:
-(BOOL)touchesShouldCancelInContentView:(UIView *)view
{
if ([view isKindOfClass:[UIButton class]] || [view isKindOfClass:[UISegmentedControl class]]) {
return YES;
}
if ([view isKindOfClass:[UIControl class]]) {
return NO;
}
return YES;
}
It works perfectly for UIButton, but it doesn't work for UISegmentedControl. Any help would be appreciated
Finally figured it out. Had to subclass both UISegmentedControl and UIScrollView.
1.) added a new property for UISegmentedControl:
#property (nonatomic, assign) BOOL touchProcessed;
2.) overloaded the following methods of the UISegmentedControl:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (touchProcessed) {
[super touchesBegan:touches withEvent:event];
}
else {
[self.nextResponder touchesBegan:touches withEvent:event];
}
self.touchProcessed = NO;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesMoved:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesEnded:touches withEvent:event];
}
3.) overloaded the following methods of th UIScrollview:
-(BOOL)touchesShouldCancelInContentView:(UIView *)view
{
if ([view isKindOfClass:[self class]])
{
return YES; //if there are two nested custom scrollviews
}
if ([view isKindOfClass:[UIButton class]] || [view isKindOfClass:[CustomSegmentedControl class]] || [[view superview] isKindOfClass:[CustomSegmentedControl class]]) {
return YES;
}
if ([view isKindOfClass:[UIControl class]]) {
return NO;
}
return YES;
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!self.dragging) {
for (UIView *sv in self.subviews) {
if ([sv isKindOfClass:[CustomSegmentedControl class]])
{ //if there is more than one add a tag or tomething
[(CustomSegmentedControl *)sv setTouchProcessed:YES];
[sv touchesBegan:touches withEvent:event];
return;
}
}
}
}
Works perfectly!
Related
I am new in Objective C and have a issue for using custom UITableViewCell.
I use touchesBegan in the my custom tableviewcell like following:
#import "UserListTableViewCell.h"
#implementation UserListTableViewCell
#synthesize userTableViewCellView, cellIndex;
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
... .. ...
}
-(void) touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
... ... ...
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
... ... ...
}
Then after that I can't use function didSelectRowAtIndexPath{}.
How can I use TableView selection even though use touchesBegan method.
Please advance me if you can fix this issue.
Thanks.
If didSelectRowAtIndexPath() isn't working properly after using touchesBegan you may want to check if you have [super touchesBegan] in your custom cell method. Like this:
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
... .. ...
}
.....
Hope it helps you!
This situation occurs because method
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
}
catches events, but doesn't send them further up the responder chain. As #Daniel mentioned above, if you add call to super like this:
[super touchesBegan:touches withEvent:event];
events will be sent further to - (void)didSelectRowAtIndexPath method.
I am needing the CGPoint of a tap on my UITableViewCell. To do this I want to use the touchesBegan:withEvent: method in my subclassed UITableViewCell.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
NSLog(#"%#", NSStringFromCGPoint(location));
}
How can I forward that from my UITableViewCell subclass to my current viewController so that I can make an action depending on where in the cell they tapped?
** I don't want to use a Gesture Recognizer on the cell since it will not allow the didSelectRowAtIndexPath: method to be called.
Either delegation or block call back would do it. Below is an example of using blocks
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
__weak __typeof(self) weakSelf = self;
cell.touchedAtPoint = ^(UITableViewCell *cell, CGPoint point) {
[weakSelf doSomethingWithPoint:point);
};
return cell;
}
In the cell
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
{
[super touchesBegan:touches withEvent:event];
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
void (^touchedAtPoint)(UITableViewCell *, CGPoint) = self.touchedAtPoint;
if (touchedAtPoint) {
touchedAtPoint(self, location);
}
}
- (void)prepareForReuse;
{
[super prepareForReuse];
self.touchedAtPoint = nil;
}
Declaration of ivar
#property (nonatomic, copy) void (^touchedAtPoint)(UITableViewCell *cell, CGPoint point);
Is there a way that I can get coordinates of clicked point inside collectionViewCell? I want to do method A if I clicked at rect with Y coordinate < 50, and method B if Y >50.
There is also option B, to subclass the UITableViewCell and get the location from the UIResponder class:
#interface CustomTableViewCell : UITableViewCell
#property (nonatomic) CGPoint clickedLocation;
#end
#implementation CustomTableViewCell
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
self.clickedLocation = [touch locationInView:touch.view];
}
#end
Then get the location from the TableViewCell it self:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//get the cell
CustomTableViewCell *cell = (CustomTableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
//get where the user clicked
if (cell.clickedLocation.Y<50) {
//Method A
}
else {
//Method B
}
}
Assuming you have a custom UICollectionViewCell, you can add a UITapGestureRecognizer to the cell and get the touch point in the touchesBegan handler. Like this:
//add gesture recognizer to cell
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] init];
[cell addGestureRecognizer:singleTap];
//handler
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self.view];
if (touchPoint.y <= 50) {
[self methodA];
}
else {
[self methodB];
}
}
How to add following condition in macro
if (![NSStringFromClass([[self superview] class]) isEqualToString:#"_UIModalItemAlertContentView"])
I want to add these two methods only if superClass of tableView category is not alertView
#if ([NSStringFromClass([[self superview] class]) isEqualToString:#"_UIModalItemAlertContentView"])
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([self.customDelegate respondsToSelector:#selector(tableView:touchBegan:withEvent:)]) {
[self.customDelegate tableView:self touchBegan:touches withEvent:event];
}
[super touchesBegan:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([self.customDelegate respondsToSelector:#selector(tableView:touchEnded:withEvent:)]) {
[self.customDelegate tableView:self touchEnded:touches withEvent:event];
}
}
#endif
#define YourMacroName(_view_) ([NSStringFromClass([[_view_ superview] class]) isEqualToString:#"_UIModalItemAlertContentView"])
if(YourMacroName){
//do something
}
Is this what you want?
I am new in iOS development. I want to hide the keyboard when tapping outside of a UITextView.
My TextView is in a cell from an UITableView. The problem is that I have a Toolbar at the top and my buttons doesn't react anymore. I implemented the method "shouldReceiveTouch" but my test is not correct i think. Any ideas? Thank you and sorry for my bad english..
In my ViewDidLoad:
tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
tap.delegate = self;
[self.view addGestureRecognizer:tap];
note: tap is an UITapGestureRecognizer property.
Implemented methods:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIBarButtonItem class]]) {
return NO;
}
return YES;
}
-(void)dismissKeyboard {
[tview resignFirstResponder];
}
UIBarButtonItem is not a subclass of UIView, hence the shouldReceiveTouch still return YES.
Try to exclude the whole UIToolbar or just add the tap gesture recognizer in the UITableViewCell when you initialize the cell in cellForRowAtIndexPath.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIToolbar class]]) {
return NO;
}
return YES;
}
You should add your gesture to table view.
tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
tap.delegate = self;
[tblView addGestureRecognizer:tap];
use didScroll method of UIScrollView delegate to resign keyboard.TableView is also subclass of UIScrollView so it should work.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[tview resignFirstResponder];
}
or use this one
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[tview resignFirstResponder];
}
If you still want to use gesture then add gesture to UIView or self.view or superView of tableView
instead of adding it to tableView
Try following code :----
Keep you code as it is and add this method
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[tview resignFirstResponder];
}
in viewDidLoad set self.view.userInteractionEnabled = yes;
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
if ([touch view] == tview) {
[tview resignFirstResponder];
}
}