This post is dedicated to TFrameStand: a FMX component I have been developing in these latest months (mostly in my spare time).
The component and some demo projects are available on GitHub (so it is freely available) and there is an article on the latest issue (45-46) of Blaise Pascal magazine that covers in detail a couple of this demo projects.
* most of the code has been developed with XE8 version and I am now switching to 10 Seattle. This means it has not been tested against previous Delphi versions (XE7 and previous).
Especially in mobile app development, many developers simply add a lot of controls to the main form of the project (that many times it is also the only form present). This quickly leads to maintainability issues first because the form usually becomes too crowded to be edited at design-time and then because this approach do not promote reuse of code and UI elements across the application.
The concept of TFrame has been introduced a long time ago (even in VCL) to provide the developer a chance to bind together some UI elements (components) and some behavior (code) into a single, reusable, unit. This is good because you can split your application into pieces that can be designed individually and eventually reused (even in different applications!) by simply putting a frame instance on a parent object (can be a form, a page of a tab control or any other FMX visual component…).
A typical example where frames can help you a lot is the development of a mobile application where you can have a different frame implementing each “view” of your app. You can then implement your application functionalities by showing this or that TFrame depending on the state of the application itself (as you would do with a TTabControl and having a page for each view).
TFrameStand allows you to go even further than this, giving you an opportunity to have a middle layer between the frame and the parent object. This middle layer (the “stand”, from now on) can be seen as that visual portion (of the UI you are providing to the user) that is not strictly tied to the purpose of the TFrame you are showing but it is rather tied to the way the TFrame is presented to the user.
This “stands” are described using a very basic FireMonkey functionality: styles! Each TFrameStand component has a StyleBook reference property that can be used to define the collection of available stands and a couple of simple naming convention will do the rest (for example, define exactly where you want your TFrame attached to the stand).
Stands and frames
One of the key aspects of TFrameStand is that it allows you to reuse a stand with different TFrame descendant classes and also to do the opposite, that is, showing the same TFrame class through different stands instances. Either way, you can achieve a good level of visual consistency throughout your entire application (or event across different applications).
Same stand, different TFrame(s)
For instance, imagine having a stand that implements a way to show a TFrame, for example with a LightBox-like effect: you will be then able to show different contents (TFrame instances) using the same visual effect (“lightbox” stand). The benefits are quite obvious, for example you have to implement the visual effect (stand) just once and then you can reuse it and, doing so, any change (improvement) made on the stand will affect every part of your application that is using it (consistency!).
Same TFrame, different stand(s)
Imagine to have a set of stands that help the user recognize the context you are showing some content (TFrames). For example, you can have a stand that clearly marks the content as something related to an error notification, another stand for warning situations and another one for when the user action is required (confirmations, choices, and so on). If you have a specific TFrame to perform some task and show the results to the user, you may want to show it to the user using different flavors (stands!). Please keep in mind that you can now use these flavor-based with whatever TFrame class you want (for example, these TFrame classes does not need to have some inheritance dependency or any other relationship) and that you are able to determine which stand to use each time you need to show the TFrame.
In a real-world application, you will face a lot of situations that falls in these two cases but also many others that are a mixture of the two or somewhere in between. It mostly depends on how you slice your application using TFrame(s).
So far, we have identified a couple of benefits in this approach that are: splitting the complexity of an application using TFrame(s) and using TFrameStand component to somehow decouple the way the frame should be shown from the specific frame content.
There are some other benefits that come in when using TFrameStand, let me produce a list of the main ones:
- you can work at design time both on the TFrame and the stand(s);
- there is a built-in support to run a task in background (using the Parallel Programming Library internally) and in the meanwhile show a piece of UI (stand+TFrame) to the user and have it hidden once the task has completed;
- TFrameStand is able to autostart some animations (FMX TAnimation descendant) that are contained into the stand or the TFrame instance; two events are supported: Show and Hide (this means you can use transition in the process of showing and hiding the stands and the frames, easily and without a single line of code);
- there is a (simple) dependency injection mechanism that allows you to easily gain a reference to context objects from within the TFrame code; this means that you are able, for example, to hide (close) the stand from a button on the TFrame that is showed or to do that programmatically;
- there is a way to represent shared behaviors (pieces of code, actions) across different stand/TFrame combinations, in order not to replicate them just because you are using a specific stand or a specific TFrame class;
- there is a (highly customizable) way to override the actual TFrame class being used at runtime; this means that you can code against a TFrame superclass and have a specific descendant class being used at runtime according to a completely custom selection algorithm you can implement (for example, you may want to use different descendant-classes on a per-platform basis);
More blog posts will come to cover this functionalities but if you are impatient (and I hope you are) feel free to check the demo projects by yourself or have a look at the four small videos (actually animated gifs) at the bottom of this blog post.
Most of main functionalities are covered by demos and more will come.
Last but not the least, you will notice that a couple of demos are related to Google’s Material design: using TFrameStand is possible (easier) to implement some Material design elements in FMX applications (in the ViewAndDialogs demo is implemented a transition taken from the official guidelines by Google), a very demanded topic during my activity as trainer and consultant to other Delphi developers.
Here are four videos showing the running demos:
Enjoy (and please give me some feedback!) 🙂