0

At the moment I'm trying to make a Hangman app. I've got the main functionality working but I want a way to display which letters a user has already guessed. I would like to do this by hiding these letters from the keyboard (which is the standard keyboard activated by a textfield.) I've read about adding buttons to the keyboard (for example this tutorial: http://www.neoos.ch/blog/37-uikeyboardtypenumberpad-and-the-missing-return-key) everywhere but not deleting/disabling existing buttons. Anyone knows a solution? I can't seem to figure it out.

Thanks

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Jaap Wijnen
  • 417
  • 2
  • 6
  • 12
  • 1
    There is no API to do this. You must create your own custom keyboard (and good luck supporting that with all of the international keyboards). – rmaddy May 30 '14 at 16:25
  • the referred article is about 5 years old, it is just a bit outdated... but you can implement an own keyboard anytime. – holex May 30 '14 at 16:27
  • possible duplicate of [How to create a custom keyboard](http://stackoverflow.com/questions/4643167/how-to-create-a-custom-keyboard) – brandonscript May 30 '14 at 16:28
  • As per rmaddy's comment, the only way to do this is by creating your own keyboard using the answers in remus' comment. – David Berry May 30 '14 at 20:58

1 Answers1

4

There is no public API to do this. So as was already advised in the comments:you should better implement your own keyboard as UIView subclass with methods to change its behaviour in the way you need (hide buttons, add new buttons, etc.). There are a lot of tutorials that will teach you how you can do this. Apple also advice to do this here. You should also handle all the localisation support in your own keyboard class if you plan to internationalize your application. So all this stuff will be pretty hard to implement. If you don't want to do this then the only way is to use some dirty views manipulations and access the keyboard as a UIView object and then do with it whatever you want. BUT it is a very bad way, because it uses private view hierarchy and can be broken when Apple will make some changes in it like it was with UITableViewCell views hierarchy in iOS 7. And also it is a very limited way. At first you have to be sure that keyboard has already shown to the user or you will have a crash (because windows array will contain only one UIWindow). To do this just add a notification observer:

NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(keyboardShowed)
  name:UIKeyboardDidShowNotification object:nil];

Then in keyboardShowed method (valid for iOS versions in [4.0,7.1] interval):

-(void)keyboardShowed
 {
UIWindow* window = [[[UIApplication sharedApplication] windows]
                    objectAtIndex:1];
for(UIView* view in window.subviews)
{
    if([[view description] hasPrefix:@"<UIPeripheralHostView"])
    {
        //This view is a keyboard view
        // you can iterate its subviews
        //and make buttons hidden
        NSLog(@"Keyboard Shown: %@", view);
    }
  }
}

Then when you actually get the reference to keyboard view you should trace it with subviews property down all the hierarchy (UIKeyboardImpl,UIKeyboardLayoutStar and etc.) while you will actually get views like buttons.

But as I said it is a bad way. Because private view hierarchy is huge with a lot of subviews. So you should handle your functionality in some other way. Why just don't allow the user to enter letters which he has already guessed in your game, and show him some sort of alert message?

Oleksandr Karaberov
  • 12,573
  • 10
  • 43
  • 70
  • Thanks for the fast reply I have tried iterating through it's subviews in this way but can't find references to individual buttons. I know it's a bad way but I'm making the app for a course I'm taking at the moment and I'm not planning on actually releasing it so I'm not really focusing on the future but thanks for the advice! Any ideas on the subviews and how to hide for example the letter A from the keyboard? Thanks! – Jaap Wijnen May 30 '14 at 17:20
  • @JaapWijnen Did you see my edits? I updated the answer. May be this will help – Oleksandr Karaberov May 30 '14 at 17:22
  • Thanks! I did find some interesting things with your edits. One question left how do i delete or disable a certain subview when I find the correct one? – Jaap Wijnen May 30 '14 at 18:28
  • @JaapWijnen There are a couple of ways. As i said it is a dirty hack, so it requires a large research effort. You should look for uibuttons subclasses in those subviews and if you will find them just set `userInteractionEnabled` to NO. But i strongly suspect keyboard buttons are not usual buttons. It may be just custom UIViews or image views. If so the only possible waybis to set `hidden` property to YES. This will comletely hide the view. You should experiment with this. But as I said in the original answer there are other more correct ways to implement this functionality – Oleksandr Karaberov May 30 '14 at 19:12
  • I have managed to find the following: keyboard contains two subviews UIKBInputBackdropView and UIKeyboardAutomatic `UIKInputBackdropView contains: UIKBBackdropView contains: _UIBackdropEffectView UIView 4x UIKeyboardAutomatic contains: UIkeyboardImpl contains: UIKeyboardLayoutStar contains: UIKBBackgroundView contains: UIImageView UIKBKeyplaneView contains: UIKBSplitImageView contains: UIKBSplitImageView contains: ImageView UIKBSplitImageView contains: ImageView UIKBKeyView 5x UIKBDimmingView` – Jaap Wijnen May 30 '14 at 19:13
  • I hoped that would turn out differently... I hope you can make some sense out of it – Jaap Wijnen May 30 '14 at 19:15
  • Thanks a lot only thing I wanted to add to my last post was that indeed the buttons like the spacebar done button and shift (All buttons except the normal letters are contained in a UIKBKeyView. The letters are grouped all together in one ImageView :( – Jaap Wijnen May 30 '14 at 19:25