Transparent UIView on top detecting touches - objective-c

I have an iPad project structured with a UISplitViewController:
RootViewController
DetailviewController
Both of them are detecting touches with Gesture Recognizer inside their own Class.
I would like to create a transparent UIView on top of all the Classes to detect ONLY a Diagonal Swipe (from the left bottom corner to the right top corner).
So, when the swipe will be detected I will launch a function otherwise nothing appended and the touch should be passed on the low level view.
I tried these two solutions:
Add a GestureRecognizer on this top transparent view but this will hide all touches to the lower hierarchy views.( with userInteraction enabled: YES ofcourse);
The other solution is to make the init like this
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self setBackgroundColor:[UIColor colorWithWhite:1 alpha:0.01]];
[self setUserInteractionEnabled:NO];
}
return self;
}
and try to detect the swipe with
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
But at this point all the touches are not detected.
Anybody have a nice solution?

I will not create a transparent UIView like you are mentioning. I will add a UISwipeGestureRecognizer to the UISplitViewController's view this is already the view that contains all your subviews. You can have access to the view within the app delegate:
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
// attach the swipe gesture to the view that embeds the rootView and the detailView
UISwipeGestureRecognizer* swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:splitViewController.view action:#selector(swipeUpdated:)];

Can't you just add a gesture recognizer to the UISplitViewController's view?

You should look into Container Controllers. You can make your own SplitViewController and make a third view on top of the controller that detects the swipe. Custom container controllers are pretty straight forward and gives you a lot of flexibility.

Related

Gesture recognizer for UIView no longer working after connecting the view to IBOutlet

I have a custom button which is basically a UIView with a gesture recognizer. Both the UIView and it's gesture recognizer were put together in interface builder.
The action for the gesture recognizer triggers a segue and opens a view controller. This works just fine.
I created an IBOutlet for this UIView button, but it seems that when I hook it up the action of triggering the segue and opening the next view controller stops working, even though the gesture recognizer and action are still showing up in interface builder.
Why does the gesture recognizer stop working when I hook the UIView up to an IBOutlet?
Check that the User Interaction is enabled for that view in the id-inspector or not. Or check there are no extra connection are shown in the connection inspector
Why you add gesture in your UIView? Simple make your UIView to UIControl class from storyboard and you can simple add action like button on it using storyboard
Or by adding gesture you can do it
connect IBOutlet of your view with UIView
then add gesture in it
-(void)viewDidLoad {
//The setup code (in viewDidLoad in your view controller)
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleSingleTap:)];
[vw_button addGestureRecognizer:singleFingerTap];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
//The event handling method
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
CGPoint location = [recognizer locationInView:[recognizer.view superview]];
//Do stuff here...
}

How to detect a tap gesture in subviews

Quick question: how do i detect if a tap gesture recognizer is within a subview of the view it is added to? Eg. if i click on an object such as a square that has been added as a subview to a background which a tap gesture recognizer has been added to, how do I detect that it has been tapped?
You can grab the point of the tap off the gesture recognizer when your handler method is called respective to any view you wish using -locationInView:. Then, use the following method on UIView: - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event to get a reference to the actual sub view that was tapped remembering that the point you pass in is in the same coordinate space as the view.
Some code to get you started:
CGPoint point = [tapGestureRecognizer locationInView:parentView];
UIView *tappedView = [parentView hitTest:point withEvent:nil];
For hit testing to work the view needs to have the userInteractionEnabled property set to YES. Many views, such as UILabels have this set to NO by default. So prior to the above:
self.subviewOfInterest.userInteractionEnabled = YES;
maybe you should set as:
subviews.userInteractionEnabled = YES;
good luck!
you can use the requireGestureRecognizerToFail: to recognize the tap on subview please refer this code

How do I make the keyboard go away when a user clicks on the background of the view?

I have a UITextField in my iOS app. When a user enters text and clicks Return, the keyboard goes away due to a call to an IBAction with "resignFirstResponder."
However, XCode does not let me drag a line from the UIView itself to File Owner. How do I associate touching the background of a UIView with an IBAction that makes the keyboard go away?
You can use UITapGestureRecognizer. see: Dismiss keyboard by touching background of UITableView
so instead of tableview, just add it to your view instead:
UITapGestureRecognizer *gestureRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)] autorelease];
gestureRecognizer.cancelsTouchesInView = NO; //so that action such as clear text field button can be pressed
[self.view addGestureRecognizer:gestureRecognizer];
and have a method to hide your keyboard
- (void) hideKeyboard {
[self.view endEditing:YES];
}
You've already noticed that you can't drag from the UIView to the file's owner to assoctiate an action with a touch.
The way to work around this is to change the class of the background view from UIView to UIControl and hook up an action from there to a method in your controller to stop editing.
That's because a UIControl can respond to touch events, and a UIView does not, but a UIControl subclasses UIView, and so it can be used in place of a UIView.
I wrote an example project a while ago that uses this technique. Have a look at the secondViewController's xib file and see how I've change the class of the background view and hooked it up to a an action in the controller to dismiss the keyboard.
Use the touchesBegan with Event and end editing on the view:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
One easy way to do it is to create a big transparent UIButton behind the view.

How to pass TouchUpInside event to a UIButton, without passing it to parent views?

I have a UIScrollview with paging enabled. There are 3 views (pages) inside this scroll view. There's a tap gesture on the parent view of the scrollview that shows and hides a navigation bar at the top.
The Problem:
In one of the pages I want to add buttons. But the problem is that whenever i tap these buttons, the show/hide navigation bar method is also fired. What is the best way to pass the touch only to these buttons and not the the parent view of the scrollview?
NJones is on the right track, but I think there are some problems with his answer.
I assume that you want to pass through touches on any button in your scroll view. In your gesture recognizer's delegate, implement gestureRecognizer:shouldReceiveTouch: like this:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch {
UIView *gestureView = recognizer.view;
// gestureView is the view that the recognizer is attached to - should be the scroll view
CGPoint point = [touch locationInView:gestureView];
UIView *touchedView = [gestureView hitTest:point withEvent:nil];
// touchedView is the deepest descendant of gestureView that contains point
// Block the recognizer if touchedView is a UIButton, or a descendant of a UIButton
while (touchedView && touchedView != gestureView) {
if ([touchedView isKindOfClass:[UIButton class]])
return NO;
touchedView = touchedView.superview;
}
return YES;
}

how to detect number of touches on the uiview in iphone sdk

in my app, when the user touches on the view ,i am showing an UIImageView there and i drag and
drop the image from another UIImageView to that touched UIImageView.
But the problem is that, only the recent touched UIImageView is activated. i mean ,when i
click 3 times then shows 3 UIImageViews but only the last is activated and accept the another
image.
How can i make all touched UIImageViews are activated .. Any body help on this..
Thanks in advance.
You should read Apples documentation on the responder chain and event handling. The key UIView method here is
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
This method traverses the view hierarchy by sending the
pointInside:withEvent: message to each subview to determine which
subview should receive a touch event. If pointInside:withEvent:
returns YES, then the subview’s hierarchy is traversed; otherwise, its
branch of the view hierarchy is ignored. You rarely need to call this
method yourself, but you might override it to hide touch events from
subviews.
You should try this:
Where there is your UIView (Or a view):
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapped:)];
tapGesture.numberOfTapsRequired = 1;//number of tap
[view addGestureRecognizer:tapGesture];
The selector:
-(void)tapped:(UITapGestureRecognizer *)sender {
NSLog(#"Pressed");
}