After a lot of trouble I was able to add a RETURN button to a numerical key pad.
I want to delete it when introduciing other data into other uitextfields because currently that button appears everytime I use the keyboard, it's part of the keyboard.
Im adding the event handler on KeyBoardDidShow, otherwise it doesnt work,
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardDidShowNotification object:nil];
Then in KeyboarWillShow
- (void)keyboardWillShow:(NSNotification *)note {
// create custom button
NSLog(#"El note es: %#", note);
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setImage:[UIImage imageNamed:#"done.jpg"] forState:UIControlStateNormal];
[doneButton setImage:[UIImage imageNamed:#"done_pressed.jpg"] forState:UIControlStateHighlighted];
[doneButton addTarget:self action:#selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual:[UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
if (!keyboardWindow) return;
// Locate UIKeyboard.
UIView *foundKeyboard = nil;
for (UIView *possibleKeyboard in [keyboardWindow subviews]) {
// iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
if ([[possibleKeyboard description] hasPrefix:#"<UIPeripheralHostView"]) {
possibleKeyboard = [[possibleKeyboard subviews] objectAtIndex:0];
}
if ([[possibleKeyboard description] hasPrefix:#"<UIKeyboard"]) {
foundKeyboard = possibleKeyboard;
break;
}
}
if (foundKeyboard) {
// Add the button to foundKeyboard.
[foundKeyboard addSubview:doneButton];
}
}
The thing is that this creates the button always! Obviously! I would like to create the button only in certains uitextfields, not in all, but how to do that?
The method - (BOOL)textFieldShouldBeginEditing: doesnt execute the first time, only the rest, why? Dont know, but if I was able to know which uitextfield is calling the keyboard my hair would grow again and I'd be slimmer, anyone can help?
textFieldShouldBeginEditing: only fires consistently if each and every one of your text fields have delegates set properly (check your XIB).
And then you can set a tag value in your text fields. You can display the Return button for fields with tag 1 and no Return button for fields with tag 0.
You can try to count the number of subviews inside the keyboard to know how many keys it has. That is a bad hack, but you already have a bad hack to find the keyboard :-)
Also another suggestion:
if (foundKeyboard) {
UIView *doneButton = [foundKeyboard viewWithTag:BUTTON_TAG];
if(numPad){
if(buttonView==nil){
//create doneButton
[foundKeyboard addSubview:doneButton];
}
}else{
[doneButton removeFromSuperview];
}
}
Related
I do some practice with iPhone4S about UITextField on iOS 7.1.2.
Interface:
The interface of the first version is simple, which just has a custom UITextField named MyUITextField and a UIButtom object that use to cancel the search operation. Inside the textField, its leftView property is initially set to a UIButton object, which background image is a magnifying glass. When users tap in the textField, that magnifying glass button will be removed and the leftView property will also set to a new UIButton object, which background image is a inverted triangle. When users tap the triangle button, app will create a new view object.
Main code:
//In this version,the textField's original frame property is set to (10,40,250,30)
//and the main operations are like this:
- (void)viewDidLoad
{
[super viewDidLoad];
self.myTextField.delegate = self;
self.myTextField.leftViewMode = UITextFieldViewModeUnlessEditing;
self.myTextField.leftView = [self creCustomSearchBar];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyBoardWillAppear:)
name:#"UIKeyboardWillShowNotification"
object:nil];
[self.cancleSearchButton addTarget:self
action:#selector(cancleSearch:)
forControlEvents:UIControlEventTouchUpInside];
}
/*when tapping in the textField,keyboard will appear*/
- (void)keyBoardWillAppear:(NSNotification *)notification
{
CGRect newLeftViewIndicatorRect = CGRectMake(20,5,20,20);
UIButton *newLeftViewIndicator = [[UIButton alloc] initWithFrame:newLeftViewIndicatorRect];
NSString *imagePath = [[NSBundle mainBundle] pathForResource:#"searchbar_textfield_down_icon#2x" ofType:#"png"];
[newLeftViewIndicator setBackgroundImage:[UIImage imageWithContentsOfFile:imagePath] forState:UIControlStateNormal];
[newLeftViewIndicator addTarget:self action:#selector(createActuralLeftView:) forControlEvents:UIControlEventTouchUpInside];
self.myTextField.leftView = newLeftViewIndicator;
/*in the second verson need to call */
//[self adjustViewFrame];
[self.cancleSearchButton setTitle:#"取消" forState:UIControlStateNormal];
}
- (void)createActuralLeftView:(UIButton *)leftViewButton
{
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(tapRegionAboveKeyboard:)];
[self.view addGestureRecognizer:tapGesture];
NewLeftView *leftView = [[NewLeftView alloc] initWithFrame:CGRectMake(10, 80, 140, 100)];
leftView.delegate = self;
[self.view addSubview:leftView];
}
- (void)tapRegionAboveKeyboard:(UITapGestureRecognizer *)tapGesture
{
for (UIView *v in self.view.subviews) {
if ([v isKindOfClass:[NewLeftView class]]) {
[v removeFromSuperview];
[self.view removeGestureRecognizer:tapGesture];
return;
}
}
}
//in the second version need to call
- (void)adjustViewFrame
{
[[self.myTextField class] animateWithDuration:0.05 animations:^{
[self.myTextField setFrame:CGRectMake(self.myTextField.frame.origin.x, 40, self.myTextField.frame.size.width, self.myTextField.frame.size.height)];
}];
[[self.cancleSearchButton class] animateWithDuration:0.05 animations:^{
[self.cancleSearchButton setFrame:CGRectMake(self.cancleSearchButton.frame.origin.x, 40, self.cancleSearchButton.frame.size.width, self.cancleSearchButton.bounds.size.height)];
}];
}
In the first version things work well.
But in the second version, I set the textField frame property to (10,260,250,30), so I need to call the adjustViewFrame method in the keyBoardWillAppear: to reposition the textField in case of obscuring by the keyboard.
Here comes the problem: the textField's position is correctly moved to the right place, but when I tap the inverted triangle button, the textField disappeared.
I can't figure out what's going wrong here.
I am trying to keep this UIAlertView up after the presses either of the buttons (1 & 2).
Once i click on the "+" button or the "-" button, I can see the UILabel text increment, then it closes the UIAlertView.
This is what i currently am using:
#pragma Alert View Methods
-(void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
{
[self dismissWithClickedButtonIndex:buttonIndex animated:animated];
}
#pragma count functions
-(void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1 || buttonIndex == 2) {
return;
}
else{
[self dismissWithClickedButtonIndex:buttonIndex animated:YES];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1) {
self.currentCountButtonCount++;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",self.countButtonCount + 1]];
}if (buttonIndex == 2) {
self.currentCountButtonCount--;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",self.countButtonCount - 1]];
}
}
- (IBAction)countClick:(id)sender {
// tallies and keeps current count number
if (!self.currentCountButtonCount)
self.currentCountButtonCount = 0;
NSString *alertMessage = [NSString stringWithFormat:#"%d", self.countButtonCount];
self.countAlert = [[UIAlertView alloc]initWithTitle:#"Count" message:alertMessage delegate:self cancelButtonTitle:#"end" otherButtonTitles:#"+",#"-", nil];
[self.countAlert show];
}
On my last question someone told me to do it custom and this is what im trying now and it still dismisses the UIAlert.
How can i keep it up while the label changes until they touch the end button?
What are you using is default button of AlertView and after click on that button it will automatically dismissed the alertview.
So you have to create your buttons programatically and add that buttons in your alertview like:
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[btn setTitle:#"+" forState:UIControlStateNormal];
[countAlert addSubview:btn ];
on this btn call your method.
So you have to create two custom button with "+" and "-". and add that buttons in AlertView.
-(void)setAlertValue:(id)sender{
switch ([sender tag]) {
case 1:
{
// currentCountButtonCount++;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",++countButtonCount]];
}
break;
case 2:
{
//currentCountButtonCount--;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",--countButtonCount]];
}
break;
default:
break;
}
}
- (IBAction)countClick:(id)sender {
// tallies and keeps current count number
if (!currentCountButtonCount)
currentCountButtonCount = 0;
NSString *alertMessage = [NSString stringWithFormat:#"%d", countButtonCount];
self.countAlert = [[UIAlertView alloc]initWithTitle:#"Count" message:alertMessage delegate:self cancelButtonTitle:#"end" otherButtonTitles:nil, nil];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(10, 50, 40, 20)];
[btn addTarget:self action:#selector(setAlertValue:) forControlEvents:UIControlEventTouchUpInside];
[btn setBackgroundColor:[UIColor greenColor]];
btn.tag = 1;
[btn setTitle:#"+" forState:UIControlStateNormal];
UIButton *btn1 = [[UIButton alloc] initWithFrame:CGRectMake(230, 50, 40, 20)];
[btn1 addTarget:self action:#selector(setAlertValue:) forControlEvents:UIControlEventTouchUpInside];
[btn1 setBackgroundColor:[UIColor redColor]];
btn1.tag = 2;
[btn1 setTitle:#"-" forState:UIControlStateNormal];
[countAlert addSubview:btn];
[countAlert addSubview:btn1];
[self.countAlert show];
}
I don't want to rain in your parade, but if you think that an alert view is the best way to handle an increment/decrement of a variable, I would suggest you to reconsider your design.
UIAlertViews are meant for transient information and simplified decision making. A simple "Are you sure?" is the text-book example of an alert view usage.
From the user stand point, it's much more comforting being able to modify all the attributes in sliders or any other form of permanent input, and then, when sure, hit the confirm button with an alert view (or confirmation screen). Doing it in an Alert view is not only error prone, but counter-intuitive compared in the way that the rest of iOS works.
If you're having trouble on fitting another form of input in your application, please read on how to perform animations and reveal control as they are needed, hiding the input inside an UIAlertView is simply the easiest solution for you, but not the best for the user.
I am new in IOS & I am using IOS 6. I have more than one textfield in my code, one of them uses the Number pad keyboard and I want to add the custom button to it.
I am using this code:
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[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:#"<UIPeripheralHost"] == TRUE)
[keyboard addSubview:doneButton];
}
Selector is called, but the problem is that the [[tempwindow.subviews]count] is 0.
Could anyone help me ?
Thanks in advance.
You can do this by checking following links.
Reference 1
Reference 2
But please do not do this.
Consider this:
what if the layout of the number keypad changes?
what if the colors of the keys change?
what if the implementation of the keyboard changes such that it's no
longer the window at index 1?
what if the implementation of the keyboard and peripheral host change
such that introspecting the description breaks?
what if you're running this on iPad where the keyboard has a totally
different layout?
For me, I am using the following code snippet to add button to the keyboard:
- (void)addHideKeyboardButtonToKeyboard {
// Locate non-UIWindow.
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual:[UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
if (!keyboardWindow) return;
// Locate UIKeyboard.
UIView *foundKeyboard = nil;
for (__strong UIView *possibleKeyboard in [keyboardWindow subviews]) {
// iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
if ([[possibleKeyboard description] hasPrefix:#"<UIPeripheralHostView"]) {
for (__strong UIView *anotherPossibleKeyboard in [possibleKeyboard subviews]) {
if ([[anotherPossibleKeyboard description] hasPrefix:#"<UIKeyboard"]) {
foundKeyboard = possibleKeyboard;
break;
}
}
}
}
if (foundKeyboard) {
[foundKeyboard addSubview:self.keyboardDoneButton];
}
}
I have used following code. Check it.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if(textField==txt1)
{
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(keyboardDidShowOrHide:)
name: UIKeyboardDidShowNotification object:nil];
}
else
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
}
}
- (void) keyboardDidShowOrHide : (id) sender {
// create custom button
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 427, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setBackgroundImage:[UIImage imageNamed:#"doneup.png"] forState:UIControlStateNormal];
[doneButton setBackgroundImage:[UIImage imageNamed:#"donedown.png"] forState:UIControlStateHighlighted];
[doneButton addTarget:self action:#selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
[tempWindow addSubview:doneButton];
}
-(void)doneButton:(id)sender
{
UIButton *btntmp=sender;
[btntmp removeFromSuperview];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
//[self setViewMovedUp:NO];
[txt1 resignFirstResponder];
}
I have a UITableViewCell with UIButton in each cell. When the button is pressed I set its state to highlighted like in this answer:
[self performSelector:#selector(doHighlight:) withObject:[cell.subviews objectAtIndex:2] afterDelay:0.0];
Then I do this:
- (void)doHighlight:(UIButton *)sender {
if (sender.highlighted) {
[sender setHighlighted:NO];
} else {
[sender setHighlighted:YES];
}
}
But the button not only is just not highlighted at all, not speaking about the fact that I should be able to UNhighlight it.
Any ideas on what is wrong?
I ended up using UIButton's selected property. It does not require any delay and it works brilliantly with this type of things:
if (!sender.selected) {
[sender setSelected:YES];
[cell addSubview:hiddenButton];
[self performSelector:#selector(doHighlight:) withObject:sender];
} else {
[sender setSelected:NO];
[self performSelector:#selector(doUnHighlight:) withObject:sender];
}
Here is a possible solution you are looking for. I have modified my answer
UIButton *button=[cell.subviews objectAtIndex:2];
//I am adding these five lines to ensure the different
//states of the button to achieve your highlighted state goal.
UIImage *highlightImage = [UIImage imageNamed:#"highlight.png"];//Also used when button is selected
UIImage *normalImage = [UIImage imageNamed:#"normal.png"];
[button setBackgroundImage:normalImage forState:(UIControlStateHighlighted)];
[button setBackgroundImage:highlightImage forState:(UIControlStateSelected)];
[button setBackgroundImage:normalImage forState:UIControlStateNormal];
[self performSelector:#selector(doHighlight:) withObject:[cell.subviews objectAtIndex:2]];
-(IBAction) doHighlight:(id)sender
{
if ([sender isKindOfClass:[UIButton class]])
{
UIButton *btn=(UIButton*)sender;
if (btn.isSelected) {
[btn setSelected:NO];
}
else
{
[btn setSelected:YES];
}
}
}
My viewWillAppear method call "-(void)doSomething".
- (void)doSomething
{
Y4AppDelegate * delegate = (Y4AppDelegate *)[[UIApplication sharedApplication] delegate];
if(delegate.booSomeValue == 0) {
UIButton * aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setFrame:CGRectMake(20,360,280,40)];
[aButton setTitle:#"Title"
forState:UIControlStateNormal];
[aButton addTarget:self
action:#selector(mySelector)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:aButton];
}
}
It work, but aButton is still visible. What can I do to hide aButton? I have three UIViewController. In third i set delegate.booSomeValue to true. When I come back to previous UIViewController, I call this viewWillAppear but aButton is visible. I want to hide it.
The problem is that you added it once, and when you go back to it, you are not adding a second one, but the first one you added is still there, so you have to remove it.
To do so, you will need first to create a property to store the button, and check if it exists
if ( ... show button condition ... ) {
if (!aButton) {
... create and show button ...
}
}
else {
if (aButton) {
[aButton removeFromSuperview];
aButton = nil;
}
}
Move this code to viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad]
UIButton * aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
aButton.tag = 101;
[aButton setFrame:CGRectMake(20,360,280,40)];
[aButton setTitle:#"Title"
forState:UIControlStateNormal];
[aButton addTarget:self
action:#selector(mySelector)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:aButton];
}
And
- (void)doSomething
{
Y4AppDelegate * delegate = (Y4AppDelegate *)[[UIApplication sharedApplication] delegate];
UIButton * aButton = (UIButton*)[self.view viewWithTag:101];
aButton.hidden = delegate.booSomeValue;
}