结果:
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 var101 LFocused : TControl;102 LFocusRect: TRectF;103 begin104 FNeedOffset := False;105 if Assigned(Focused) then106 begin107 LFocused := TControl(Focused.GetObject);108 LFocusRect := LFocused.AbsoluteRect;109 LFocusRect.Offset(VertScrollBox1.ViewportPosition);110 if (LFocusRect.IntersectsWith(TRectF.Create(FKBBounds))) and111 (LFocusRect.Bottom > FKBBounds.Top) then112 begin113 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 then121 RestorePosition;122 end;123 124 end.
PS:
1.本实例来自官方demo(D:\DelphiXE8\Users\Public\Documents\Embarcadero\Studio\15.0\Samples\Object Pascal\Mobile Samples\User Interface\ScrollableForm)。
2.控件布局是VertScrollBox1、Layout1,之后的控件都是在Layout1上的。