TiOSKeyboard

//
// Programming by Andree Heyroth, Syncro-Concept
// programming language is Firemonkey / Delphi from Embarcadero
// http://www.syncro-concept.de
//
// Please add this unit to an existing package or create a new one.
// After compiling and installing the package the following methods will be available
// through the object inspector:
//
// OnkeyboardWillShow
// OnkeyboardWillHide
// OnkeyboardDidShow
// OnkeyboardDidHide
//
// The methods will be called each time when the app-events with the same name are fired
//
// Remark: Is not cpmpletely ready yet. Coordinates of the Keyboard have to be converted
// to Screen-Coordinates.
// ---------------------------------------------------------------------------
//
{$IFDEF FPC}
//{$mode objfpc}{$H+}
{$modeswitch objectivec1}
{$ENDIF}

unit KeyboardU;

interface

uses
SysUtils, Classes, FMX_Types
{$IFDEF FPC}
, FMX_Platform_iOS, iPhoneAll, CGGeometry
{$ENDIF}
;

type
TiOSkbdPos = (kiTop, kiBottom);

type
TkbdInfo = record
iOSkbdPos: TiOSkbdPos;
iOSkbdTop, iOSkbdLeft, iOSkbdHeight, iOSkbdWidth: single;
end;

{$IFDEF FPC}
type
TiOSKeyboardBase = objcclass (NSObject)
procedure keyboardWillShow(Notification: NSNotification); message 'keyboardWillShow:';
procedure keyboardWillHide(Notification: NSNotification); message 'keyboardWillHide:';
procedure keyboardDidShow(Notification: NSNotification); message 'keyboardDidShow:';
procedure keyboardDidHide(Notification: NSNotification); message 'keyboardDidHide:';
end;
{$ENDIF}

type
TiOSKeyboardEvent = procedure (kbdInfo: TkbdInfo) of object;

type
TiOSKeyboard = class(TFmxObject)
private
{$IFDEF FPC}
delegate: TiOSKeyboardBase;
{$ENDIF}
FOnkeyboardWillShow: TiOSKeyboardEvent;
FOnkeyboardWillHide: TiOSKeyboardEvent;
FOnkeyboardDidShow: TiOSKeyboardEvent;
FOnkeyboardDidHide : TiOSKeyboardEvent;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
{$IFDEF FPC}
procedure GetActiveFieldInfo (var kbdInfo: TkbdInfo; Notification: NSNotification);
{$ENDIF}
published
property OnkeyboardWillShow: TiOSKeyboardEvent read FOnkeyboardWillShow write FOnkeyboardWillShow;
property OnkeyboardWillHide: TiOSKeyboardEvent read FOnkeyboardWillHide write FOnkeyboardWillHide;
property OnkeyboardDidShow: TiOSKeyboardEvent read FOnkeyboardDidShow write FOnkeyboardDidShow;
property OnkeyboardDidHide: TiOSKeyboardEvent read FOnkeyboardDidHide write FOnkeyboardDidHide;
end;

var
GlobaliOSKeyboardVar: TiOSKeyboard;

procedure Register;

implementation

constructor TiOSKeyboard.Create(AOwner: TComponent);
begin
if Assigned(GlobaliOSKeyboardVar) then begin
//raise Exception.Create('I won''t let you have more than one of these things (Keyboard) ...');
exit;
end;
inherited;
{$IFDEF FPC}
delegate := TiOSKeyboardBase.alloc.init;
NSNotificationCenter.defaultCenter.addObserver_selector_name_object (delegate, objcselector('keyboardWillShow:'), UIKeyboardWillShowNotification, nil);
NSNotificationCenter.defaultCenter.addObserver_selector_name_object (delegate, objcselector('keyboardWillHide:'), UIKeyboardWillHideNotification, nil);
NSNotificationCenter.defaultCenter.addObserver_selector_name_object (delegate, objcselector('keyboardDidShow:'), UIKeyboardDidShowNotification, nil);
NSNotificationCenter.defaultCenter.addObserver_selector_name_object (delegate, objcselector('keyboardDidHide:'), UIKeyboardDidHideNotification, nil);
GlobaliOSKeyboardVar := self;
{$ENDIF}
end;

destructor TiOSKeyboard.Destroy;
begin
{$IFDEF FPC}
delegate.Release;
{$ENDIF}
inherited;
end;

{$IFDEF FPC}
procedure TiOSKeyboard.GetActiveFieldInfo (var kbdInfo: TkbdInfo; Notification: NSNotification);
var
info: NSDictionary;
cgr: CGRect;
// view: UIView;
begin
// view := UIApplication.sharedApplication.windows.ObjectAtIndex(0).subViews.objectAtIndex(0);
kbdInfo.iOSkbdPos := kiTop;
info := Notification.UserInfo;
// frame für den start der tastatureinblendung
cgr := info.objectForKey(UIkeyBoardFrameBeginUserInfoKey).CGRectValue;
// frame der tastatur nach einblendung
cgr := info.objectForKey(UIkeyBoardFrameEndUserInfoKey).CGRectValue;
// cgr := cgr.fromView (cgr);
kbdInfo.iOSkbdTop := cgr.origin.X;
kbdInfo.iOSkbdLeft := cgr.origin.Y;
kbdInfo.iOSkbdWidth := cgr.size.width;
kbdInfo.iOSkbdHeight := cgr.size.height;
if kbdInfo.iOSkbdTop > 0 then begin
kbdInfo.iOSkbdPos := kiBottom;
end;
end;

procedure TiOSKeyboardBase.keyboardWillShow (Notification: NSNotification);
var
kbdInfo: TkbdInfo;
begin
if not assigned (GlobaliOSKeyboardVar) then begin
exit;
end;
if Assigned(GlobaliOSKeyboardVar.FOnkeyboardWillShow) then begin
GlobaliOSKeyboardVar.GetActiveFieldInfo (kbdInfo, Notification);
GlobaliOSKeyboardVar.FOnkeyboardWillShow (kbdInfo);
end;
end;

procedure TiOSKeyboardBase.keyboardWillHide (Notification: NSNotification);
var
kbdInfo: TkbdInfo;
begin
if not assigned (GlobaliOSKeyboardVar) then begin
exit;
end;
if Assigned(GlobaliOSKeyboardVar.FOnkeyboardWillHide) then begin
GlobaliOSKeyboardVar.GetActiveFieldInfo (kbdInfo, Notification);
GlobaliOSKeyboardVar.FOnkeyboardWillHide (kbdInfo);
end;
end;

procedure TiOSKeyboardBase.keyboardDidShow (Notification: NSNotification);
var
kbdInfo: TkbdInfo;
begin
if not assigned (GlobaliOSKeyboardVar) then begin
exit;
end;
if Assigned(GlobaliOSKeyboardVar.FOnkeyboardDidShow) then begin
GlobaliOSKeyboardVar.GetActiveFieldInfo (kbdInfo, Notification);
GlobaliOSKeyboardVar.FOnkeyboardDidShow (kbdInfo);
end;
end;

procedure TiOSKeyboardBase.keyboardDidHide (Notification: NSNotification);
var
kbdInfo: TkbdInfo;
begin
if not assigned (GlobaliOSKeyboardVar) then begin
exit;
end;
if Assigned(GlobaliOSKeyboardVar.FOnkeyboardDidHide) then begin
GlobaliOSKeyboardVar.GetActiveFieldInfo (kbdInfo, Notification);
GlobaliOSKeyboardVar.FOnkeyboardDidHide (kbdInfo);
end;
end;
{$ENDIF}

procedure Register;
begin
RegisterComponents('iOS', [TiOSKeyboard]);
end;

end.