Pass on a Tap to an UITextView - iphone

I was wondering how to pass on a tap on an UIView to an UITextView. This is my code so far:
- (void)foundTap:(UITapGestureRecognizer *)recognizer {
label.text = #"Touch detected";
[self.view bringSubviewToFront:aTextView];
[aTextView touchesBegan:touches withEvent:event];
}
Now, this obviously does not work as touches and event are not defined. But how do I define them? I can't declare touches as 1 (won't work). I could initialise it like so:
UITouch *touches =[touches anyObject];
But then again, touches is still undeclared. And I have no idea of how to declare the event. This is usually easy if you use the - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {} method, but I want to pass on the tap not the touches. Any help would be very much appreciated.
Edit:
I rewrote the method, but I still can't pass on the tap to the UITextView. I now need to double tap in order to edit it, i.e. the first tap for bringing the aTextView upfront and the second tap will then edit the UITextView (as it is in front and thus receives all the touches swipes etc.):
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[super touchesMoved:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self.view];
CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x); // will always be positive
CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y); // will always be positive
if (deltaY == 0 && deltaX == 0) {
label.text = #"Touch"; [self performSelector:#selector(eraseText) withObject:nil afterDelay:2];
[self.view bringSubviewToFront:aTextView];
[self.view bringSubviewToFront:doneEdit];
[aTextView touchesBegan:touches withEvent:event];
}
}

See if this previous SO question iPhone: Detecting Tap in MKMapView helps you.

Related

Detect touches for 2 subviews

I have a UIView sitting atop a UIScrollView.
I'd like to be able to scroll my ScrollView normally while having my UIView catch:
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
The only issue is I cannot seem to get both subviews to detect touches at the same time. I can set the top one to userInteractionEnabled to NO. But that doesnt really help me get them both.
Any thoughts??
Thanks!
In one of my project I catch touches in one view and pass the method to a second one this way:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
// Do something here
[otherView touchesEnded:touches withEvent:event];
}
EDIT: You can also use a third UIView just to menage touches.
Put a third UIView on top of your views (it should be as wide as your screen) and let it menage your touches
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
// Get touch position
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
// Use location to pass touches to one view ot the other
if (location == something) {
[oneView touchesEnded:touches withEvent:event];
} else {
[otherView touchesEnded:touches withEvent:event];
}
}

touchesMoved reaching out of my view bounds

I have subclassed UIView and there initially my view will be in a default color and i need to fill some different color on touch (from x axis = 0 to user touched point),here the problem is touchesMoved even if i drag out of my self view bounds it is getting those points,how to restrict it to only for my self view bounds.
I googled & tried below snippets but of no luck
if([self pointInside:point withEvent:nil]){
[self fillColor];
}
My touchesMoved method is as below,
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
endPoint = point;
NSLog(#"moved x: %f,y: %f",point.x,point.y);
if(CGRectContainsPoint([self frame], endPoint)){ // this also not working
[self fillColor];
}
}
Any help is appreciated in advance.
just set tag in viewDidLoad: method and use bellow logic..
fillColorView.tag = 111;
and use bellow logic in touchesMoved: method like bellow..
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *tap = [touches anyObject];
CGPoint pointToMove = [tap locationInView:fillColorView];
if([tap.view isKindOfClass:[UIView class]])
{
UIView *tempView=(UIView *) tap.view;
if (tempView.tag == 111){
[self fillColor];
}
}
}
hope this help you...
In your touchesMoved method, CGPoint point = [touch locationInView:self]; replcae self by the view in which you wants the touch to be worked.
self will get the complete view, you should pass your drawingView at there, so that it will detetc touch only on that view.

cocoa-touch: How to pass on a touch to another object

This is a beginner's question I'm afraid:
I have an UIText which covers the entire screen. I have another transparent view on top of this UITextView so as to be able to recognise swiping gestures (horizontally and vertically), like so:
- (void)viewDidLoad
{
[super viewDidLoad];
// UITextView
CGRect aFrame = CGRectMake(0, 0, 320, 480);
aTextView = [[UITextView alloc] initWithFrame:aFrame];
aTextView.text = #"Some sample text.";
[self.view addSubview:aTextView];
// canTouchMe
CGRect canTouchMeFrame = CGRectMake(0, 0, 320, 480);
canTouchMe = [[UIView alloc] initWithFrame:canTouchMeFrame];
[self.view addSubview:canTouchMe];
}
Let's consider the user touches (not swipes) the canTouchMe View. In this case, I would like the canTouchMe view to disappear and pass on the touch to the UITextView hiding beneath so that it enters the editing mode and enable the 'natural' scrolling options an UITextView has (i.e. only horizontally).
My touches began method looks like this:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch =[touches anyObject];
gestureStartPoint = [touch locationInView:self.view];
}
How do I tell this method that IF it recognises only ONE touch, that it should hide the canTouchMeFrame and PASS ON the touch to the UITextView?
Sorry if this is basic, but I have no idea how to implement this. Thanks for any suggestions.
EDIT:
I introduced a touchEnded method, but I still have no luck. The touch will not be forwarded to the UITextView. I need to tap twice in order to edit it:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[super touchesMoved:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self.view];
CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x); // will always be positive
CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y); // will always be positive
if (deltaY == 0 && deltaX == 0) {
label.text = #"Touch"; [self performSelector:#selector(eraseText) withObject:nil afterDelay:2];
[aTextView touchesBegan:touches withEvent:event];
[self.view bringSubviewToFront:aTextView];
[self.view bringSubviewToFront:doneEdit];
}
}
NSSet has a -count method. If touches only has one object, then you're responding to a single touch.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
if ([touches count] == 1) {
[self hideMyRectangle];
[someOtherObject touchesBegan:touches withEvent:event];
//etc, etc.
return;
}
// if you get here, there's more than one touch.
UITouch *touch =[touches anyObject];
gestureStartPoint = [touch locationInView:self.view];
}

Programmatically pass touches to UIScrollView to scroll

Basically I'm trying to make UIScrollView only scroll on higher angles. As in right now if you move your finger 10 degrees off horizontal, the scrollview will scroll. I'd like to push that up to, say, 30 degrees.
After doing some reading, I established the best way to do this would be to put a subclassed UIView on top of the scrollview. If the UIView on top's touches are above 30 degrees, pass it down to the scrollview, and otherwise don't.
However, I can't figure out how to pass the touches down. Here's my code right now:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"glass touch began");
UITouch *touch = [touches anyObject];
beginning_touch_point = [touch locationInView:nil];
[scroll_view touchesBegan:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"glass touch ended");
UITouch *touch = [touches anyObject];
CGPoint previous_point = beginning_touch_point;
CGPoint current_point = [touch locationInView:nil];
float x_change = fabs(previous_point.x - current_point.x);
float y_change = fabs(previous_point.y - current_point.y);
if(x_change > y_change)
{
if(previous_point.x - current_point.x < 0)
{
[(MyScheduleViewController *)schedule_controller didFlickLeft];
}
else
{
[(MyScheduleViewController *)schedule_controller didFlickRight];
}
[scroll_view touchesCancelled:touches withEvent:event];
}
else
{
[scroll_view touchesEnded:touches withEvent:event];
}
}
I know right now that it's checking for 45 degrees, but that's not the important thing. What is important is that the touches are indeed getting passed down correctly to my scroll_view. I have it doing a NSLog() on touchesbegan and touchesended, and it's doing both correctly. It's just not scrolling. I'm worried touchesBegan and touchesEnded cannot cause a scroll. Does anyone know what can, or what I'm doing wrong?
I also tried to do the same but didn't succeed. It seems scrollView doesn't handle touchesMoved/touchesBegan, but it handles some other events to understand that user wants to scroll the view.
For me the solution was to determine thet shift value and set it explicitly as a scrollView content offset. It looked like this (I don't have the exact source code no, this code may work incorrectly):
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint curr = [touch locationInView: self];
CGPoint offset = [scrollView contentOffset];
[scrollView setContentOffset: CGPointMake(offset.x + (curr.x - prev.x), offset.y) animated:YES];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
prev = [[touches anyObject] previousLocationInView: self];
}

iPhone - UIWebView Gestures

I have viewcontrollers set up to track gestures and commit an action, in this case, change the tab. The code for the viewcontrollers is as follows:
#define HORIZ_SWIPE_DRAG_MIN 100
CGPoint mystartTouchPosition;
BOOL isProcessingListMove;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint newTouchPosition = [touch locationInView:self.view];
if(mystartTouchPosition.x != newTouchPosition.x || mystartTouchPosition.y != newTouchPosition.y) {
isProcessingListMove = NO;
}
mystartTouchPosition = [touch locationInView:self.view];
[super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = touches.anyObject;
CGPoint currentTouchPosition = [touch locationInView:self.view];
// If the swipe tracks correctly.
double diffx = mystartTouchPosition.x - currentTouchPosition.x + 0.1; // adding 0.1 to avoid division by zero
double diffy = mystartTouchPosition.y - currentTouchPosition.y + 0.1; // adding 0.1 to avoid division by zero
if(abs(diffx / diffy) > 2.5 && abs(diffx) > HORIZ_SWIPE_DRAG_MIN)
{
// It appears to be a swipe.
if(isProcessingListMove) {
// ignore move, we're currently processing the swipe
return;
}
if (mystartTouchPosition.x < currentTouchPosition.x) {
isProcessingListMove = YES;
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:0];
return;
}
else {
isProcessingListMove = YES;
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:2];
return;
}
}
else if(abs(diffy / diffx) > 1)
{
isProcessingListMove = YES;
[super touchesMoved:touches withEvent:event];
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
isProcessingListMove = NO;
[super touchesEnded:touches withEvent:event];
}
I'd like to have the same gesture do the same thing on a uiwebview I have set up under the view of the viewcontroller. In short, the uiwebview is on the view. When I swipe, I just get the basic uiwebview functions (scrolling). If I set up a custom uiwebview class with the same code as the uiviewcontroller, I get errors. I need to know how to translate that block of code, keeping the functionality intact, to suit the uiwebview.
You should be able to subclass UIWebView and override those methods. You may have to override all of the touch methods, though,
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
EDIT:
Ah, I see your errors now. They are because those things don't apply to the UIWebView like they did to the parent (which you already know...)
Since UIWebView is a UIView, you should be able to replace
[touch locationInView:self.view]
with
[touch locationInView:self]
To get to the parent's tab bar controller, though, you'll have to design a different way to do it. You could pass a reference to the parent to your UIWebView subclass and expose a method on the parent for changing which tab is active, for instance:
In your subclass, add a property for the parent tab bar controller:
UITabBarController *parent;
When creating your UIWebView subclass and adding it to the tab bar controller, also set the parent:
webView.parent = self;
If you're setting this up in Interface Builder, make the parent an IBOutlet and hook it up through IB.
In your tab bar controller view, add a method that changes the selected controller. You could use named constants for the view you want to switch to, or methods that describe exactly what you are switching to, but for simplicity, you'd do something conceptually similar this:
- (void) switchToView: (int)viewNumber
{
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:viewNumber];
}
then call [parent switchToView:2] in your code.
Another and arguably better way is to use NSNotifications, registering the parent as a listener.
My full code is the following:
#import "CustomWebView.h"
#implementation CustomWebView
//Swipe between tabs
#define HORIZ_SWIPE_DRAG_MIN 100
CGPoint mystartTouchPosition;
BOOL isProcessingListMove;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint newTouchPosition = [touch locationInView:self.view]; "error: request for member 'view' in something not a structure or union"
if(mystartTouchPosition.x != newTouchPosition.x || mystartTouchPosition.y != newTouchPosition.y) {
isProcessingListMove = NO;
}
mystartTouchPosition = [touch locationInView:self.view]; "error: request for member 'view' in something not a structure or union"
[super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = touches.anyObject;
CGPoint currentTouchPosition = [touch locationInView:self.view]; "error: request for member 'view' in something not a structure or union"
// If the swipe tracks correctly.
double diffx = mystartTouchPosition.x - currentTouchPosition.x + 0.1; // adding 0.1 to avoid division by zero
double diffy = mystartTouchPosition.y - currentTouchPosition.y + 0.1; // adding 0.1 to avoid division by zero
if(abs(diffx / diffy) > 2.5 && abs(diffx) > HORIZ_SWIPE_DRAG_MIN)
{
// It appears to be a swipe.
if(isProcessingListMove) {
// ignore move, we're currently processing the swipe
return;
}
if (mystartTouchPosition.x < currentTouchPosition.x) {
isProcessingListMove = YES;
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:0]; "error: request for member 'tabBarController' in something not a structure or union"
return;
}
else {
isProcessingListMove = YES;
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:2]; "error: request for member 'tabBarController' in something not a structure or union"
return;
}
}
else if(abs(diffy / diffx) > 1)
{
isProcessingListMove = YES;
[super touchesMoved:touches withEvent:event];
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
isProcessingListMove = NO;
[super touchesEnded:touches withEvent:event];
}
// End of swipe
#end
The errors are as follows are included with the code.
I appreciate the help.