Remove Done Button From Number Pad upon a New Keyboard Loading - iphone

Alright, I'll try to explain this the best I can. I have an iPhone app and it has a text field which the user can only input Numbers. Not a problem there. However, there is no done button on the numpad, so I can't make it disappear. I could make a button that the user presses to dismiss the keyboard, but I'd rather have a done button because the screen is "busy" as is.
Well, after some research, I came across this. Wow, that worked great. However, I also have another text field which requires the default keyboard. And whenever the keyboard comes up, regardless of the type, it has the "Done" button on it.
Not good.
So I do some more digging. Read through the comments, and people mentioned a way to get rid of the Done button using the "Editing Did Begin" trait, to only call the "Done Button" code when necessary. I also got that mostly done. If you type in the number field, and then dismiss the keyboard, and then type in the normal field, the done button does not appear.
However, there is one bug, where the "Done" button still appears. If you tap the Numeric Field, and then tap the Normal field, the keyboard never "disappears", so even though it changes from a numpad to a normal keyboard, the button still is there. I want to remove the buttom from the view, but I'm not sure how to go about this. This is the code I have...
//Done button for numpad
- (void)keyboardWillShow:(NSNotification *)note {
if (showDoneButton == YES)
{
// create custom button
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
if ([[[UIDevice currentDevice] systemVersion] hasPrefix:#"3"]) {
[doneButton setImage:[UIImage imageNamed:#"DoneUp3.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImage imageNamed:#"DoneDown3.png"] forState:UIControlStateHighlighted];
} else {
[doneButton setImage:[UIImage imageNamed:#"DoneUp.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImage imageNamed:#"DoneDown.png"] forState:UIControlStateHighlighted];
}
[doneButton addTarget:self action:#selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
// locate keyboard view
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
UIView* keyboard;
for(int i=0; i<[tempWindow.subviews count]; i++) {
keyboard = [tempWindow.subviews objectAtIndex:i];
// keyboard view found; add the custom button to it
if([[keyboard description] hasPrefix:#"<UIKeyboard"] == YES)
[keyboard addSubview:doneButton];
}
showDoneButton = NO; //This tells done button code to run or not
}
}
- (void)doneButton:(id)sender {
NSLog(#"Input: %#", playerOneLifeLabel.text);
NSLog(#"Input: %#", playerTwoLifeLabel.text);
[playerOneLifeLabel resignFirstResponder];
[playerTwoLifeLabel resignFirstResponder];
}
When the NumPadfield triggers "editing did begin" it calls this function:
- (IBAction)needNumberPad:(id)sender{
showDoneButton = YES;
}
Which then makes sure the done button is shown. When the done button code is done, the variable (as seen above) is set back to NO, so it doesn't show up again if you tap the default text field. The Boolean variable is set to NO as default.
What needs to happen is if you jump immediately from editing the numPad field to the default field, the done button disappears. I can put the code in the function that is called when "Editing did end" but I don't know what to put there. Help would be appreciated, I've gotten this far!
Thank you!

Follow these steps
a. First make the doneButton an instance varible of your class, this will help you maintain the reference to the button
b. Add this code at the beginning of your keyboardWillShow:(NSNotification *)note method
if(!showDoneButton ){
if(doneButton){
[doneButton removeFromSuperview];
doneButton = nil;
}
return;
}
c. add notification for keyBoardWillHide
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
d. in keyBoardWillHide method do the following
- (void)keyboardWillHide:(NSNotification *)note
{
if(doneButton)
{
[doneButton removeFromSuperview];
doneButton = nil;
}
}
This should do the trick.

You can use the method below:
//This delegate notify when the user done from the textfield
- (void) textFieldDidEndEditing:(UITextField *)textField{
[yourTextField resignFirstResponder];
[doneButton removeFromSuperview];
doneButton = nil;
}
yourTextField means the textfield that contains done button on keypad.
The previous method will remove the doneButton from the next keyboards.

Related

Implement Long press on button and show delete button on top of that button like deleting app from background

I want to implement a long press on my button and after that long press a cross button should appear on the top of the button to remove that button from scroll view which is added in table view.
I search on web and got UILongPressGestureRecognizer to implement.I tried with it but I have many button in my scroll view and I put UILongPressGestureRecognizer on every button but how will I give reference of the pressed button to the selector method so that I can add a cross button on that particular pressed button.
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(deleteAppFromList:)];
UIButton *btn=(UIButton *)[cell.contentView viewWithTag:101+i];
[btn addGestureRecognizer:longPressGesture];
[longPressGesture release];
Please suggest me how to implement this.I want to do the functionality just as when we delete an app from ios device or simulator.
I've just done something similar. I detect the touchDown event, schedule a timed method which sets a flag after 1 second, then when the touch up event is detected it checks the flag and calls the appropriate method.
[myButton addTarget:self action:#selector(itemTouchDown) forControlEvents:UIControlEventTouchDown];
[myButton addTarget:self action:#selector(itemTouchUpInside) forControlEvents:UIControlEventTouchUpInside];
-(void)itemHoldTimer:(NSTimer *)timer
{
self.itemHoldTimer = nil;
didHold = YES;
}
-(void)itemTouchDown{
didHold = NO;
self.itemHoldTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(itemHoldTimer:) userInfo:nil repeats:NO];
}
-(void)itemTouchUpInside {
if (didHold) {
didHold = NO;
[self itemWasTouchedUpAndDidHold];
} else {
didHold = NO;
[self itemWasTouchedUp];
}
}
In your handler method that you set up as the target of the gesture recognizer you are passed a reference to the recognizer that fired, e.g.:
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer;
The recognizer has a 'view' property, which is the view the recognizer is attached to. Use this directly or get the tag of this view and you can work out which button was pressed.
UIView *myButton = gestureRecognizer.view;
Having said that, adding a gesture recognizer to each button seems the wrong way to do this. I would create a custom control and handle 'touchesBegan' and 'touchesEnded' directly.
In the handler method of the long press recognizer, use the view property and its tag to identify the view.
-(void)handleLongPress:(UILongPressGestureRecognizer*)longPressRecognizer
{
//longPressRecognizer.view.tag
}

Dismiss the keyboard if action sheet is going to popup

I have a UIDatePickerView inside UIActionSheet as a input to the UITextField. When focusing on UITextField UIActionSheet will popup instead of Keyboard. When clicking on the done button in the UIActionSheet it'll hide. I have several other text fields behave as normal (Showing keyboard).
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if ([textField isEqual:txtExpDate]) {
[textField resignFirstResponder];
[self showDatePicker];
}
}
- (void) showDatePicker{
UIActionSheet *datePickerActionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:#"Done" otherButtonTitles:nil];
datePickerView = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 80, 0, 0)];
datePickerView.datePickerMode = UIDatePickerModeDate;
[datePickerActionSheet addSubview:datePickerView];
[datePickerActionSheet showInView:self.navigationController.view];
[datePickerActionSheet setBounds:CGRectMake(0, 0, 320, 500)];
[datePickerActionSheet release];
}
Now my problem is, Let say first user taps on normal textfield. Which will popups keyboard. Then without selecting done button he taps on date field. Which will popup action sheet (without dismissing the keyboard). After hiding actionsheet user has to tap on other text filed and click on return key of the keyboard.
I want to hide the keyboard if action sheet is going to popup?
Make the text field resignFirstResponder when you are going to bring up the action sheet. If you have more than one text fields, create an instance variable of type UITextField in .h file.
UITextField *currentTextField;
Then you can keep reference of the current text field in textFieldDidBeginEditing: method.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
currentTextField = textField;
....
And, call [currentTextField resignFirstResponder] in showDatePicker method.
- (void)showDatePicker {
[currentTextField resignFirstResponder];
UIActionSheet *datePickerActionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:#"Done" otherButtonTitles:nil];
...
EDIT: #Samuel Goodwin is correct. We don't have to track the text fields. We can simply do the following to dismiss the keyboard.
- (void)showDatePicker {
[self.view endEditing:YES];
...
If you want to dismiss the keyboard for any reason, simply do:
[[UIApplication sharedApplication] sendAction:#selector(resignFirstResponder) target:nil forEvent:nil];
Worked for all text fields everywhere anywhere.
The method proposed by EmptyStack did not work for me (using xcode 4.2). I placed the message [currentTextField resignFirstResponder] in the method willPresentActionSheet:(UIActionSheet *)actionSheet, that also didn't work. Then I put the message in actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex and that did the trick... strange!
I know this is a very old post but I just thought I'd add the solution that worked for me (the others didn't). I found that I had to re-assign a text field to be first responder the resign it again. It doesn't matter which text field becomes then looses first responder status, this is just a way to ditch that keyboard.
[self.textfield becomeFirstResponder];
[self.textfield resignFirstResponder];
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if ([textField isEqual:txtExpDate]) {
[self showDatePicker];
return NO;
}
return YES;
}
It is working fine.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if(textField==myTextField2){
[myTextField1 resignFirstResponder];
[self showActionSheet];
return NO;
}
return YES;
}

Search Bar Cancel Button is Not Working

My App is having a search bar for searching records from the table view,which is populated by sqlite DB.
My problem is that when the view opens the "cancel" button is not enabled and also I cant touch on that, just like a image only.It is there but no action is with that.
when we click on that search bar text the cancel button will be changed to "done" it is enabled one.
so here is my code
this is my search bar view,see that cancel button.It is not enabled
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
//[newSearchBar setShowsCancelButton:YES animated:YES];
newSearchBar.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;
NSLog(#"search begin edit") ;
//searchString = searchBar.text;
//NSLog(#"print did edit searchstring : %#", searchString) ;
for(UIView *view in [searchBar subviews])
{
//shareItemId =newSearchBar.text;
if([view isKindOfClass:[NSClassFromString(#"UINavigationButton") class]]) {
[(UIBarItem *)view setTitle:#"Done"];
}
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
NSLog(#"searchBarTextDidEndEditing:");
[searchBar resignFirstResponder];
//[self dismissModalViewControllerAnimated:YES];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
NSLog(#"searchBarSearchButtonClicked");
searchString = searchBar.text;
NSLog(#"search %#", searchBar.text);
[newSearchBar setShowsCancelButton:NO animated:YES];
[searchBar resignFirstResponder];
//[self dismissModalViewControllerAnimated:YES];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
NSLog(#" searchBarCancelButtonClicked");
[searchBar resignFirstResponder];
shareItemName =newSearchBar.text;
[self dismissModalViewControllerAnimated:YES];
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
NSLog(#"searchBarShouldBeginEditing");
[newSearchBar setShowsCancelButton:YES animated:YES];
return YES;
}
These are my delegates for that
Please check my code and give me the answer. I need to enable the "Cancel" button when the view is loaded and it action will be go back to previous view
I need like this
Or else how can I add a another cancel button on exciting cancel button.so that I can enable that.please give me all the details
You need to set the UISearchDisplayController to be ACTIVE, like this:
[mySearchDisplayController setActive:YES animated:YES];
or more simply:
mySearchDisplayController.active = YES;
My guess is that Apple made the UISearchBar in a way that the cancel button is disabled if the search text field is empty or not first responder.
This is make sense because you should not use the "Cancel" button to other purpose than actually canceling the search. and since there is no search to cancel - the button is disabled.
If you still want that the button will be active immediately when the view is presented, you can call at viewWillAppear: to [mySearchBar becomeFirstResponder];
This will cause to the keyboard to appear and the button will be enabled.
And then if the user hit cancel you can intercept it to go back to the previous view. (I'm not sure if apple will like this behavior).
Sample code:
-(void) viewWillAppear : (BOOL) animated
{
[super viewWillAppear:animated];
// Make keyboard pop and enable the "Cancel" button.
[self.mySearchBar becomeFirstResponder];
}
Here's what I did to always enable the cancel button, even when the search field is not first responder.
I'm calling this method whenever I call resignFirstResponder on the search field
- (void)enableCancelButton {
for (UIView *view in self.searchBar.subviews) {
if ([view isKindOfClass:[UIButton class]]) {
[(UIButton *)view setEnabled:YES];
}
}
}
This works, but I'm not sure whether it will pass App Store verification yet, so use it at your own risk. Also, this probably only works if the cancel button is the only button you are using with the search field.
This works to reenable the cancel button as of iOS 8:
private func enableButtonsInSubviews(view: UIView) {
if let view = view as? UIButton {
view.enabled = true
}
for subview in view.subviews {
enableButtonsInSubviews(subview)
}
}

is Gesture Recognization working on buttons or not?

In my app, I wrote these lines of code :
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[mybutton1 addGestureRecognizer:tapper];
[mybutton2 addGestureRecognizer:tapper];
[mybutton3 addGestureRecognizer:tapper];
[tapper release];
}
-(void)tapped:(UIGestureRecognizer *)sender{
NSLog(#"I'am in tapped");
}
but nothing happened. why ? and if I need to get the button's currentTitle inside tapped, can I ?
Thanks
You're missing the recognizer delegate. Implement that. You should also add the UIGestureRecognizerDelegate protocol to your header file and make recognizer.delegate = self.
re: getting the title - you can get the title. in your tap event handler you can extract that information from the sender object. i'll post some code later...
You don't need to use a gesture recogniser just to detect when a button is pressed. A button knows when it's being pressed!
Try:
{
// Blah...
[myButton addTarget:self action:#selector(tapped:) forControlEvents:UIControlEventTouchUpInside];
// Other stuff
}
-(void)tapped:(id)sender {
NSLog (#"I'm in tapped!");
}
A gesture recognizer can only be attached to one view at a time. Handling single taps on buttons can just as easily be done using IBAction. You can create one IBAction and connect all three buttons to it.
- (IBAction)tapped:(id)sender {
UIButton *button = (UIButton *)sender;
NSLog(#"%#", button.titleLabel.text);
}
A similar question: UITapGestureRecognizer on a UIButton

Remove clear button (grey x) to the right of UISearchBar when cancel button tapped

Right, to begin my question, here's some screenies of the problem already solved by the Spotify app:
Spotify's Step 1: Standard UISearchBar not in editing mode.
Spotify's Step 2: UISearchBar now in editing mode. Search term entered. Cancel button slides in from the right, and the clear button (grey x) appears.
Spotify's Step 3: Cancel button pressed; keyboard slides out and the search bar is no longer in editing mode. Search term remains and the grey x button is now hidden.
At present, the following code fires off when my cancel button is pressed:
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
[searchBar setShowsCancelButton:NO animated:YES];
}
Which results in:
My Step 3: Search bar now not in editing mode. Cancel button and keyboard has slid out. Search term remains but so does the grey x.
So, my question is this: given that -resignFirstResponder (and -endEditing:, FYI) does not hide the grey x button when a search bar has had text entered into it, how does one hide it?
Thanks again, friends.
The problem is that UISearchBar doesn't expose it's text field, and manages the properties on the text field itself. Sometimes, the values of the properties aren't what you want.
For instance, in my own app, I wanted the keyboard style for my search bar to use the transparent alert style.
My solution was to walk through the subviews of the search bar until you find the text field. You should then be able to set the clearButtonMode property, using something like UITextFieldViewModeWhileEditing as a parameter.
This should make it so that the clear button is only shown while the text field is editing.
You want to do this on viewDidLoad or something early, so it's set before you start using it (but after the search bar is initialised.
for (UIView *subview in searchBar.subviews)
{
if ([subview conformsToProtocol:#protocol(UITextInputTraits)])
{
[(UITextField *)subview setClearButtonMode:UITextFieldViewModeWhileEditing];
}
}
Looks like iOS 7 changed the view hierarchy of UISearchBar, and the text box is deeper in the view (The above solution didn't work for me). However, modifying the above solution to traverse the whole hierarchy works:
[self configureSearchBarView:[self searchBar]];
- (void)configureSearchBarView:(UIView*)view {
for (UIView *subview in [view subviews]){
[self configureSearchBarView:subview];
}
if ([view conformsToProtocol:#protocol(UITextInputTraits)]) {
[(UITextField *)view setClearButtonMode:UITextFieldViewModeWhileEditing];
}
}
I'm building upon the previous answers because I started seeing crashes on iOS 7.1 unless I made the following change. I added an additional call to respondsToSelector for each view to make sure that setClearButtonMode: can be called. I observed an instance of UISearchBar getting passed in, which seems to conform to the UITextInputTraits protocol yet does not have the setClearButtonMode: selector, so a crash occurred. An instance of UISearchBarTextField also gets passed in and is the actual object for which to call setClearButtonMode:.
- (void)removeClearButtonFromView:(UIView *)view
{
if (!view)
{
return;
}
for (UIView *subview in view.subviews)
{
[self removeClearButtonFromView:subview];
}
if ([view conformsToProtocol:#protocol(UITextInputTraits)])
{
UITextField *textView = (UITextField *)view;
if ([textView respondsToSelector:#selector(setClearButtonMode:)])
{
[textView setClearButtonMode:UITextFieldViewModeNever];
}
}
}
You need to get the textField of the Search Bar
UITextField *textField = [searchBar valueForKey:#"_searchField"];
textField.clearButtonMode = UITextFieldViewModeNever;
use in - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar method.
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
UITextField *textField = [searchBar valueForKey:#"_searchField"];
textField.clearButtonMode = UITextFieldViewModeNever;
}
A better way to do this in iOS7 is:
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setClearButtonMode:UITextFieldViewModeWhileEditing];
To expand on Jadariens answer if you never want the grey x to appear you need to use the following
for (UIView *subview in searchBar.subviews)
{
if ([subview conformsToProtocol:#protocol(UITextInputTraits)])
{
[(UITextField *)subview setClearButtonMode:UITextFieldViewModeNever];
}
}
Accepted answer does not work on iOS7+, here is the modified version as a Swift extension
extension UIView {
class func removeClearButton(svs: [UIView]) {
for sv in svs {
if let tv = sv as? UITextField where sv.conformsToProtocol(UITextInputTraits) {
tv.clearButtonMode = .Never
return
} else {
UIView.removeClearButton(sv.subviews)
}
}
}
}
Usage
UIView.removeClearButton(searchBar.subviews)
Hers is a category I wrote that does this
Category
#implementation UISearchBar (Additions)
- (void)setClearButtonMode:(UITextFieldViewMode)viewMode {
UITextField *textField = [self findTextFieldInView:self];
[textField setClearButtonMode:viewMode];
}
- (UITextField *)findTextFieldInView:(UIView *)view {
for (UIView *subview in view.subviews) {
if ([subview isKindOfClass:[UITextField class]] ||
[subview.class isSubclassOfClass:[UITextField class]]) {
return (UITextField *)subview;
}
UITextField *textField = [self findTextFieldInView:subview];
if (textField) {
return textField;
}
}
return nil;
}
#end
Usage
[searchBar setClearButtonMode:UITextFieldViewModeWhileEditing];
There's a better way than any of the answers here, and you don't have to use private APIs or traverse subviews to do it.
UISearchBar has a built-in API for doing this:
[UISearchBar setImage:forSearchBarIcon:state]
The SearchBar icon key you want is UISearchBarIconClear, and you want the UIControlStateNormal state. Then give it a clear image for the image, and you're done.
So, it should look like this:
[searchBar setImage:clearImage forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];
For the (x) icon in searchBar. You can use below delegate method.
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
searchBar.showsCancelButton = YES;
}
for (UIView *subview in _search_bar.subviews)
{
NSLog(#"%#",subview.subviews);
for (UIView *subview11 in subview.subviews)
{
if ([subview11 conformsToProtocol:#protocol(UITextInputTraits)])
{
[(UITextField *)subview11 setClearButtonMode:UITextFieldViewModeNever];
}
}
}