Androidアプリでネイティブコントロールをフォームに配置するには
Delphi 10.1 BerlinのFireMonkeyアプリケーションでAndroidのネイティブコントロールをフォームに配置する方法です。
コントロールを配置する
DelphiのフォームにAndroidのネイティブコントロールを配置するには、JNativeLayoutを使用します。
uses Androidapi.JNI.Embarcadero;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ private 宣言 }
FNativeLayout: JNativeLayout;
public
{ public 宣言 }
end;
Androidのネイティブコントロールを使用するときは、
CallInUIThread関数またはCallInUIThreadAndWaitFinishing関数を使用して、
AndroidのUIスレッドで行います。
CallInUIThread関数は非同期で処理を行います。
CallInUIThreadAndWaitFinishing関数は処理が完了するまでブロックします。
uses FMX.Helpers.Android;
CallInUIThreadAndWaitFinishing(
procedure
begin
// ネイティブコントロールを使用する
end);
JNativeLayoutのインスタンスを作成します。
uses Androidapi.Helpers, FMX.Platform.Android;
FNativeLayout := TJNativeLayout.JavaClass.Init(
TAndroidHelper.Activity,
MainActivity.getWindow.getDecorView.getWindowToken);
ネイティブコントロールを作成し、JNativeLayoutに登録します。
今回のサンプルではEditTextを配置します。
uses Androidapi.JNI.Widget;
EditText := TJEditText.JavaClass.Init(TAndroidHelper.Activity);
FNativeLayout.setControl(EditText);
JNativeLayoutに登録できるコントロールは一つだけです。
また、nilを登録すると、登録されていたコントロールが削除されます。
コントロールの位置と大きさを設定します。
この設定は、JNativeLayoutにコントロールを登録した後に行います。
FNativeLayout.setPosition(50, 300);
FNativeLayout.setSize(400, 200);
コントロールを非表示にする
事前にウィンドウのサイズを取得しておきます。
type
TForm1 = class(TForm)
…
private
{ private 宣言 }
FRealBounds: TRect;
procedure CalcRealBorder;
…
end;
procedure TForm1.CalcRealBorder;
var
NativeWin: JWindow;
ContentRect: JRect;
begin
NativeWin := TAndroidHelper.Activity.getWindow;
if NativeWin <> nil then
begin
ContentRect := TJRect.Create;
NativeWin.getDecorView.getDrawingRect(ContentRect);
FRealBounds := Rect(ContentRect.left, ContentRect.top, ContentRect.Right,
ContentRect.bottom);
end
else
FRealBounds := TRect.Empty;
end;
コントロールを非表示にする処理は、UIスレッドで行います。
procedure TForm1.ButtonHideClick(Sender: TObject);
begin
CallInUIThread(
procedure
begin
if FEditText.getVisibility <> TJView.JavaClass.INVISIBLE then
begin
FEditText.setVisibility(TJView.JavaClass.INVISIBLE);
FNativeLayout.setPosition(
FRealBounds.Right * 2,
FRealBounds.Height * 2);
end;
end);
end;
コントロールを表示する
非表示にしたコントロールを再表示します。
procedure TForm1.ButtonShowClick(Sender: TObject);
begin
CallInUIThread(
procedure
begin
FNativeLayout.setPosition(50, 300);
FNativeLayout.setSize(400, 200);
if FEditText.getVisibility <> TJView.JavaClass.VISIBLE then
begin
FEditText.setVisibility(TJView.JavaClass.VISIBLE);
end;
end);
end;
サンプルアプリケーション
Createボタンを押すとコントロールを作成し、Hideボタンで非表示にし、Showボタンで再表示します。
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes,
System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics,
FMX.Dialogs, Androidapi.JNI.Embarcadero, FMX.Controls.Presentation,
FMX.StdCtrls, Androidapi.JNI.Widget;
type
TForm1 = class(TForm)
ButtonCreate: TButton;
ButtonShow: TButton;
ButtonHide: TButton;
procedure ButtonCreateClick(Sender: TObject);
procedure ButtonShowClick(Sender: TObject);
procedure ButtonHideClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ private 宣言 }
FEditText: JEditText;
FNativeLayout: JNativeLayout;
FRealBounds: TRect;
procedure CalcRealBorder;
public
{ public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
uses Androidapi.Helpers, FMX.Platform.Android, FMX.Helpers.Android,
Androidapi.JNI.GraphicsContentViewText;
procedure TForm1.ButtonCreateClick(Sender: TObject);
begin
CallInUIThreadAndWaitFinishing(
procedure
begin
FNativeLayout := TJNativeLayout.JavaClass.Init(TAndroidHelper.Activity,
MainActivity.getWindow.getDecorView.getWindowToken);
FEditText := TJEditText.JavaClass.Init(TAndroidHelper.Activity);
FEditText.setText(StrToJCharSequence('テスト'),
TJTextView_BufferType.JavaClass.NORMAL);
FNativeLayout.setControl(FEditText);
FNativeLayout.setPosition(50, 300);
FNativeLayout.setSize(400, 200);
end);
end;
procedure TForm1.ButtonHideClick(Sender: TObject);
begin
CallInUIThread(
procedure
begin
if FEditText.getVisibility <> TJView.JavaClass.INVISIBLE then
begin
FEditText.setVisibility(TJView.JavaClass.INVISIBLE);
FNativeLayout.setPosition(FRealBounds.Right * 2,
FRealBounds.Height * 2);
end;
end);
end;
procedure TForm1.ButtonShowClick(Sender: TObject);
begin
CallInUIThread(
procedure
begin
FNativeLayout.setPosition(50, 300);
FNativeLayout.setSize(400, 200);
if FEditText.getVisibility <> TJView.JavaClass.VISIBLE then
begin
FEditText.setVisibility(TJView.JavaClass.VISIBLE);
end;
end);
end;
procedure TForm1.CalcRealBorder;
var
NativeWin: JWindow;
ContentRect: JRect;
begin
NativeWin := TAndroidHelper.Activity.getWindow;
if NativeWin <> nil then
begin
ContentRect := TJRect.Create;
NativeWin.getDecorView.getDrawingRect(ContentRect);
FRealBounds := Rect(ContentRect.left, ContentRect.top, ContentRect.Right,
ContentRect.bottom);
end
else
FRealBounds := TRect.Empty;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CalcRealBorder;
end;
end.
ソースコードはGitHubで取得できます。