I've an UITextView into an UITableViewCell, but I can't scroll the text. When I try to scroll the textView, the tableView catch the touches.
There is any way to fix this?
PS: Subclass of UITableViewController
I'm thinking you can detect the object being touched and if it is a UITextView, then temporarily disable scrolling with UITableView:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
//detect if touch is on UITextView
if ([touch.view isKindOfClass: UITextView.class]) {
yourTableView.scrollEnabled = NO;
}
}
Don't forget to re-enable scrolling of the UITableView afterwards in touchesEnded
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
yourTableView.scrollEnabled = YES;
}
Related
If there is a uiscrollview and and multiple sub view on the uiscrollview. how to know where the user touches i.e on specific view or scrollview(blank space)
Use this approach:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
NSLog(#"View touched: %#", touch.view);
}
This method is called every time your finger touches the screen, and the touch knows which view it touched.
Edit: It won't work on a UIScrollView because the scroll view gets the touch itself, check this:
touchesBegan method not called when scrolling in UIScrollView
How to enable touch began in UIScrollView?
You have 2 possibilities for detect the touch with - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; in a scrollView:
first, implement this method in your viewController, and add the scrollview on this viewController.
second, which I recommend: make a custom class which is inherited from UIScrollView like this:
.h:
#interface CustomScrollView : UIScrollView
#end
.m:
#import "CustomScrollView.h"
#implementation CustomScrollView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.nextResponder touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if(!self.dragging){
[self.nextResponder touchesMoved:touches withEvent:event];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[self.nextResponder touchesEnded:touches withEvent:event];
}
#end
in your vc make:
...
CustomScrollView* customScrollView = [[CustomScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
...
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
NSLog(#"View touched: %#", touch.view);
}
I put UIButton inside UITableViewCell in UITableView that is behind UIScrollView. I subclassed UIScrollView to forward touches to UITableView.
So method from UITableViewDelegate didSelectRow is calling properly. The problem is that UIButton inside table cell is not receiving TouchUpInside actions.
How can I solve this problem without deleting ScrollView over TableView?
EDIT:
I resolved this issue by detecting which view will receive touch. Here's the code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UIView *hitView = [self hitTest:[(UITouch*)[[touches allObjects] objectAtIndex:0] locationInView:self] withEvent:event];
if ([hitView isKindOfClass:[UIButton class]]) {
[(UIButton*)hitView sendActionsForControlEvents:UIControlEventTouchUpInside];
}
[super touchesBegan:touches withEvent:event];
}
If you want to enable actions for bouth objects - UIScrollView and UIButton you should to implement custom hit test mechanism for ScrollView.
In your UIScrollView subclass override - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event method to make views behind ScrollView available for getting events.
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
return __touchesEnabled;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
_touchesEnabled = NO;
UIWindow *window = [UIApplication sharedApplication].delegate.window;
for(UITouch *touch in touches) {
CGPoint point = [touch locationInView:self];
point = [window convertPoint:point fromView:self];
UIView *view = [window hitTest:point withEvent:event];
[view touchesBegan:touches withEvent:event];
}
_touchesEnabled = YES;
}
It works for me
Since you have added your scroll view over the UIButton, all the touch actions will not be passed to the button.
[yourScrollView setUserInteractionEnabled:NO];
This may solve your problem.
I have a UITextField on a UITableView and I am using a number keyboard however I want it to be dismissed when user clicks on anything but the UiTextField.
I have seen several solutions however there appears to not be one definitive answer. For example some talk about gestures and when I implement them they do not appear to work using the code below:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[[self view] endEditing:TRUE];
}
As you can see I am trying but there is not one way that seems to be working. Can someone guide me please?
Thanks
Usually, you will want to hit-test the touch against areas which should not dismiss the keyboard; but in general the requirement is to tell the currently-in-focus control to "resign" it's status as "firstResponder". It might look like this:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.userInput resignFirstResponder];
}
However, you may also want to consider a special gesture recognizer for this, so that you are not having to over-analyze the NSSet of touches in the long run (delegate to the GestureRecognizer the task of determining the difference between an actual "dismiss pleas!" tap and a "can I scroll this?" swipe.
You should use resignFirstResponder instead :
[textField resignFirstResponder];
Use the following code
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
// Note the '!':
if(![[touch view] class] isKindOfClass [UITableViewController class]]){
// It's not a bubble they touched, dismiss the keyboard:
[self.view endEditing:YES];
}
[super touchesBegan:touches withEvent:event];
}
or else
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
// Note the '!':
if(![[touch view] class] isKindOfClass [UITableViewController class]]){
// It's not a bubble they touched, dismiss the keyboard:
[textField resignFirstResponder];
}
[super touchesBegan:touches withEvent:event];
}
this helps in doing what you want
What's the Xcode code for this pseudocode?
if ([Any UIPickerView in my ViewController isTouched]) {
[AnyUIView setHidden:NO];
}
if ([Any UIPickerView in my ViewController is__NOT__Touched__Anymore__]) {
[AnyUIView setHidden:YES];
}
Tried it with the -(void)touchesBeganmethod, it detects the touches but I was not able to make it object-specific. Thanks
P.S. I want to display a hint on the display while the UIPickerViewis touched.
This is just from the top of my head...... but you should be able to get the idea...
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
if ([touch.view isKindOfClass: UIPickerView.class]) {
//your touch was in a uipickerview ... do whatever you have to do
}
}
..and do the same with touchesEnded:withEvent:
I am doing some custom drawing a UITableViewCell that I have subclassed. In there there is an OpenGL ES 2.0 control that needs user interaction to work... now if I start dragging horizontally the control responds but as soon as I go in the vertical direction then it starts to move the table view's viewport. How do I stop this interaction from going to the UITableView and limit it to my own UIView in the UITableViewCell?
You can try to subclass UITableView and override following methods
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
// if user tapped on your custom view, disable scroll
self.scrollEnabled = NO;
// end if
[super touchesBegan:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
self.scrollEnabled = YES;
[super touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
self.scrollEnabled = YES;
[super touchesCancelled:touches withEvent:event];
}
I don't think you can prevent user interaction on the UITableView, since it would affect all the subviews.
I'll try to send the UITableView interaction to the method you want it to use it.
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[MyClass myScrollDidStartMethod];
}
or use - (void)scrollViewDidScroll:(UIScrollView *)sender so that you can work on the sender's contentOffset to get the scrolling direction (see this post for more info about this)