My problem is about tap detection.
I have a uiviewcontroller and there are some controls on uiview (labels, buttons, tableview, imageview, etc..)
When I tap the uibutton I display a small uiview (200x150), if the user taps the uibuttons in smallview I hide the smallview.
But I can't hide the uiview if the user taps the background.
I tried this code..
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//NSLog(#"Touches began.");
[self hideShareView];
}
It doesn't work if I tap the another button in the uiviewcontrols view.
I just want my uiviewcontrol's uiview to react first.
I think its about firstResponder but I dont know how to set it first.
edit: i want it to work like a uiPopover in ipad.
I believe that the correct approach is to add a new transparent UIView when you display your "smallview". You should add a UITapGestureRecognizer to that UIView, in order to trigger the desired selector when the tap is detected. Also, you must ensure that the views are arranged properly, with your smallview being the one at the top, the transparent UIView being immediately below and the rest of the view hierarchy below the transparent UIView.
Finally, you should ensure to remove the transparent UIView from your view hierarchy at the same time that you remove your smallview.
Does that make sense?
Please have a look at this question (how-to-make-a-superview-intercept-button-touch-events), it does seem highly related.
try your hands with bringing your small view (i.e. shareview) to front or sent your main view behind your small view.
If it still doesn't work & you don't want your main view to perform any action when smallview is opened then try
[<YOUR_MAIN_VIEW> setUserInteractionEnabled:NO];
, but MAKE SURE you can do this only when you don't want your main view to perform any action when smallview is opened
Related
Possibly a duplicate, but I couldn't find an exact answer to my problem searching SO tonight...
I have a UIButton which contains a UIScrollView, so the button is the superview.
All I want to do is pass a single-tap event from the UIScrollView subview to the UIButton superview, and have the UIButton handle it as it would if the user tapped the button directly.
Setting the scroll view's userInteractionEnabled property to NO won't work for me because there is content the user can scroll. Doing so would defeat the purpose of the scroll view.
Is this possible? Thanks!
Like huoxinbird said, it's definitely not common to lay your views like that.
In the case where you are solidly adamant about this, you could use UITapGestureRecognizer and have it call the button's target and selector.
If you wanted to include the button highlight and such, then you may have to subclass UITapGestureRecognizer and forward the touchesEnded to the button.
Create a subclass of scrollview and override
-(BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
return YES;
}
Also subclass the uibutton(Your superview) and handle touches in touches began.
Usually you don't put scrollview within a button. Instead consider using a UIView as the superview of scrollview. Or tell us more about your use case, so I can understand why you have to design in this way.
I have a UIButton underneath a (transparent) UIView. The UIView above has a UISwipeGestureRecognizer added to it, and that is its only purpose - to detect certain swipe gestures. I want all other touches to be ignored by that UIView, and passed to other views (such as my UIButton underneath). Currently, the UIView above seems to be detecting the tap (for example), doing nothing (as it should be), and not letting the UIButton underneath get a chance to respond.
I would prefer not to implement my own swipe recognizer, if possible. Any solutions / advice? I basically just want to know how to tell a UIView to pay attention to only a certain type of added gesture recognizer, and ignore (and thus let through to views behind) all other touches.
Have you set:
mySwipeGesture.cancelsTouchesInView = NO;
to allow the touches to be sent to the view hierarchy as well as the gesture?
Additionally, ensure that the view on top is:
theTransparentView.opaque = NO;
theTransparentView.userInteractionEnabled = YES;
I've had pretty good success attaching gestures to the parent view without needing to create a transparent subview on top for the gesture. Are you sure you need to do that?
I must have just been in a funk yesterday - I woke up with a simple solution today. Add the UISwipeGesture to a view which is a superview to both the UIView and the UIButton. Then, when processing those swipes, figure out where the swipe originated, and whether that point is in the frame of where I used to have the UIView. (As I mentioned, the only reason for the existence of the UIView was to define a target area for these swipe gestures.)
Can't you put your button on top of the view and add gesture recognisers to that button too?
In the end, your UIButton inherits form UIView via UIControl. Therefore there is practically nothing that you could do with a view but not with a button.
In my case, I fixed it by not using a button, but rather a UITapGestureRecognizer. My pan gesture recognizer was added to the background view, and the tap gesture was added to a view above it.
I have a simple app which adds a subview over the main view when the user clicks on a UIButton in the main view. This subview is of size 480x320 (I'm in landscape mode), but there is a boarder around the centre image in this subview which is transparent.
This is where my problem lies. I would like only the subview to process touches until it is removed from the superview, but if there is a touch event on the transparent boarder, the event gets passed to the superview, and ignores the subview, even though the subview is the full size of the window.
Doing some research into this, it seems as though this is what apple intended to happen, as touches will only get passed to opaque sections, even if the subview is the full size of the window. It is explained in the reference:
http://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/MultitouchEvents/MultitouchEvents.html
I would like to be able to set it such that the touches will stay with the subview, regardless of any transparency issues. The hitTest:withEvent: method seems to do something like this, but more for passing touches to different subviews then the one that was touched.
Is there anyone who has a fix/work-around that can achieve this?
Simple solution is to subclass your subview and add the following empty method...
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
}
This will prevent the touch from getting passed to the superview, even if the user were to touch a transparent part of the view.
You should just put a clear button in the back of the xib. That will prevent touch events from going off.
If you make the backgroundColor of your subview hidden, you will obtain the same effect (a transparent border around the UIButton), and your view will receive touches:
You can execute this code just before adding the subview:
subview.backgroundColor = [UIColor clearColor];
subview.hidden = NO;
[parentView addSubview:subview];
I have a UIScrollView ontop of my UIViewController recreating an effect like in the Gowalla iPhone app when you're on a spot's page. Under my scroll view I have a button that I want to be able to perform it's action even when the scroll view's frame covers it up (where it's ontop of the button, the scroll view's clear). How would I do something like this? Is it possible? (it has to be, Gowalla [somehow] did it)
As for me, I will transfer touch event to another view by override following methods.
– touchesBegan:withEvent:
– touchesMoved:withEvent:
– touchesEnded:withEvent:
– touchesCancelled:withEvent:
Like this way,
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// pass touch event by default implement.
[super touchesBegan:touches withEvent:event];
// redirect the touch events.
[anotherView touchesBegain:touches withEvent:event];
}
hitTest:withEvent: is used to decide which view should response touch event on the view hierarchy tree. If the view doesn't want to response touch event, it will return nil in hitTest. As result the above touch event methods won't be called.
I have no idea what this "Gowalla" app might do; hopefully, your description of "a button behind the scroll view, that you can touch 'through' the scroll view" is accurate.
If your button behind the scroll view can be sized to fill the entire contentSize area of the scroll view without screwing up your interface, the easiest solution would be to just put it inside the scroll view (under all the other views) and do just that.
Otherwise, your best bet is probably to create a custom view with a clear background to be placed in the scroll view as above. The easy solution is to have the custom view (probably a UIControl) just do whatever touching the button does. If that's not possible for some reason, your best option would be to override hitTest:withEvent: on the custom view to return the underlying button. I'd be wary of overriding hitTest:withEvent: on the scroll view itself, as that might interfere with scrolling.
Try adding the button on top of the scroll view. The only problem with that is if you hit the button, you will not be able to interact with the scrollView, but it will still be visible.
I have my UIWindow structured in Interface Builder as:
window
drawingView (custom UIView)
toolbar (UIToolbar)
Where the drawingView handles touches using touchesBegan etc. However, when I try and add 'someView' (a custom UIView) which has UIButtons on it as a subview of window, the buttons don't receive any of the touches.
I create 'someView' with:
[[[UIApplication sharedApplication] keyWindow] addSubview:someView];
'someView' displays fine on top of the drawingView, but the touches don't seem to register at all, and get passed through to drawingView. Why is that?
Another odd thing is that the backgroundColor of someView always seems to be clear, even if I set it to something else programatically or in IB.
Also, when I create someView using
[[UIPopoverController alloc] initWithContentViewController:someView];
it works fine, handling touches and all. The reason I want to add it as a subview is because I want a more general way of adding someView, that is works on the iphone as well.
Make sure the userInteractionEnabled flag is set on all parents of the view that needs to receive touches.
I've figured out a fix (in a hackish kind of way).
I had to add 'someView' as a subview of drawingView, which appears on top of drawView when shown, and allows me to programatically set up someView with UIButtons, which receives touches.
I think it's because drawView is an OpenGL view, that overrides layerClass which does something funky with how the views are arranged to obtain touches. I think.