Display iPhone OS Keyboard - Solved
by Michael Perry · in iTorque 2D · 02/22/2009 (12:08 pm) · 60 replies
Hey everyone. So, while working with Ecliptic to get the camera/screenshot functionality of an iPhone into iTGB, I had to figure out how to send a message from iTGB to the iPhone SDK.
This is opposite of how input works, as the iPhone SDK detects a touch, creates a TGB mouse event, and sends that to the TGB system.
Fortunately, I have an iTGE demo that does just that! When the user clicks on a text edit control, the iPhone OS keyboard pops up. I had to start digging through the code, and found wrapper that performs this functionality.
This is opposite of how input works, as the iPhone SDK detects a touch, creates a TGB mouse event, and sends that to the TGB system.
Fortunately, I have an iTGE demo that does just that! When the user clicks on a text edit control, the iPhone OS keyboard pops up. I had to start digging through the code, and found wrapper that performs this functionality.
About the author
Programmer.
#42
08/06/2009 (9:22 am)
You can easily customize that 'ugly screen' using interface builder in xcode - adding images, removing cancel button, adding new buttons, etc.
#43
I'm working on a solution that just shows the keyboard and directs it's input to your existing GuiTextEditCtrl . It's 99% working right now, just missing the cursor visibility.
08/06/2009 (9:36 am)
Yea but that's not an integrated solution. I have to build 1 panel for the user to see before they edit, and then have some popup they see when they click on an edit bar. I honestly can't believe that anyone would use the existing solution in a real production game.I'm working on a solution that just shows the keyboard and directs it's input to your existing GuiTextEditCtrl . It's 99% working right now, just missing the cursor visibility.
#44
08/07/2009 (1:58 am)
Quote:I'm working on a solutionIt would be great if you could share your progress/solution :)
#45
08/07/2009 (5:44 am)
Yeah, we didn't use the text edit control to open up the xib file - instead we called a console function that opened up the xib file..so as soon as we wanted user input, the keyboard would pop up instead of requiring the user to click "Edit" or anything along those lines.
#46
What developers are likely to want is the ability to input values into iTGB using the iPhone keyboard and maintaining their current user interaction screens. Though there are definitely pluses and minus to this. I'm on the fence again whether I should redesign certain screens to use iPhone's view and static images in order to take advantage of the rich editor fields.
Below is how I integrated the keyboard into a UI textedit control. I'm not sure if I pasted everything below, so let me know if I missed something. This is for working with 1.2 of iTGB.
BTW this is a bit advanced for most people but here are the instructions.
1. Add the textentry.xib to your project.
2. Edit the textentry.xib and delete the confirm/cancel buttons and make every control in the xib 100% transparent.
3. in platformiPhone/ modify TextEntry_wrapper.h and TextEntry_wrapper.cpp:
4. Modify TextEntryController.h/.mm
5. Open interface builder and bind the new event listeners.
Click on the TextField. In the inspector on the second tab bind the top three events to the appropriate action listener (drag from event circle to the TextEntryController and select the correct popup).
Essentially what this all does is when you click on the gui text control is popup the keyboard and an invisible set of controls. When you type in the keyboard it sets the value of the iTGB guitextcontrol to the value of the invisible textedit control. This gives you the appearance of complete integration of the keyboard with the torque GuiTextEditCtrl.
This could be greatly improved to have it layer the control over the GuiTextEditCtrl and set it's colors are the same or similar to use the advanced iphone editor abilities. I however didn't want to spend that much time on it and kept it with minimal integration.
*next post*
08/07/2009 (7:32 am)
I was a little harsh when I first commented on it, I was just disappointed that I'd have to go and finish the integration. Popping up a new View and then utilizing standard iphone views for obtaining input is rather trivial, so I didn't consider that use of the keyboard in iTGB. Rather it was just how to popup a view, get a value and then use that within torque which is not terribly useful for a game. What developers are likely to want is the ability to input values into iTGB using the iPhone keyboard and maintaining their current user interaction screens. Though there are definitely pluses and minus to this. I'm on the fence again whether I should redesign certain screens to use iPhone's view and static images in order to take advantage of the rich editor fields.
Below is how I integrated the keyboard into a UI textedit control. I'm not sure if I pasted everything below, so let me know if I missed something. This is for working with 1.2 of iTGB.
BTW this is a bit advanced for most people but here are the instructions.
1. Add the textentry.xib to your project.
2. Edit the textentry.xib and delete the confirm/cancel buttons and make every control in the xib 100% transparent.
3. in platformiPhone/ modify TextEntry_wrapper.h and TextEntry_wrapper.cpp:
4. Modify TextEntryController.h/.mm
5. Open interface builder and bind the new event listeners.
Click on the TextField. In the inspector on the second tab bind the top three events to the appropriate action listener (drag from event circle to the TextEntryController and select the correct popup).
Essentially what this all does is when you click on the gui text control is popup the keyboard and an invisible set of controls. When you type in the keyboard it sets the value of the iTGB guitextcontrol to the value of the invisible textedit control. This gives you the appearance of complete integration of the keyboard with the torque GuiTextEditCtrl.
This could be greatly improved to have it layer the control over the GuiTextEditCtrl and set it's colors are the same or similar to use the advanced iphone editor abilities. I however didn't want to spend that much time on it and kept it with minimal integration.
*next post*
#47
In TextEntry.mm comment out the section and make the other minor changes I made below
*next post*
08/07/2009 (7:33 am)
/*
* TextEntry.h
* TGE
*
* Created by James Touton on 11/19/08.
* Copyright 2008 Pick Up And Play. All rights reserved.
*
*/
#ifndef TEXTENTRY_INCLUDED
#define TEXTENTRY_INCLUDED
#include <core/stringBuffer.h>
#include "guiTextEditCtrl.h"
namespace TextEntry
{
// Returns false if the user cancels.
// text [in/out]: The contents of the text entry field. The text entry field is initialized
// with the value of the StringBuffer. On exit, if the function returns true, the StringBuffer
// contains the text entered by the user; otherwise, the StringBuffer is unchanged.
bool getUserText(GuiTextEditCtrl* ctrl);
}
#endifIn TextEntry.mm comment out the section and make the other minor changes I made below
/*
* TextEntry.mm
* TGE
*
* Created by James Touton on 11/19/08.
* Copyright 2008 Pick Up And Play. All rights reserved.
*
*/
#include "platformiPhone/TextEntry_Wrapper.h"
#include "TextEntryController.h"
bool TextEntry::getUserText(GuiTextEditCtrl* ctrl)
{
TextEntryController* controller = [[TextEntryController alloc] initWithNibName: @"TextEntry" bundle: nil];
UIWindow* window = [UIApplication sharedApplication].keyWindow;
[controller loadView];
controller.textControl = ctrl;
controller.view.alpha = 0.0f;
[window addSubview: controller.view];
// For some reason, autorotation doesn't always happen -- check for this here:
UIApplication* app = [UIApplication sharedApplication];
CGAffineTransform viewTransform = controller.view.transform;
if ((app.statusBarOrientation != UIInterfaceOrientationPortrait) && (memcmp(&viewTransform, &CGAffineTransformIdentity, sizeof(CGAffineTransform)) == 0)) {
CGRect bounds = controller.view.bounds;
switch (app.statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
controller.view.bounds = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.height, bounds.size.width);
controller.view.transform = CGAffineTransformMakeRotation((3 * M_PI) / 2);
break;
case UIInterfaceOrientationLandscapeRight:
controller.view.bounds = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.height, bounds.size.width);
controller.view.transform = CGAffineTransformMakeRotation(M_PI / 2);
break;
case UIInterfaceOrientationPortraitUpsideDown:
controller.view.transform = CGAffineTransformMakeRotation(M_PI);
break;
}
}
[UIView beginAnimations: nil context: nil];
controller.view.alpha = 1.0f;
[UIView commitAnimations];
[controller.textField becomeFirstResponder];
/*
while (!controller.finished) {
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]];
}
[controller.view removeFromSuperview];
bool userCanceled = controller.userCanceled;
/*if (!userCanceled) {
text.set(reinterpret_cast<const UTF16*>([controller.textField.text cStringUsingEncoding: NSUTF16LittleEndianStringEncoding]));
}
[controller release];
return !userCanceled;
*/
return true;
}*next post*
#48
08/07/2009 (7:34 am)
next in classes modify the TextEntryController.h and .mm//
// TextEntryController.h
// TGE
//
// Created by James Touton on 11/19/08.
// Copyright 2008 Pick Up And Play. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "guiTextEditCtrl.h"
@interface TextEntryController : UIViewController
{
UITextField* textField;
GuiTextEditCtrl* textControl;
}
@property(nonatomic, readonly) IBOutlet UITextField* textField;
@property(nonatomic) GuiTextEditCtrl* textControl;
- (IBAction)onEndEditing: (id)sender;
- (IBAction)onBeginEditing:(id) sender;
- (IBAction)onValueChanged: (id) sender;
@end//
// TextEntryController.mm
// TGE
//
// Created by James Touton on 11/19/08.
// Copyright 2008 Pick Up And Play. All rights reserved.
//
#import "TextEntryController.h"
@implementation TextEntryController
@synthesize textField;
@synthesize textControl;
- (void)dealloc
{
[textField release];
[super dealloc];
}
- (IBAction)onEndEditing: (id)sender
{
[self.view removeFromSuperview];
[self release];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return YES;
}
- (IBAction) onBeginEditing:(id) sender {
char buffer[GuiTextEditCtrl::MAX_STRING_LENGTH+1];
textControl->getText(buffer);
textControl->setCursorOn(true);
textControl->setFirstResponder();
textField.text = [NSString stringWithUTF8String:buffer];
}
- (IBAction) onValueChanged:(id) sender
{
const char* text = [textField.text UTF8String];
textControl->setFirstResponder();
textControl->setCursorOn(true);
textControl->setText(text);
}
@end
#49
Was planning on doing the same (same reasons, the existing solution was not a usable solution imo!) but you beat me to it :)
I'll give this a whirl later if I find some time, and give feedback/changes I make here if I think people will find them useful. If I don't find time it'll have to wait until Monday.
08/07/2009 (9:15 am)
*Thumbs up*Was planning on doing the same (same reasons, the existing solution was not a usable solution imo!) but you beat me to it :)
I'll give this a whirl later if I find some time, and give feedback/changes I make here if I think people will find them useful. If I don't find time it'll have to wait until Monday.
#50
08/07/2009 (11:29 am)
BTW I should add I couldn't get the cursor to work except when the GuiTextCtrl was empty. Not sure why and didn't want to invest anymore time on it. I'm trying really hard to get my game finished this week and sent to my friends for final beta testing.
#52
I don't think I completely followed you on the interface builder to bind event listeners. can you post your textentry.xib ?
Last thing. how do you use it? I created a guiCtrl with a guiTextEditCtrl and setContent to it, but I still don't see the keyboard. What am I missing here?
10/07/2009 (1:04 pm)
Bret, I was able to make all the changes you've posted and compile them.I don't think I completely followed you on the interface builder to bind event listeners. can you post your textentry.xib ?
Last thing. how do you use it? I created a guiCtrl with a guiTextEditCtrl and setContent to it, but I still don't see the keyboard. What am I missing here?
#53
10/07/2009 (2:15 pm)
I'll post the xib and more details when I get home.
#54
www.kingdomofgorath.com/temp/TextEntry.xib.zip
In script I created the GUI Text control using the following code ( I think I layered it on top of an image which I named PlayerNameClass in the editor).
The trick is to resize the XIB file such that the completely clear text entry is overload with your gui text control, that way when they think they are clicking on the gui text entry control they actually click on the iphone entry control which causes the keyboard to popup.
It's very hackish but I needed something quick and dirty as I only had 1 place you needed to do any text entry. It's a crappy way to do it if you have a lot of places to do text entry.
10/07/2009 (10:14 pm)
Below is my TextEdit.xib file. www.kingdomofgorath.com/temp/TextEntry.xib.zip
In script I created the GUI Text control using the following code ( I think I layered it on top of an image which I named PlayerNameClass in the editor).
The trick is to resize the XIB file such that the completely clear text entry is overload with your gui text control, that way when they think they are clicking on the gui text entry control they actually click on the iphone entry control which causes the keyboard to popup.
It's very hackish but I needed something quick and dirty as I only had 1 place you needed to do any text entry. It's a crappy way to do it if you have a lot of places to do text entry.
function PlayerNameClass::onLevelLoaded(%this) {
$guiEditName =
new GuiTextEditCtrl(startServerName) {
profile = "NameTextEditProfile";
horizSizing = "right";
vertSizing = "bottom";
position = "0 0";
extent = "130 25";
minExtent = "8 2";
visible = "1";
variable = "PlayerNameClass::Name";
maxLength = "64";
historySize = "0";
password = "0";
tabComplete = "0";
sinkAllKeyEvents = "0";
};
%this.attachgui( $guiEditName, SceneWindow2D );
$PlayerNameClass::Name = "";
}I then had a profile created at the top of the same file with:if(!isObject(NameTextEditProfile)) new GuiControlProfile (NameTextEditProfile)
{
opaque = true;
fillColor = "0 0 0";
fillColorHL = "0 0 0";
border = -2;
bitmap = "./images/textEdit";
borderColor = "40 40 40 100";
fontColor = "255 255 255";
fontColorHL = "255 255 255";
fontColorNA = "255 255 255";
textOffset = "4 2";
autoSizeWidth = false;
autoSizeHeight = true;
tab = true;
canKeyFocus = true;
cursorColor = "255 255 255";
};
#55
I'm not sure if I know how to add the textEntry.xib . I've overwritten the one in my project tree /ui/textEntry.xib (I'm using 1.3) and then I've added the whole directory into my project as reference. Other than that, I've made all the changes that you've made to the files above and compiled with no errors.
10/08/2009 (1:45 am)
Bret, I think I still miss something. I did the same thing with a bg image and on top of it I can see the GuiTextEditCtrl. when I press the gui, it seems like it's in focus (there's a line for text editing), but I still don't get the keyboard.I'm not sure if I know how to add the textEntry.xib . I've overwritten the one in my project tree /ui/textEntry.xib (I'm using 1.3) and then I've added the whole directory into my project as reference. Other than that, I've made all the changes that you've made to the files above and compiled with no errors.
#56
12/18/2009 (4:01 pm)
@Ecliptic: Did you work out why the XIB would rotate on the second load?
#57
"Added new iPhoneTextEntry and iPhoneTextEntryController modules"
Added the scripts that Michael Perry posted in post # 33 of this thread to see if it was working. Interesting results. First no iPhone keyboard when button is selected and two, seems when the button is selected that some console output is displayed on the button instead of what is intended which is what is entered from the iPhone keyboard. No scripting console errors and did clean build.
Thoughts?
03/07/2010 (6:12 pm)
Ok I guess this has been implemented in 1.3 according to the 1.3 release thread."Added new iPhoneTextEntry and iPhoneTextEntryController modules"
Added the scripts that Michael Perry posted in post # 33 of this thread to see if it was working. Interesting results. First no iPhone keyboard when button is selected and two, seems when the button is selected that some console output is displayed on the button instead of what is intended which is what is entered from the iPhone keyboard. No scripting console errors and did clean build.
Thoughts?
#58
03/08/2010 (11:15 am)
In 1.3 you can use this code to bring up the iPhoneKeyboard. Make sure that the resource textEntry.xib is included in your resources folder. It may have been improperly named iPhoneTextEntry.xib .if (isFunction("getIphoneKeyboardInput"))
%input = getIphoneKeyboardInput("Default"); //Where Default is the default text you want displayed
#59
Sun Mar 28 22:13:20 unknown iWT[2942] <Error>: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] was unable to load a nib named "TextEntry"'
Any ideas please?
03/28/2010 (2:26 pm)
I'm having problems with this .. I have renamed as per the previous comment but still get the following error in the console:Sun Mar 28 22:13:20 unknown iWT[2942] <Error>: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] was unable to load a nib named "TextEntry"'
Any ideas please?
#60
Cheers
03/28/2010 (2:41 pm)
Not to worry, got it working, I had renamed the xib to textEntry.xib with a lower case 't' - it needs to be 'TextEntry.xib'.Cheers
Torque Owner Bret Patterson
Does anyone have an integrated solution we can use?