I have UIScrollView that has many subviews. When I scroll, I want to tap on a subview which I want to be dragged. Is there a possible way to make the UIScrollView stop from swallowing touches? Or is it possible to start new touch when you cancel the scrolling (like what it scrolls and I tapped on it, the subview will be tapped as well so I can drag it out)?
Subclass UIScrollView and override the - (BOOL)touchesShouldCancelInContentView:(UIView *)view method. Here's an example to allow uibutton touches to pass through:
#import "scrollViewWithButtons.h"
#implementation scrollViewWithButtons
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
return ![view isKindOfClass:[UISlider class]];
}
#end
Related
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...
}
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.
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.
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;
}
I have a custom UIViewController class whose view (hooked up in IB) is a UIScrollView. I want to know when the UIScrollView gets "touch up inside".
I overrode the
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
method but it doesn't get called. What am I doing wrong?
Did you override touchesBegan:: in the UIViewController or the UIScrollView? If you did it on the UIViewController, it needs to be in the UIScrollView (or whatever it contains).
The UIScrollView is intercepting the touch events before it "bubbles" to your UIViewController.
like ryan said, you need to override your touchesBegan:: method in the UIScrollView. you may need to create a custom scrollView for this purpose and set the scrollView you use (in IB) to that class. also, be sure to set the scrollView delegate to your view controller. that way, when touches are intercepted, it knows where to send them