UPDATE: If you’ve applied Update 1 for XE5, please revert any changes made based on this article, or ignore it if you have not made any changes. The issue has been resolved in Update 1 for the DEVICE; sadly, Update 1 causes an issue with the Done bar in the simulator. Please refer to this article if you have installed Update 1.
If you’ve recently compiled your iOS app for iOS7 with Delphi XE5, and your app uses the virtual keyboard, you would have noticed that the “Done” bar is out of vertical alignment:
After a fair amount of research, I’m still a bit fuzzy on why this should be, however it appears to be to do with how iOS7 considers the total screen area. In any event, I’ve come up with a solution that at least for now appears to work.
The solution involves copying the FMX.VirtualKeyboard.iOS unit into your project directory, and making some changes to it. Firstly, the TCocoaVirtualKeyboardService needs a reference to the area occupied by the virtual keyboard when it is shown, so add the code indicated by the comment in the code below: (note that these are fragments of the code in the file. I am publishing only as much as to demonstrate what changes need to be made)
TCocoaVirtualKeyboardService = class(TInterfacedObject,
IFMXVirtualKeyboardService,
IFMXVirtualKeyboardToolbarService)
private
FKeyboardHandler: TKeyboardEventHandler;
{ IFMXVirtualKeyboardToolbarService }
FToolbarVisible: Boolean;
FToolBar: UIToolBar;
FFlexibleSepararator: UIBarButtonItem;
FHideButton: UIBarButtonItem;
FButtons: TList<TVirtualKeyboardToolButton>;
FUpdatingButtons: Boolean;
FToolbarEnabled: Boolean;
FHideButtonVisible: Boolean;
FStoredActiveForm: TComponent;
// Add the following line:
FVKRect: TRect;
procedure SetToolbarVisible(const Value: Boolean);
Next, in the TKeyboardEventHandler.KeyboardWillShow method make the changes indicated:
procedure TKeyboardEventHandler.KeyboardWillShow(notification: Pointer);
var
VKRect: TRect;
begin
VKRect := GetKeyboardRect(notification);
// Add the following line:
CocoaKeyboardService.FVKRect := VKRect;
CocoaKeyboardService.CreateToolbar;
Finally, in the TCocoaVirtualKeyboardService.GetToolbarFrame method:
function TCocoaVirtualKeyboardService.GetToolbarFrame: NSRect;
var
ScreenRect: NSRect;
// Add the following variables:
App: UIApplication;
Device: UIDevice;
Offset: Single;
begin
// Add the following lines:
Offset := 0;
App := TUIApplication.wrap(TUIApplication.OCClass.SharedApplication);
{$IFDEF CPUARM}
Device := TUIDevice.Wrap(TUIDevice.OCClass.currentDevice);
if Pos('7', Device.systemVersion.UTF8String) = 1 then
Offset := App.statusBarFrame.size.height;
{$ENDIF}
// Up to here
ScreenRect := TUIScreen.Wrap(TUIScreen.OCClass.mainScreen).applicationFrame;
and:
UIDeviceOrientationPortrait,
UIDeviceOrientationPortraitUpsideDown:
begin
if ToolbarVisible then
// Add the following line, and comment out the others as shown:
Result.origin.y := ScreenRect.size.height - (FVKRect.Height + TOOLBAR_HEIGHT - Offset)
{
if TUIDevice.Wrap(TUIDevice.OCClass.currentDevice).userInterfaceIdiom = UIUserInterfaceIdiomPhone then
Result.origin.y := ScreenRect.size.height - 260
else
Result.origin.y := ScreenRect.size.height - 308
}
else
Result.origin.y := ScreenRect.size.height + Offset; // <-- Alter this line
and:
UIDeviceOrientationLandscapeLeft,
UIDeviceOrientationLandscapeRight:
begin
if ToolbarVisible then
// Add the following line, and comment out the others as shown:
Result.origin.y := ScreenRect.size.height - (FVKRect.Height + TOOLBAR_HEIGHT - Offset)
{
if TUIDevice.Wrap(TUIDevice.OCClass.currentDevice).userInterfaceIdiom = UIUserInterfaceIdiomPhone then
Result.origin.y := ScreenRect.size.width - 206
else
Result.origin.y := ScreenRect.size.width - 396
}
else
Result.origin.y := ScreenRect.size.width + Offset; // <-- Alter this line
These changes do a couple of things: they correct for the hardcoded screen size values used in GetToolbarFrame, and use a “hack” to account for the “Done” bar being out of place on the device, offsetting it by the size of the status bar.
I hope this modification goes some way to helping out others with the same issue that I had.
Leave a Reply