Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

HOWTO: Customize UIKeyboard

keyboardcowboykeyboardcowboy Posts: 62Tutorial Authors, Registered Users
edited January 2012 in iPhone SDK Development
So for my application I needed to add a button to the number pad keyboard because I wanted users to be able to enter decimal values but the standard button keyboard doesnt include the decimal. And using a full keyboard has a lot of wasted keys that I had to restrict the user from hitting.

Then I came across this post that discussed the issue somewhat.

http://www.iphonedevsdk.com/forum/iphone-sdk-development/6275-add-toolbar-top-keyboard.html

I wanted to elaborate on that post to show how I was able to actually access the view of the keyboard to add my own buttons.

Step 1: Follow the instructions in the above post to handle the messages sent when the the keyboard is going to be show/hidden. This will help you understand a little more about how the keyboard works.

For my use I didnt really need to know the information regarding position of the keyboard and all that, but it was handy to know when it is being show.

Step 2: Check out the code below that actually gets you a reference to the UIKeyboard view (UIView) which will allow you to add subviews.
//The UIWindow that contains the keyboard view - It some situations it will be better to actually
	//iterate through each window to figure out where the keyboard is, but In my applications case
	//I know that the second window has the keyboard so I just reference it directly
	UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
	
	//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;

	//Iterate though each view inside of the selected Window
	for(int i = 0; i < [tempWindow.subviews count]; i++)
	{
		//Get a reference of the current view 
		keyboard = [tempWindow.subviews objectAtIndex:i];
		
		//Check to see if the className of the view we have referenced is "UIKeyboard" if so then we found
		//the keyboard view that we were looking for
		if([[keyboard className] isEqualToString:@"UIKeyboard"] == YES)
		{
			//Keyboard is now a UIView reference to the UIKeyboard we want. From here we can add a subview
			//to th keyboard like a new button
			
			//Do what ever you want to do to your keyboard here...
		}
	}

I put the above code inside of the appDelegate into a method that I call the first time that the user shows the textbox (figured that out using the didShow method in step1).

Im not much of a tutorial writter, but hopefully that will shine some light on how to add custom items to your keyboards :)
Post edited by keyboardcowboy on

Replies

  • keyboardcowboykeyboardcowboy Posts: 62Tutorial Authors, Registered Users
    edited November 2008
    UPDATE:

    Apparently className does not work with the 2.1 firmware or in all conditions so as per the article linked above I would recomend a change in the code i provided.
    if([[keyboard className] isEqualToString:@"UIKeyboard"] == YES)
    

    that if statement should change. Instead of using [keyboard className] I used the following line of code
    if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
    
  • ChriBChriB Posts: 154Registered Users
    edited November 2008
    Awesome, this will come in handy, thank you! :)
  • rames44rames44 Posts: 365Tutorial Authors, Registered Users @ @
    edited November 2008
    Great post. You might consider reposting this over in the Tutorials form so that it doesn't eventually get lost in the mist here...
    For a little fun, check out my <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=298866985&mt=8" target="_blank">Biorhythms</a> app
  • keyboardcowboykeyboardcowboy Posts: 62Tutorial Authors, Registered Users
    edited November 2008
    Thanks for the good responses. When I get some time I will write a proper tutorial with images and put it in the tutorial section. Just trying to finished up my first app for now :)
  • ks bobks bob Posts: 4New Users
    edited December 2008
    I have not used your technique, but I think the following is safer using isKindOfClass. It allows my code to detect my IB changes "cleanly" when I forget to make all the code changes.

    #define TAG_MYBUTTON (1234) /* Set the tag in IB */
    .
    .
    assert([[self viewWithTag:TAG_MYBUTTON] isKindOfClass:[UIButton class]]);
    UIButton *buttonMyButton = (UIButton*) [self viewWithTag:TAG_MYBUTTON];
    assert(buttonMyButton);

    so, extending to your example:

    if( [keyboard isKindOfClass: [UIKeyboard class]] ) {
    // ... use the keyboard
    }

    Give it a try and some thought, you might find it preferable.

    -m2c
  • TEEKAYTEEKAY Posts: 4New Users
    edited June 2009
    Can this be used in anyway to make the keyboard transparent?
  • DutchDutch Posts: 884Registered Users
    edited June 2009
    TEEKAY wrote: »
    Can this be used in anyway to make the keyboard transparent?

    This is a function of the TextField/TextView.
    [myTextView setKeyboardAppearance:UIKeyboardAppearanceAlert];
    
  • bugnotebugnote Posts: 183Registered Users
    edited June 2009
    thanks for all the above info, its set me on my way to adding a decimal point in the number pad.

    one thing that's still puzzling me though. If I have the keyboard set to emoji,(by this I mean that the last view the keyboard was showing before being dismissed was the emoji one) and I pop my viewController that shows the keyboard with added decimal point subview, the keyboard that is shown is the emoji one? I have to go into another view and change it, as the decimal place subview hides the international keyboard symbol.

    any ideas on how I would tailor this line:
    if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)

    to show the number pad only?

    many thanks

    Nik
    <b><a href="http://www.burnsoft.co.uk" target="_blank">Burnsoft Ltd.</a></b> Apps for your iOS device.
  • bugnotebugnote Posts: 183Registered Users
    edited June 2009
    doh, is it as simple as changing it to:

    if([[keyboard description] hasPrefix:@"<UIKeyboardTypeNumberPad"] == YES)


    not as my mac during the day, so doing my usual of asking before I've really thought it through ;-)

    cheers

    Nik
    <b><a href="http://www.burnsoft.co.uk" target="_blank">Burnsoft Ltd.</a></b> Apps for your iOS device.
  • mmilommilo Posts: 30Registered Users
    edited June 2009
    bugnote wrote: »
    doh, is it as simple as changing it to:

    if([[keyboard description] hasPrefix:@"<UIKeyboardTypeNumberPad"] == YES)


    not as my mac during the day, so doing my usual of asking before I've really thought it through ;-)

    cheers

    Nik

    For starters I'm using [keyboard class], it'll return the same thing.

    For me, it seems that no matter what type of keyboardType is being used, it will always return UIKeyboard.

    I can't seem to find a way to distinguish between what kind of keyboard is currently being used - anyone know something that I don't?

    Thanks!
  • narutnarut Posts: 43Registered Users
    edited July 2009
    mmilo wrote: »
    For starters I'm using [keyboard class], it'll return the same thing.

    For me, it seems that no matter what type of keyboardType is being used, it will always return UIKeyboard.

    I can't seem to find a way to distinguish between what kind of keyboard is currently being used - anyone know something that I don't?

    Thanks!
    Same here. [keyboard description] always reture "<UIKeyboard: ..." , no matter what type of key it is.
  • mhorbulmhorbul Posts: 2New Users
    edited August 2009
    The custom button does not produce the standard click. Is there a way to use the standard sound or I have to create my own click.caf and play it when the custom button is clicked ?
  • mhorbulmhorbul Posts: 2New Users
    edited August 2009
    mhorbul wrote: »
    The custom button does not produce the standard click. Is there a way to use the standard sound or I have to create my own click.caf and play it when the custom button is clicked ?

    I have figured out how to do that. I grabbed the default sound from the iphone. It's Tack.caf. And created the system sound which is played when the button is clicked.
    - (void)createSystemClickSound {
    	CFBundleRef mainBundle;
    	mainBundle = CFBundleGetMainBundle ();
    	soundFileURLRef  =	CFBundleCopyResourceURL (mainBundle, CFSTR ("Tock"), CFSTR ("caf"), NULL);
    	AudioServicesCreateSystemSoundID (soundFileURLRef, &soundFileObject);
    }
    
    - (void)buildButton {
    	self.periodButton = [UIButton buttonWithType:UIButtonTypeCustom];
    	self.periodButton.adjustsImageWhenHighlighted = NO;
    	[self.periodButton setImage:[UIImage imageNamed:@"periodButtonUp.png"] forState:UIControlStateNormal];
    	[self.periodButton setImage:[UIImage imageNamed:@"periodButtonDown.png"] forState:UIControlStateHighlighted];
    	[self.periodButton addTarget:self action:@selector(periodButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    	[self.periodButton addTarget:self action:@selector(playClickSound:) forControlEvents:UIControlEventTouchDown];
    	self.periodButton.frame = CGRectMake(0, 163, 105, 53);
            [self createSystemClickSound];
    }
    
    // play system click sound created before
    - (void)playClickSound:(id)sender {
    	AudioServicesPlaySystemSound (self.soundFileObject);
    }
    
    - (void)periodButtonClicked:(id)sender {
    // do whatever you want when the button is pressed
    }
    
  • oscarmkoscarmk Posts: 2New Users
    edited December 2009
    This works great thank you for your help =).

    Allthough you might want to add this in the if else clause...

    //Also check if button has not already been added otherwise it will be added over and over again each time you switch edits.
    if (numberPadShowing && [keyboard viewWithTag:123] == nil)

    //Only remove if the number pad is not showing, otherwise it will switch between adding it and removing it with every begin edit.
    else if (!numberPadShowing)
    {

    for (UIView *v in [keyboard subviews]){
    if ([v tag]==123)
    [v removeFromSuperview];
    }
    }

    The reason the other code works is because the foreach loop will still remove every single subview that was added. However this consumes resources and time.

    Hope this helps =)
  • scotopiascotopia Posts: 2,074Registered Users
    edited September 2010
    Hey All, I know I'm a little late to the party on this but I have two quick questions:

    1) I've heard that some methods of messing with the keyboard will get your app rejected; is this one kosher?

    2) Do any of you have a sample project of a custom keyboard set up somewhere? Saving time is always good ;) Thanks!
    <div align="center"><br />
    <br />
    <a href="http://bit.ly/c4r7uo" target="_blank">omegasoftIconBanner.png</a><br />
    <br />
    <a href="http://bit.ly/9EGiHD" target="_blank">Aura Trainer</a> | <a href="http://bi
  • maxamundomaxamundo Posts: 1New Users
    edited January 2012
    I just wanted to get rid of the keyboard without pressing [search]. So I found it easier to add a gesture tap recogniser to the view behind the search bar.
    This seems to be what most other apps do. Don't know if there are any catches to doing it this way!
    //link Sent actions to gesture tap recogniser in IB
    - (IBAction)tapGesture: (id)sender {
    NSLog(@"tapGesture");
    if (self.userSearchBar != nil){
    [self.userSearchBar resignFirstResponder];
    }
    }
    // add UISearchBarDelegate to UIViewController
    //add to UIViewCnt?.h IBOutlet UISearchBar *userSearchBar;
    //@property (strong, nonatomic) IBOutlet UISearchBar *userSearchBar;

    - (void) searchBarTextDidBeginEditing: (UISearchBar *)searchBar{
    self.userSearchBar = searchBar;
    NSLog(@"search begin edit");
    }
    - (void)searchBarSearchButtonClicked: (UISearchBar *)searchBar{
    [searchBar resignFirstResponder];
    self.userSearchBar = searchBar;
    NSString *searchFor = self.userSearchBar.text;
    NSLog(@"user searched %@",searchFor);
    self.userSearchBar = nil;
    }
  • OwaisOwais Posts: 8New Users
    edited January 2012
    maxamundo wrote: »
    I just wanted to get rid of the keyboard without pressing [search]. So I found it easier to add a gesture tap recogniser to the view behind the search bar.
    This seems to be what most other apps do. Don't know if there are any catches to doing it this way!
    //link Sent actions to gesture tap recogniser in IB
    - (IBAction)tapGesture: (id)sender {
    NSLog(@"tapGesture");
    if (self.userSearchBar != nil){
    [self.userSearchBar resignFirstResponder];
    }
    }
    // add UISearchBarDelegate to UIViewController
    //add to UIViewCnt?.h IBOutlet UISearchBar *userSearchBar;
    //@property (strong, nonatomic) IBOutlet UISearchBar *userSearchBar;

    - (void) searchBarTextDidBeginEditing: (UISearchBar *)searchBar{
    self.userSearchBar = searchBar;
    NSLog(@"search begin edit");
    }
    - (void)searchBarSearchButtonClicked: (UISearchBar *)searchBar{
    [searchBar resignFirstResponder];
    self.userSearchBar = searchBar;
    NSString *searchFor = self.userSearchBar.text;
    NSLog(@"user searched %@",searchFor);
    self.userSearchBar = nil;
    }



    Can any one help me how to play play radio in BAckground..
    Thankx IN advance
Sign In or Register to comment.