Thursday, August 18, 2016

FireMonkey VyDVSBHelper: A Component to Manage a Vertical Scroll Box to Reveal Input Fields Obscured by a Virtual Keyboard


This is the third post of a four-post series on Delphi's FireMonkey support for mobile device virtual keyboards. For the first in the series, see Using Delphi's FireMonkey Vertical Scroll Box With a Virtual Keyboard.

There is source code that accompanies these blogs. The project group FMXVertScrollBoxEtude can be downloaded from GitHub:

https://github.com/Pasquina/FMXVertScrollBoxEtude/releases

Source code was developed using RAD Studio 10.1 Berlin (No updates.)

Overview


VyDVSBHelper is designed to manage a Vertical Scroll Box in response to change in the presence or absence of a virtual keyboard and the current input field focus. The concept is straightforward:
  • For each change in either input field focus or virtual keyboard show or hide, calculate the screen difference between the bottom of the focused field and the top of the virtual keyboard.
  • If the difference is positive (the top of the virtual keyboard is above the bottom of the focused field and therefore is obscuring the field) then reposition the vertical scroll box viewport so that the focused field is just above the virtual field and no longer obscured.

There are three major event handlers required to achieve this functionality, all events of TForm:
  • FormFocusChanged—fired when the focus changes to a different child on the form.
  • VirtualKeyboardShown—fired when the virtual keyboard is shown in response an input field receiving the focus.
  • virtualKeyboardHidden—fired when no control requiring input has the focus.

In addition, there is one event handler that is used to effect viewport repositioning:
  • CalcContentBounds—fired when the RealignContents method is invoked. Here is is used to ensure sufficient vertical content to allow the viewport to be shifted the required amount.

Internally used routines are:
  • Create—performs initialization including setting the TForm event handlers needed by the component.
  • LogFocused—Optionally logs the FormFocusChanged event. (Debugging tool.)
  • LogVK—Optionally logs the VirtualKeyboardHidden and VirtualKeyboardShown events. (Debugging tool.)
  • ResetViewport—resets the scroll box viewport if needed to reveal obscured input objects.
  • SetFocusedABSY—besides being a property setter determines if a viewport shift is required.
  • SetVKAbsY—besides being a property setter determines if a viewport shift is required.
  • SetupContentBounds—ensures that the vertical bounds of the scroll box are sufficient to effect the viewport shift.
  • ShiftViewport—Determines the shift amount required and either resets the viewport to the default position or invokes SetupContentBounds and then repositions the viewport to reveal the obscured object.

Using the VyDVSBFMXScroll Component


Component Installation


Install the 32-bit version of the component. This will cause it to appear in the Tool Pallet in the VSB Helper category. Note that this will only appear if the project framework is FireMonkey. The component is intended to work for mobile devices that can only be developed using FireMonkey. See the Register procedure for details on how this is accomplished.

The component code must be available for use in your Android deployments. One way to do this is to build the Android version of the component.

It is assumed that the user is familiar with how components are installed and used in projects. You may have to make changes to the component project to ensure that the proper libraries contain the necessary files.

Application Project 


The application project must contain a vertical scroll box. This is the layout that will be repositioned to reveal obscured input objects. All objects requiring repositioning must be children of the vertical scroll box, so that they are repositioned along with the scroll box when needed. (This can be seen in the VKScrollDemo project.)

Drop the VyDVSBHelper onto the project. There is one property to set: VScrollBox should be set to the vertical scroll box it is desired to manage. Normally, there will be only one. Optionally, you can specify a value for the MemoBox property if it is desired to log the event handler traces. This property is optional and if omitted, no logging will take place.

Be sure that the tab order is set as you intend navigation to take place. Also, you must include the following event handler (OnFormKeyDown) in your own code:



Besides any application code you require, no other programming should be necessary to manage the vertical scroll box.

Some Caveats


The create procedure of the VKScrollDemo component modifies the TForm component that calls it. Specifically, it puts its own event handler addresses in the OnVirtualKeyboardShown, OnVirtualKeyboardHidden and OnFocusChanged events. It will overlay any specification you may have made at design time. Do not modify these values as proper functioning of the component depends on the required event handlers.

Similar remarks apply to the OnCalcContentBounds event handler of the Vertical Scroll Box. It is not done in the Create procedure because the address of the Vertical Scroll Box is not yet available to make the modification. See the SetupContentBounds procedure in the source code for more information.

It is important that the two setters, SetVKAbsY and SetFocusedAbsY be used rather than referencing the base fields, FVKAbsY and FFocusedAbsY. This is because the setters make a logical decision and invoke the ShiftViewportRoutine when required. Setting the field values directly would bypass this small but important piece of logic.

It is not always possible to determine the height of a virtual keyboard accurately. When the reported height is 25, you can be certain this is erroneous. See the event handler VirtualKeyboardShown to see the simple hack used to try to guess an appropriate value.

Conclusion


I have attempted to make VyDVSBHelper a simple and straightforward component to use. Certain anomalies in either FireMonkey or Android conspire to make this a bit dodgy, especially when parameters from events are not reported accurately and consistently.

In the fourth and final posting in this series, we examine a working example of an application that uses the VyDVSBHelper component. Since there are occasional random failings when virtual keyboard heights are misreported, we examine circumventions that the user may employ to recover.


Comments are welcomed. Thanks for reading this far.

No comments:

Post a Comment

FireMonkey String Grid Responsive Columns

FireMonkey String Grid Responsive Columns Code to Cause Column Widths to Change When String Grids Are Resized Overview I have a FireMonke...