结果:
1.可以自动向上移动,来防遮挡,但同时发现个问题,如果是按硬件返回没有问题,要是点输入法(QQ、百度输入法)上的隐藏就不行了。
2.点击Edit2后出现输入法,点输入法上的隐藏后, 再点Edit2输入法不再显示。
实例代码:
1 unit Unit1; 2 3 interface 4 5 uses 6 System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.ComboEdit, 8 FMX.Edit, FMX.EditBox, FMX.NumberBox, FMX.DateTimeCtrls, FMX.ScrollBox, 9 FMX.Memo, FMX.Controls.Presentation, FMX.StdCtrls, 10 System.Math,//需要引入 11 FMX.VirtualKeyboard,//需要引入 12 FMX.Layouts; 13 14 type 15 TForm1 = class(TForm) 16 VertScrollBox1: TVertScrollBox; 17 Layout1: TLayout; 18 Memo1: TMemo; 19 Label1: TLabel; 20 Button1: TButton; 21 Edit1: TEdit; 22 Edit2: TEdit; 23 procedure FormCreate(Sender: TObject); 24 procedure FormFocusChanged(Sender: TObject); 25 procedure FormVirtualKeyboardHidden(Sender: TObject; 26 KeyboardVisible: Boolean; const Bounds: TRect); 27 procedure FormVirtualKeyboardShown(Sender: TObject; 28 KeyboardVisible: Boolean; const Bounds: TRect); 29 private 30 //定义移位标记 31 FKBBounds:TRectF; 32 FNeedOffset: Boolean; 33 procedure CalcContentBoundsProc(Sender: TObject; var ContentBounds: TRectF); 34 procedure RestorePosition; 35 procedure UpdateKBBounds; 36 { Private declarations } 37 public 38 { Public declarations } 39 end; 40 41 var 42 Form1: TForm1; 43 44 implementation 45 46 {$R *.fmx} 47 {$R *.NmXhdpiPh.fmx ANDROID} 48 49 //赋值事件 50 procedure TForm1.FormCreate(Sender: TObject); 51 begin 52 VertScrollBox1.OnCalcContentBounds := CalcContentBoundsProc; 53 end; 54 55 //每次焦点改变都要更新位置 56 procedure TForm1.FormFocusChanged(Sender: TObject); 57 begin 58 UpdateKBBounds; 59 end; 60 61 //输入法隐藏时的处理 62 procedure TForm1.FormVirtualKeyboardHidden(Sender: TObject; 63 KeyboardVisible: Boolean; const Bounds: TRect); 64 begin 65 FKBBounds.Create(0, 0, 0, 0); 66 FNeedOffset := False; 67 RestorePosition; 68 end; 69 70 //输入法显示时的处理 71 procedure TForm1.FormVirtualKeyboardShown(Sender: TObject; 72 KeyboardVisible: Boolean; const Bounds: TRect); 73 begin 74 FKBBounds := TRectF.Create(Bounds); 75 FKBBounds.TopLeft := ScreenToClient(FKBBounds.TopLeft); 76 FKBBounds.BottomRight := ScreenToClient(FKBBounds.BottomRight); 77 UpdateKBBounds; 78 end; 79 80 //计算内容边界 81 procedure TForm1.CalcContentBoundsProc(Sender: TObject; 82 var ContentBounds: TRectF); 83 begin 84 if FNeedOffset and (FKBBounds.Top > 0) then 85 begin 86 ContentBounds.Bottom := Max(ContentBounds.Bottom, 2 * ClientHeight - FKBBounds.Top); 87 end; 88 end; 89 90 //还原位置 91 procedure TForm1.RestorePosition; 92 begin 93 VertScrollBox1.ViewportPosition := PointF(VertScrollBox1.ViewportPosition.X, 0); 94 Layout1.Align := TAlignLayout.Client; 95 VertScrollBox1.RealignContent; 96 end; 97 98 //更新边界 99 procedure TForm1.UpdateKBBounds; 100 var 101 LFocused : TControl; 102 LFocusRect: TRectF; 103 begin 104 FNeedOffset := False; 105 if Assigned(Focused) then 106 begin 107 LFocused := TControl(Focused.GetObject); 108 LFocusRect := LFocused.AbsoluteRect; 109 LFocusRect.Offset(VertScrollBox1.ViewportPosition); 110 if (LFocusRect.IntersectsWith(TRectF.Create(FKBBounds))) and 111 (LFocusRect.Bottom > FKBBounds.Top) then 112 begin 113 FNeedOffset := True; 114 Layout1.Align := TAlignLayout.Horizontal; 115 VertScrollBox1.RealignContent; 116 Application.ProcessMessages; 117 VertScrollBox1.ViewportPosition := PointF(VertScrollBox1.ViewportPosition.X, LFocusRect.Bottom - FKBBounds.Top); 118 end; 119 end; 120 if not FNeedOffset then 121 RestorePosition; 122 end; 123 124 end.
PS:
1.本实例来自官方demo(D:DelphiXE8UsersPublicDocumentsEmbarcaderoStudio15.0SamplesObject PascalMobile SamplesUser InterfaceScrollableForm)。
2.控件布局是VertScrollBox1、Layout1,之后的控件都是在Layout1上的。