Cleaned up the iOS text input code, fixed the orientation of the view offset when the onscreen keyboard is shown in iOS 8+, and changed UIKit_SetTextInputRect to update the view offset if the keyboard is currently visible.

This commit is contained in:
Alex Szpakowski 2014-11-23 23:23:47 -04:00
parent 6d85f52228
commit 9b8a1768f2
2 changed files with 115 additions and 98 deletions

View File

@ -40,7 +40,13 @@
#if SDL_IPHONE_KEYBOARD #if SDL_IPHONE_KEYBOARD
- (void)showKeyboard; - (void)showKeyboard;
- (void)hideKeyboard; - (void)hideKeyboard;
- (void)initializeKeyboard; - (void)initKeyboard;
- (void)deinitKeyboard;
- (void)keyboardWillShow:(NSNotification *)notification;
- (void)keyboardWillHide:(NSNotification *)notification;
- (void)updateKeyboard;
@property (nonatomic, assign, getter=isKeyboardVisible) BOOL keyboardVisible; @property (nonatomic, assign, getter=isKeyboardVisible) BOOL keyboardVisible;
@property (nonatomic, assign) SDL_Rect textInputRect; @property (nonatomic, assign) SDL_Rect textInputRect;

View File

@ -35,8 +35,6 @@
#include "SDL_uikitmodes.h" #include "SDL_uikitmodes.h"
#include "SDL_uikitwindow.h" #include "SDL_uikitwindow.h"
void _uikit_keyboard_init();
@implementation SDL_uikitview { @implementation SDL_uikitview {
SDL_TouchID touchId; SDL_TouchID touchId;
@ -54,7 +52,7 @@ void _uikit_keyboard_init();
{ {
if (self = [super initWithFrame:frame]) { if (self = [super initWithFrame:frame]) {
#if SDL_IPHONE_KEYBOARD #if SDL_IPHONE_KEYBOARD
[self initializeKeyboard]; [self initKeyboard];
#endif #endif
self.multipleTouchEnabled = YES; self.multipleTouchEnabled = YES;
@ -67,6 +65,13 @@ void _uikit_keyboard_init();
} }
- (void)dealloc
{
#if SDL_IPHONE_KEYBOARD
[self deinitKeyboard];
#endif
}
- (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize
{ {
CGPoint point = [touch locationInView:self]; CGPoint point = [touch locationInView:self];
@ -152,7 +157,7 @@ void _uikit_keyboard_init();
@synthesize keyboardVisible; @synthesize keyboardVisible;
/* Set ourselves up as a UITextFieldDelegate */ /* Set ourselves up as a UITextFieldDelegate */
- (void)initializeKeyboard - (void)initKeyboard
{ {
textField = [[UITextField alloc] initWithFrame:CGRectZero]; textField = [[UITextField alloc] initWithFrame:CGRectZero];
textField.delegate = self; textField.delegate = self;
@ -173,7 +178,16 @@ void _uikit_keyboard_init();
/* add the UITextField (hidden) to our view */ /* add the UITextField (hidden) to our view */
[self addSubview:textField]; [self addSubview:textField];
_uikit_keyboard_init(); NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)deinitKeyboard
{
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[center removeObserver:self name:UIKeyboardWillHideNotification object:nil];
} }
/* reveal onscreen virtual keyboard */ /* reveal onscreen virtual keyboard */
@ -190,6 +204,71 @@ void _uikit_keyboard_init();
[textField resignFirstResponder]; [textField resignFirstResponder];
} }
- (void)keyboardWillShow:(NSNotification *)notification
{
CGRect kbrect = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue];
int height;
/* The keyboard rect is in the coordinate space of the screen, but we want
* its height in the view's coordinate space.
*/
#ifdef __IPHONE_8_0
if ([self respondsToSelector:@selector(convertRect:fromCoordinateSpace:)]) {
UIScreen *screen = self.window.screen;
kbrect = [self convertRect:kbrect fromCoordinateSpace:screen.coordinateSpace];
height = kbrect.size.height;
} else
#endif
{
/* In iOS 7 and below, the screen's coordinate space is never rotated. */
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
height = kbrect.size.width;
} else {
height = kbrect.size.height;
}
}
[self setKeyboardHeight:height];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
[self setKeyboardHeight:0];
}
- (void)updateKeyboard
{
SDL_Rect textrect = self.textInputRect;
CGAffineTransform t = self.transform;
CGPoint offset = CGPointMake(0.0, 0.0);
if (self.keyboardHeight) {
int rectbottom = textrect.y + textrect.h;
int kbottom = self.bounds.size.height - self.keyboardHeight;
if (kbottom < rectbottom) {
offset.y = kbottom - rectbottom;
}
}
/* Put the offset into the this view transform's coordinate space. */
t.tx = 0.0;
t.ty = 0.0;
offset = CGPointApplyAffineTransform(offset, t);
t.tx = offset.x;
t.ty = offset.y;
/* Move the view by applying the updated transform. */
self.transform = t;
}
- (void)setKeyboardHeight:(int)height
{
keyboardVisible = height > 0;
keyboardHeight = height;
[self updateKeyboard];
}
/* UITextFieldDelegate method. Invoked when user types something. */ /* UITextFieldDelegate method. Invoked when user types something. */
- (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{ {
@ -255,7 +334,8 @@ void _uikit_keyboard_init();
/* iPhone keyboard addition functions */ /* iPhone keyboard addition functions */
#if SDL_IPHONE_KEYBOARD #if SDL_IPHONE_KEYBOARD
static SDL_uikitview * getWindowView(SDL_Window * window) static SDL_uikitview *
GetWindowView(SDL_Window * window)
{ {
if (window == NULL) { if (window == NULL) {
SDL_SetError("Window does not exist"); SDL_SetError("Window does not exist");
@ -272,117 +352,46 @@ static SDL_uikitview * getWindowView(SDL_Window * window)
return view; return view;
} }
SDL_bool UIKit_HasScreenKeyboardSupport(_THIS) SDL_bool
UIKit_HasScreenKeyboardSupport(_THIS)
{ {
return SDL_TRUE; return SDL_TRUE;
} }
void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window) void
UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window)
{ {
@autoreleasepool { @autoreleasepool {
SDL_uikitview *view = getWindowView(window); SDL_uikitview *view = GetWindowView(window);
if (view != nil) { if (view != nil) {
[view showKeyboard]; [view showKeyboard];
} }
} }
} }
void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window) void
UIKit_HideScreenKeyboard(_THIS, SDL_Window *window)
{ {
@autoreleasepool { @autoreleasepool {
SDL_uikitview *view = getWindowView(window); SDL_uikitview *view = GetWindowView(window);
if (view != nil) { if (view != nil) {
[view hideKeyboard]; [view hideKeyboard];
} }
} }
} }
SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window) SDL_bool
UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window)
{ {
@autoreleasepool { @autoreleasepool {
SDL_uikitview *view = getWindowView(window); SDL_uikitview *view = GetWindowView(window);
if (view == nil) { if (view != nil) {
return 0; return view.isKeyboardVisible;
} }
return 0;
return view.isKeyboardVisible;
} }
} }
void _uikit_keyboard_update() {
SDL_Window *window = SDL_GetFocusWindow();
if (!window) { return; }
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
if (!data) { return; }
SDL_uikitview *view = data.view;
if (!view) { return; }
SDL_Rect r = view.textInputRect;
int height = view.keyboardHeight;
int offsetx = 0;
int offsety = 0;
if (height) {
int sw,sh;
SDL_GetWindowSize(window,&sw,&sh);
int bottom = (r.y + r.h);
int kbottom = sh - height;
if (kbottom < bottom) {
offsety = kbottom-bottom;
}
}
UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation];
if (ui_orient == UIInterfaceOrientationLandscapeLeft) {
int tmp = offsetx; offsetx = offsety; offsety = tmp;
}
if (ui_orient == UIInterfaceOrientationLandscapeRight) {
offsety = -offsety;
int tmp = offsetx; offsetx = offsety; offsety = tmp;
}
if (ui_orient == UIInterfaceOrientationPortraitUpsideDown) {
offsety = -offsety;
}
view.frame = CGRectMake(offsetx,offsety,view.frame.size.width,view.frame.size.height);
}
void _uikit_keyboard_set_height(int height) {
SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
if (view == nil) {
return;
}
view.keyboardVisible = height > 0;
view.keyboardHeight = height;
_uikit_keyboard_update();
}
void _uikit_keyboard_init() {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
NSOperationQueue *queue = [NSOperationQueue mainQueue];
[center addObserverForName:UIKeyboardWillShowNotification
object:nil
queue:queue
usingBlock:^(NSNotification *notification) {
int height = 0;
CGSize keyboardSize = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
height = keyboardSize.height;
UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation];
if (ui_orient == UIInterfaceOrientationLandscapeRight || ui_orient == UIInterfaceOrientationLandscapeLeft) {
height = keyboardSize.width;
}
_uikit_keyboard_set_height(height);
}
];
[center addObserverForName:UIKeyboardDidHideNotification
object:nil
queue:queue
usingBlock:^(NSNotification *notification) {
_uikit_keyboard_set_height(0);
}
];
}
void void
UIKit_SetTextInputRect(_THIS, SDL_Rect *rect) UIKit_SetTextInputRect(_THIS, SDL_Rect *rect)
{ {
@ -392,12 +401,14 @@ UIKit_SetTextInputRect(_THIS, SDL_Rect *rect)
} }
@autoreleasepool { @autoreleasepool {
SDL_uikitview *view = getWindowView(SDL_GetFocusWindow()); SDL_uikitview *view = GetWindowView(SDL_GetFocusWindow());
if (view == nil) { if (view != nil) {
return; view.textInputRect = *rect;
}
view.textInputRect = *rect; if (view.keyboardVisible) {
[view updateKeyboard];
}
}
} }
} }