修正 XE5 Android 键盘三个问题

说明:XE5 在 Android 平台上存在这一些键盘操作的问题,目前发现有下列几种:

  1. 按键盘上的隐藏键后,无法按上一页。
  2. 按键盘上的隐藏键后,无法触发 OnVirtualKeyboardHidden 事件.
  3. 关闭键盘后,再点一次无法显示键盘(大部份机子都有这个问题,实测 Nexus 7 II 没有这个问题)。

适用:Delphi XE5 update 2

参考:此修正方法是参考「完美解决 XE5 安卓下 虚拟键盘 隐藏没有事件的 BUG。」在此感谢。

源码下载:修正XE5_Android键盘三个问题.zip

 

目前发现的键盘问题,需要修改 XE5 源码「FMX.VirtualKeyboard.Android.pas」才能修正,改好的档案已经放在上面源码 zip 里,改动内容如下({+++>}内为增加的部份{<+++}):

{+++>}
function ObtainKeyboardRect: TRect;
var
  ContentRect, TotalRect: JRect;
begin
  ContentRect := TJRect.Create;
  TotalRect := TJRect.Create;
  MainActivity.getWindow.getDecorView.getWindowVisibleDisplayFrame(ContentRect);
  MainActivity.getWindow.getDecorView.getDrawingRect(TotalRect);
  Result := TRectF.Create(ConvertPixelToPoint(TPointF.Create(TotalRect.left, TotalRect.top + ContentRect.height)),
    ConvertPixelToPoint(TPointF.Create(TotalRect.right, TotalRect.bottom))).Truncate;
end;
{<+++}

function TVirtualKeyboardAndroid.GetVirtualKeyBoardState: TVirtualKeyBoardState;
begin
  if FError then
    Result := [vksError]
  else
    Result := [];
  if IsAutoShow then
    Result := Result + [vksAutoShow];
  if not FError then
  begin
{+++>}
    // 这里只解决: 按键盘上的隐藏后, 无法再按上一页的问题 (按上一页后, 才会执行这里).
    if FState = vkbsVisible then
       if ObtainKeyboardRect.Height < 30 then
          SetState(TVirtualKeyboardAndroid.TvkbState.vkbsHidden);
{<+++}
    if FState = vkbsVisible then
      Result := Result + [vksVisible];
  end;
end;

Main.pas

//------------------------------------------------------------------------------
// 2014.04.02 by 龟山阿卍 QQ 1467948783                                        -
// http://www.cnblogs.com/onechen/                                             -
//                                                                             -
// 需修改                                                                      -
// FMX.VirtualKeyboard.Android.pas                                             -
//------------------------------------------------------------------------------

unit Main;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,

  FMX.Platform,
  FMX.VirtualKeyboard.Android,
  FMX.VirtualKeyboard,

  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Edit,
  FMX.StdCtrls, FMX.Layouts, FMX.Memo;

type
  TForm1 = class(TForm)
    ToolBar1: TToolBar;
    Label1: TLabel;
    VirtualKeyboardTimer: TTimer;
    Memo1: TMemo;
    Edit1: TEdit;
    procedure FormVirtualKeyboardHidden(Sender: TObject;
      KeyboardVisible: Boolean; const Bounds: TRect);
    procedure FormVirtualKeyboardShown(Sender: TObject;
      KeyboardVisible: Boolean; const Bounds: TRect);
    procedure VirtualKeyboardTimerTimer(Sender: TObject);
    procedure Edit1Click(Sender: TObject);
  private
    { private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

// 显示键盘
function ShowVirtualKeyboard(const AControl: TFmxObject): Boolean;
var Service1: IFMXVirtualKeyboardService;
begin
     if (ObtainKeyboardRect.Height < 30) and
        TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(Service1)) then
          Result := Service1.ShowVirtualKeyboard(AControl)
     else Result := False;
end;

procedure TForm1.FormVirtualKeyboardHidden(Sender: TObject;
  KeyboardVisible: Boolean; const Bounds: TRect);
begin
     Edit1.Text := Keyboard hidden!;
     Memo1.Text := Format(W: %d H: %d, [Bounds.Width, Bounds.Height]);

     VirtualKeyboardTimer.Enabled := False; // 关闭检查键盘高度
end;

procedure TForm1.FormVirtualKeyboardShown(Sender: TObject;
  KeyboardVisible: Boolean; const Bounds: TRect);
begin
     Edit1.Text := Keyboard shown!;
     Memo1.Text := Format(W: %d H: %d, [Bounds.Width, Bounds.Height]);

     VirtualKeyboardTimer.Enabled := True; // 开启检查键盘高度
end;

procedure TForm1.VirtualKeyboardTimerTimer(Sender: TObject);
var R: TRect;
begin
     // 检查键盘高度 < 30 代表键盘关闭.
     R := ObtainKeyboardRect;
     if R.Height < 30 then
        Self.OnVirtualKeyboardHidden(Sender, False, R);
end;

procedure TForm1.Edit1Click(Sender: TObject);
begin
     // 在 TEdit 或 TMemo 需要用到键盘的控件, 加入下行, 才能确保关闭键盘后, 再点一次可以显示键盘.
     ShowVirtualKeyboard(TFmxObject(Sender));
end;

end.

 

「键盘上的隐藏键」是指下图所示位置: 

修正 XE5 Android 键盘三个问题,,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。