****** IMPORTANT*******
Inside the code segements, some code i had was causing the code blocks to mess up and cut out code, so please not that when i write hasPrefix:@"(lessThen)UIKeyboard" the (lessThen) should be replaced by the actual symbol. so like this hasPrefix:@"
***********************
************************************************** *****
* There is a code example a few posts down that has all this code in it *
************************************************** *****
This tutorial will show an example of how to add content to a UIKeyboard by adding a custom button. The following will show you how to add a decimal button to the numeric keyboard so you can enter decimal values without having to use a full keyboard. The key idea to understand here is that although the UIKeyboard is not directly available to us through the current iPhone SDK, we can still reference an instance of the keyboard using its base class.
UIKeyboard is a subclass of UIView. This is handy because it is very easy to add content to a view using code like below:
Code:
[myView addSubview:subview];
This is how we will add a button to our keyboard, by referencing the keyboard and adding a subview.
In my program I only had one keyboard and on text area to use the keyboard, so the following code worked fine for me. This example is not robust enough to handle multiple keyboard and multiple text areas but hopefully it gives you a good idea how things work.
STEP 1: Finding the UIKeyboard
The first thing we have to do is actually get a reference to the UIKeyboard. If your application uses a keyboard, you will find that they keyboard is not actually inside the UIWindow you create in your applicationDelegate, but in a separate UIWindow that is automatically generated. Each iPhone application you create has an array of windows. The example below shows you how to reference an item in your applications array of UIWindows.
Code:
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
The code above works fine if you know what window you want to reference. I am not 100% sure what the max number of windows an application can have is, but in general it is better to write smart code that can automatically find each window, instead of writing working code once and hoping that conditions never change. With that said lets take a look at the following code example. The code blow shows how to iterate through each window in our applications
Code:
UIWindow* tempWindow;
//Check each window in our application
for(int c = 0; c < [[[UIApplication sharedApplication] windows] count]; c ++)
{
//Get a reference of the current window
tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:c];
}
So now that we are able to loop through all of our application windows, we are ready to starting looking for the UIKeyboard. As mentioned before, UIKeyboard is a subclass of UIView. This is helpful because each UIWindow has an array of its subviews. All we have to do now is loop through each subview of the current window. We can do this with a nested for loop. Below is an extended version of the code above that will show you how to iterate through all the subviews in a window.
Code:
UIWindow* tempWindow;
//Check each window in our application
for(int c = 0; c < [[[UIApplication sharedApplication] windows] count]; c ++)
{
//Get a reference of the current window
tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:c];
//Get a reference of the current view
for(int i = 0; i < [tempWindow.subviews count]; i++)
{
}
}
Now we are at the point where we can look for the view that contains the keyboard. There are a couple of ways you can check the content/type of a UIView, in my code I do this by checking the prefix of the view description. Through debugging I found out that a UIKeyboard description starts with the text "
Code:
UIWindow* tempWindow;
//Because we cant get access to the UIKeyboard throught the SDK we will just use UIView.
//UIKeyboard is a subclass of UIView anyways
UIView* keyboard;
//Check each window in our application
for(int c = 0; c < [[[UIApplication sharedApplication] windows] count]; c ++)
{
//Get a reference of the current window
tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:c];
//Get a reference of the current view
for(int i = 0; i < [tempWindow.subviews count]; i++)
{
keyboard = [tempWindow.subviews objectAtIndex:i];
if([[keyboard description] hasPrefix:@"(lessThen)UIKeyboard"] == YES)
{
//If we get to this point, then our UIView "keyboard" is referencing our keyboard.
}
}
}
So there you have it. Using a couple simple loops, we can reference our keyboard. Next, we need to add content.
STEP 2: Adding a custom button to the keyboard.
So now that we have a UIView reference of the keyboard. Adding a custom button is actually really simple. All we need to do is add a subview to the keyboard view. Below is the code that I use in my application to add a peroid to my numeric keypad keyboard. Keep in mind that we are referencing the keyboard directly, so position 0, 0 is not the top left of your screen, rather the top left of the keyboard. Remeber that the variable keyboard is the UIView we found in step1.
Code:
dot = [UIButton buttonWithType:UIButtonTypeCustom];
dot.frame = CGRectMake(0, 163, 106, 53);
[dot setImage:[UIImage imageNamed:@"period.gif"] forState:UIControlStateNormal];
[dot setImage:[UIImage imageNamed:@"period2.gif"] forState:UIControlStateHighlighted];
[keyboard addSubview:dot];
[dot addTarget:self action:@selector(addDot:) forControlEvents:UIControlEventTouchUpInside];
The code is just as simple as adding any other button. The button has 2 images, one for when its not clicked and one for when it is. When the button is pressed I want to update my textbox by appending a '.' which is show in the code below.
Code:
gameOptions.size.text = [gameOptions.size.text stringByAppendingString:@"."];
Now this was a little bit more difficult in my case then what I showed, that is because where I add the button, and where the buttons textarea target are in 2 different classes. But there are plenty of examples of calling methods from other classes on these forums so i wont get into that. If I can figure out how I will include the 2 images I used for this button in this tutorial so that anyone who wants to use them can.
STEP 3: Where does all this code go?
So here comes the point where I tell you that I am not 100% sure that what I am about to write is the best way to do things. There are most likely better places to add buttons to your text boxes, I just did it the following way. It will work fine, but you are more then welcome/encouraged to find a better solution.
Using notifications we can easily find out when a keyboard is about to be shown and attach a method to that event. Because a keyboard cannot be show without this method being called, I figured it would be a good place to reference the keyboard. This way we dont waste any time creating a custom keyboard if the user never uses a textarea.
I put all this code into the app delegate. I figured it was a good spot because it will live as long as my application does. Below is the first thing you need to do. As mention before, I wanted to listen for the notification of when the keyboard will be shown. The following line of code shows how to do this.
Code:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
As seen above, i just told my application that each time the keyboard is shown, I want to call the method keyboardWillShow. This method is where all the code from step 1 and 2 is held. As mentioned this method sits inside of my app delegate. The follow code is what my appDelegate looks like. As you can see I have a function keyboardWillShow that handles events due the the code above. Each time the keyboard is to be shown we will add our button. The way i have done things, if you do not do this each time, the button will not persist. I hope this all makes sense.
--- My post is to long, tutorial continues below ---