Hi all i want to know how to make subView added to content view of cell to become firstResponder.When i touch cell tableViewDidSelectRow methods get called.I have added customView as subView to cell.I have implemented delegate method which gets called when toches in custom view gets ended.But this method gets called after tableViewDidSelectRow method is called.I want first the delegate method to get called and then tableViewDidSelectRow .I have even set customView excluiveTouch property to YES.
Definitely ,
(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
will called after DidSelectRowFor . Because didSelect called as we click the cell and touchesEnded after when we removing the finger.
if u want touchesEnded must called before DidSelectRowFor than you have to override the some method. like
(BOOL)becomeFirstResponder in cell class as well as in custom class properly. also override
(UIResponder *)nextResponder this method to call next responder.
try once this . and let me know whether working or not?
Related
In iOS, I would like to receive touchesMoved events in a subview even when the touch began i the super view! Ideally, I would also like to receive touchesBegan when the moving finger reaches the subview.
What is the best way to achieve this?
I guess I could override touchesMoved:withEvent: in the superview, do a hit-test and then call the subview, but is there a better solution? (I have tried to resign first responder in the superview but that did not help)
I had to solve this exact same problem today, and I just did.
Say, you have the following -- this is an abstract description of exactly my case:
Main view containing a button and a sub view
When touches begin on the main view you want to receive the touch events on the sub view
One exception is that button: if you tap the button in the main view, then the button should handle that
The solution is to override the -hitTest:withEvent: method. The purpose of that method is to return the view that should handle the touches.
You have two options: override it in the sub view or override it in the main view. If you want ALL touches to be handled by the sub view, you can just have the -hitTest:withEvent on the sub view return self and be done with it. In my case I still needed the button on the main view to have its own touch detection, so my fix was to override the -hitTest:withEvent: method on the main view instead, as follows:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if (CGRectContainsPoint(self.myButton.frame, point))
{
return self.myButton;
}
else
{
return self.mySubView;
}
}
This works like an absolute charm! Hope this works for you as well :-)
You should of course modify the details inside -hitTest:withEvent: to suit your specific needs -- maybe you want to limit this override to a specific region or a specific set of controls -- but the point is that the answer to the main question on this thread lies in the override of this -hitTest:withEvent: method.
Erik
I'm currently developing an iPhone app where I have two UITextField's in one View Controller.
I have a method that is called when the keyboard appears (keyboardWillShow), and one that is called when it disappears (keyboardWillDisappear).
Now if the user touches the first field the keyboardWillShow method is called, but if he now touches the second field without touching the background before, keyboardWillShow of course is not called again, because the keyboard is already here.
I can also not use textFieldDidBeginEditing:(UITextField *)textField because it's also not called when you change field's directly.
Now how can i call keyboardWillShow again if he touches the first and the second one without letting the keyboard disappear between??
I found out the problem was i didn't set the delegate of the textfield's properly.
After setting #interface ViewController : UIViewController <UITextFieldDelegate>in my .h file and textfield2.delegate = self in the .m file, textFieldDidBeginEditing: was called when i changed the textfield's directly.
It appears that all the touch methods of a UIView are only called if the touches began within the bounds of that view. Is there a way to have a view respond to a user who has touched outside the view, but then dragged his fingers into the view?
In case it matters, my specific application is for dragging a MKPinAnnotationView (using built-in 4.0 dragging). I want something to happen if the user drags a pin onto another view (which happens to be an AnnotationView as well, but it could be anything). No method for dragging is called until I let go of the pin; and no method no the UIView that's being dragged to seems to be called unless I started by touching from within the view.
Because the superview is a MKMapView, it is difficult to just use the touchesMoved event of that and check if the user is in the right location or not. Thanks!
So after playing around with it for a while, I found that the answer given here actually gave me what I needed, even though the question being asked was different.
It turns out you can subclass UIGestureRecognizer; and have it handle all the touches for the view that it has been added to (including an MKMapView). This allows all the normal MKMapView interactions to still behave without any problem; but also alerts me of the touches. In touchesMoved, I just check the location of the touch; and see if it is within the bounds of my other view.
From everything I tried; this seems to be the only way to intercept touchesMoved while the user is dragging an MKAnnotation.
You sure can:
(HitstateView.h)
#import <UIKit/UIKit.h>
#interface HitstateView : UIView {
id overrideObject;
}
#property (nonatomic, retain) id overrideObject;
#end
(HitstateView.m)
#import "HitstateView.h"
#implementation HitstateView
#synthesize overrideObject;
- (void)dealloc {
self.overrideObject = nil;
[super dealloc];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *hitView = [super hitTest:point withEvent:event];
if (hitView == self) {
return overrideObject;
}
return hitView;
}
#end
Make this view the size of your touch area. Set the overideObject to the view you want the touches to go. IIRC it ought to be a subview of the HitstateView.
Every view inherits UIResponder so every view gets touchesBegan/Moved/Ended - I do not think starting the touch outside the view means the view gets no event when the touch moves over the view. If you want to get a notification that something has been dragged onto your MKMapView you should make a subclass that handles the touch but then passes the event to super, allowing the hierarchy to do whatever it needs to do with the touch. You don't need to capture or modify the event just observe it.
It depends on how your views are set up. Generally leveraging the responder chain is the best way to go. It allows you to play tricks, though it may be too specific to address your particular needs.
You can also play tricks with forward events by override hit testing:
http://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/MultitouchEvents/MultitouchEvents.html%23//apple_ref/doc/uid/TP40009541-CH3-SW3
Your particular case sounds pretty exotic, so you may have to play tricks like having a parent view whose frame is large enough to contain both views in question.
I have a table view with custom cells and I recognize swipes in that cells. That works just fine but I'd like the table view to behave normally. When I tap the wherever on the table view I'd like cell to get selected and perform action tableView:didSelectRowAtIndexPath:
Any tips or ideas?
Thanks.
I assume you are implementing the various UIResponder methods in your UITableView cell subclass. If you want the rest of the stack to continue processing the events you can just pass them on:
- (void) touchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
//do something with touch
//...
//pass the event to super which cause it to continue along the chain as
//though you didn't do anything special with it
[super touchEnded:touch withEvent:event];
}
I'm not sure why this is so hard. I have a UISearchBar at the top of my page. When the user types into that UISearchBar, it will automatically filter the results in the UITableView that is below the search bar. There is no need for a Search button since I search when keys are pressed.
The flow of the application is that the user types a search in the search bar (with the keyboard being displayed) and then will scroll the results in the table view - at which point the keyboard needs to disappear.
I'm having a hard time getting the keyboard to disappear.
I know I need to do:
[searchBar resignFirstResponder];
to get the keyboard to disappear but I can't find what delegate I need to perform this on. I want to do this as soon as the user touches the table view.
Any ideas?
Try this:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[searchBar resignFirstResponder];
}
It worked for me
I think the easiest (and best) way to do this is to subclass your global view and use hitTest:withEvent method to listen to any touch. Touches on keyboard aren't registered, so hitTest:withEvent is only called when you touch/scroll/swipe/pinch... somewhere else, then call [self endEditing:YES].
This is better than using touchesBegan because touchesBegan are not called if you click on a button on top of the view. It is also better than using a dim screen because in a complexe and dynamic user interface, you can't put dim screen every where. Also, it's better than calling [searchBar resignFirstResponder], because you may have many text fields on screen, so this works for all of them.
You might want to do it as Cydia (jailbroken packaging UI) does it - there is a search button, and when you press the search button, it closes the keyboard. The results are still filtered as you type for a preview.
Since the results are going to be in a table view, use UIScrollView's delegate (to which UITableView responds) method - (void)scrollViewDidScroll:(UIScrollView *)scrollView.
You'll need to have your view controller respond to the UITableView's data source and delegate (in the .h file):
<UITableViewDataSource, UITableViewDelegate>
Than in your initialization method in the .m file add:
self.tableView.dataSource = self;
self.tableView.delegate = self;
Finally, add this method:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self.view endEditing:YES];
}
This will make the UISearchBar lose focus, and the keyboard will hide.
One possibility is that the UISearchBar belongs to a controller, that is displayed in UIModalPresentationFormSheet.
I had the same problem and found out that this is related to the method "disablesAutomaticKeyboardDismissal" of UIViewController.
The Apple documentation states the following:
Override this method in a subclass to allow or disallow the dismissal
of the current input view (usually the system keyboard) when changing
from a control that wants the input view to one that does not. Under
normal circumstances, when the user taps a control that requires an
input view, the system automatically displays that view. Tapping in a
control that does not want an input view subsequently causes the
current input view to be dismissed but may not in all cases. You can
override this method in those outstanding cases to allow the input
view to be dismissed or use this method to prevent the view from being
dismissed in other cases.
The default implementation of this method returns YES when the modal
presentation style of the view controller is set to
UIModalPresentationFormSheet and returns NO for other presentation
styles. Thus, the system normally does not allow the keyboard to be
dismissed for modal forms.
In my case, I displayed the search bar within the navigation bar, so I had to create a subclass of UINavigationViewController that overrides the method as follows:
- (BOOL)disablesAutomaticKeyboardDismissal {
return NO;
}
After that resignFirstResponder would finally make the keyboard disappear.
Might be super late to answer but this might help anyone in future. This particular piece of code worked for me. P.S. I don't own this solution, found some time ago on the net itself.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
if ([self.srchBar isFirstResponder] && [touch view] != self.srchBar)
{
[self.srchBar resignFirstResponder];
}
[super touchesBegan:touches withEvent:event];
}
Given a view with a searchBar variable, add this method to the view:
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
{
if searchBar.isFirstResponder && !searchBar.point(inside: point, with: event){
searchBar.resignFirstResponder()
}
return super.hitTest(point, with: event)
}