不完美-FMX 程序中避免输入焦点被虚拟键盘遮挡

【更新】

2017.3.27

  • 增加对 10.2 版的兼容,请 SVN 直接检出或单独下载

2016.8.24

  • 修正了 ScrollBox 滚动过程中调整位置造成错位的问题

2016.7.29

  • 修正了当设置了最后一个焦点控件的ReturnType 为 Next 时,回车会出现 Access Volation 的问题
  • 修正了在特定设备中添加调整层时,引发对齐控件时出错的问题
  • 优化了将控件移动到调整层时的效率,避免重复对齐控件的问题

2016.7.19

  • 修正了特定场景下,调整焦点的位置过头的问题
  • 修正了设置窗体的填充设置会失效的问题

2016.7.18

  • 修复了在特定场景下出现 AV 错误的问题

2016.7.7

  • 修复了 Delphi 在 iOS 下特定场景下处理输入法状态不正确的问题,详细描述

2016.6.28:针对滚动条优化

  • 在滚动条惯性滚动过程中,不去尝试调整从而避免惯性滚动时的抖动现象(SVN 已更新)。我能说坑爹的动画中的 FStarted 没有公开,造成我不得不去用RTTI来检查是否处于动画中嘛:(

2016.6.1:重新设计调整算法

  • 新算法考虑了滚动框和Memo等控件的支持,优先使用滚动类控件内部的滚动来调整位置,在不能满足需要时,才会整体上移布局
  • 新版本已经加入 QDAC 的 SVN 源,并命名为 qdac_fmx_vkhelper.pas,以后更新直接检出即可
  • 后面的下载仍是老版本,保持原样不再更新,以便供已经使用老版本,但不愿意改名的朋友下载。其它朋友推荐使用新版本。

2016.4.15:更完美

  • 加入 iOS 支持和 Memo 控件的支持(Memo 控件的效果还不算完美,但可以满足日常使用要求)

2016.1.17:进一步修正

  • 修正了还有输入焦点时,按返回直接退出而不是去除焦点的问题
  • 修正了键盘隐藏时,未检查 FLastControl 是否为空造成 AV 错误的问题

2016.1.16:更完美

  • 移除 Timer,改在收到 TIdleMessage 时进行检查,从而提高响应速度
  • 修正了FMX系统自身在虚拟键盘自身隐藏时,没有将虚拟键盘服务内部的 FState 的值修改为TvkbState.Hidden,造成按返回键无法退出应用的问题(FMX自身的 Bug,本方案通过 RTTI 来强制改了它的状态);
  • 修正了输入焦点控件再次点击时弹出虚拟键盘时,没有正确调整焦点控件位置的问题;

2016.1.8

  • 修正了输入法在特定的情况下,检查输入法隐藏的代码没有正确激活的问题(感谢阿笨猫报告)

2015.7.16:更完美

  • 修正了输入法隐藏后旋转屏幕时布局出现错乱的问题(感谢红鱼儿、多春鱼)
  • 修正了特定场景下出现多余空白的问题

2015.6.3 :更完美

  • 解决了虚拟键盘隐藏后无法退出的问题;
  • 对于没有ScrollBox做底的窗体也加入了支持,自动添加一个 TLayout 而不是 TVertScrollBox(参考恢弘想法)

Delphi 提供了一个 Demo,叫 ScrollableFormDemo,要实现避免输入焦点被虚拟键盘遮挡的效果,需要写一堆的代码。也许这一切已不再重要,但是,它却没有考虑虚拟键盘隐藏的问题,在你隐藏虚拟键盘时,它没有自动回复原位,所以这一切显得更加的不完美。

为了避免每次都得写一堆代码的麻烦,我尝试换种思路来解决这一个问题,于是有了下面 vkbdhelper.pas 单元。但这个单元依然是三个字:不完美!不过我抛出来块砖,是希望将来第三方或官方能够更完美的解决这一问题。

大概的思路是通过订阅三个消息来捕获和控制虚拟键盘的状态:

  • TVKStateChangeMessage 消息,以得到常规的虚拟键盘状态改变通知;
  • TSizeChangedMessage 消息,以得到屏幕方向改变的通知;
  • TIdleMessage 消息,以便检查用户是否手动隐藏了虚拟键盘;如果用户手动隐藏了虚拟键盘,则自己触发一个TVKStateChangeMessage消息,这样子就回归到第 1 步正常的处理过程。

Long long ago,FMX 在 Android 下就有一个 Bug,一旦输入法弹出来,按键盘上的返回键就无法正确退出程序。该问题是由于输入法隐藏时,没有正确的通知应用改变虚拟键盘服务的 FState 成员造成的。本程序同时修正了这一个问题。

好了,思路有了,那么接下来是考虑易用性的问题:

实际上,易用性的设计一直是让人头痛的问题。我写这个单元就是为了解决系统自带的实现的不完美,虽然目前依然不是那么完美,但至少易用性上做到了我能做到的最好。你只需要在程序中的任意一个单元的 uses 里加入vkbdhelper,剩下的一句代码也不需要你去写。

接下来,还需要说啥呢?代码代表我的心~~~~

下载地址:VKHelperVsDemoR20160415

为什么我说这个设计依然不完美?。

  • Memo 的支持仍有问题
  • 控件上移出可视区域时,没有处理它的位置
  • 需要引入这个单元。
分享到:

0 条评论

沙发空缺中,还不快抢~