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];
}
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 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;
}
I have added a button to my annotation view, and it appears correctly. When the button is tapped, I want a call to be made, but when I tap the button, it doesn't respond (the button doesn't even highlight). It seems that the button doesn't receive the touch event, but I don't know why.
Here is my code in customAnnotationView.m
- (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
{
NSLog(#"initWithAnnotation start");
//initialze the view
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
if (self != nil)
{
CGRect frame = self.frame;
frame.size = CGSizeMake(60.0, 85.0);
self.frame = frame;
self.backgroundColor = [UIColor clearColor];
self.centerOffset = CGPointMake(30.0, 42.0);
}
//this has nothing to do with my question
self.title=[[[NSString alloc] init] autorelease];
self.description=[[[NSString alloc] init] autorelease];
self.phoneNumber=[[[NSString alloc] init] autorelease];
customAnnotation * tempCust = (customAnnotation *)annotation;
self.title=annotation.title;
self.description=tempCust.description;
self.phoneNumber=tempCust.phoneNumber;
//here is the question button
self.userInteractionEnabled=YES;
self.exclusiveTouch=NO;
UIButton *button=[UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"Call" forState:UIControlStateNormal];
//decide the button's position
CGRect rect=button.frame;
rect.origin.x=15;
rect.origin.y=47;
rect.size.width=40;
rect.size.height=20;
button.frame=rect;
[self addSubview:button];
[button becomeFirstResponder];
[button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
NSLog(#"initWithAnnotation finished");
return self;
}
//action method
-(void)buttonClicked:(id)sender{
NSString *callNumber=[[[NSString alloc] initWithFormat:#"tel://%#",self.phoneNumber] autorelease];
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:callNumber]];
}
Why doesn't the button work?
self.rightCalloutAccessoryView = button;
Use the above instead of [self addSubview:button];
Hope this help's you
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];
}
}