很久前就想写这篇了,一直没动手,因为懒,太懒。也没有动力,朋友们多收藏、多点赞可能动力会强些。

前言

这篇博客,说是界面布局(二),其实更确切的说应该是(一),今天主要内容是说FMX界面下可视控件的布局基础知识,也是一些基本的概念,也只有当你了解这些基础知识后,才能更好的应用界面布局。文章有点长,需要多花点时间阅读(写的时间比起阅读多同了N多倍)。

同时,我还在计划下一篇在 APP界面布局 中写什么内容( 朋友们可以留言,或是给点建议)。FMX 确实强大,越是深入的了解,越会为之倾倒。


那么再继续看后面内容前,需要请您注意

如果您是delphi老手(这里指以前做VCL,并且很熟练的朋友),那么,请先清空VCL的使用方法,以及VCL里窗体控件的排列思路,全新的去了解FMX,一定不要受固有思维的影响与局限;
如果您会Html、会CSS,那么您可能在学习时会发现很多似曾相识之处;
如果您是刚学习Delphi的朋友,那么恭喜你,你将直接达到那些使用多年Delphi朋友现今才达到的技术等级,更重要的是,您可能会更容易接受。
如果您有机会深入了解FMX,你会发现她的强大、她的美丽。

什么是FMX

FireMonkey(FMX)使用现代台式机或移动设备中的图形处理单元(GPU)在多个平台上创建视觉上能引人入胜的应用程序。

认识FireMonkey坐标系

在我们的“窗体设计器”中,坐标系的原点是左上角,一直延伸到右下角。每个坐标以单精度浮点数来表示。在所有支持的系统平台上都视为由若干像素组成的正方形,每一个坐标单位通常会映射到其中一个像素,但也会有一些例外。

  • 2D控件的Position属性是具有X和Y属性的TPosition。以Width(宽)和Height(高)属性代表控件的大小。
  • 3D对象使用带有附加Z属性的TPosition3D,正值指向屏幕(X指向左侧,Y指向下方,因此遵循“右手定则”);和深度(Depth)属性。通过位置和大小来共同定义描述控件的边界框。

FMX控件间的从属关系

FireMonkey控件间有三种从属关系:所有者、父级控件、子级控件。FMX里允许任何控件成为另一个控件的父级,也就是说他可以是其他任何控件的子级。(这与VCL的区别很大)

所有者

窗体通常拥有其中的所有控件,并且在窗体设计器中放置的控件都遵循这个约定。所有者是通用构造函数(Create)的第一个也是唯一的参数。

TFmxObject.Create(AOwner: TComponent)

通过代码创建控件时,如果控件打算保留到窗体直到窗体释放,则将窗体指定为控件的所有者。该窗体应该是已创建好的。所有者在释放自己时负责控件的释放。
对于需要临时使用的控件,在创建时可以指定nil为其所有者。然后,由代码在控件完成工作后去释放控件。控件使用过程中,不管是否会(是否有可能)出现异常,我通常建议使用try / finally块来确保控件能得到正确的释放。

父控件

为了使控件在窗体中显示,指定所有者是不够的。还必须将其放置在控件树中,可以是窗体的直接子元素,或放置在树的更下方。在“ 窗体设计器”中放置的控件会自动将其放置到控件树中,并且在“ 结构视图”控件树中显示。如果是通过代码创建控件时,需要将控件的Parent属性设置为窗体或对应的父级控件。

子控件

子控件的位置是相对于其父控件的。如果坐标为零,则子控件从父控件的左上角开始。子控件同时会自动继承父控件的部分属性。例如可见性,不透明度,旋转度和比例。更改父控件的这些属性会影响该子树中的所有子级。
控件的父子关系不限于类似容器的控件。还有,ClipChildren属性默认为False(如果为True,则不允许在控件的内容框中绘制子级)。这样就可以临时收集相关控件,而无需正式的容器控件。例如,TLabel可以是它对应的TEdit的子控件(相反也是可以的)。Label的坐标为负数时,其显示位置看上去是在TEdit控件之外。在移动TEdit时,他也会一起移动,并保持固定的相对位置。TLayout可以用作安放其他控件的功能性容器。

对齐(Align)

控件的对齐Align属性确定他在初始时以及在调整父控件大小时是否根据父控件的四个边或中心自动定位和(或)调整大小。它默认值为None,不会执行自动计算:控件将一直保留在原位置(相对于父控件)。该属性是TAlignLayout类型的枚举,具有其他多个使用值(TAlignLayout的介绍请参考我另一篇博客:《Delphi FMX窗体中控件对齐方式介绍》)。它们中的大多数会计算父控件中两个用于自动对齐的属性值:Padding(填充)和Margins(边距)。

填充(Padding)

填充是在作为父控件时,内容框的内部所留出空间。例如,如果控件“顶部(Top)”和“左侧(Left)”填充值均为10,则自动位于左上角的子控件的位置将设置为10,10。
更准确地说,自动定位的不是控件的内容框,而是其布局框。从Margins可以看出两者之间的区别,边距在控件的内容框外部留出空间,边距值增加或减少,布局框的尺寸始终会保持不变,如果受到空间大小的约束,则会缩小控件的内容框。回到10,10的示例,如果上下边距均为5,则控件的位置为15,15。
负填充将控件的内容框放置在其计算的布局框之外。

边距(Margins)

边距可设置由父级控件自动定位的控件之间的间距,而填充可确保这些控件与父级控件边缘之间的间距。对于边距和填充可以使用正值也可以使用负值。负边距将子级控件放置在父级的内容框之外,如果其 ClipChildren属性为False,则仍会显示它们。

delphi ANDROID移动应用程序连接到MSSQL delphi10开发安卓应用_delphi安卓开发


简单理解:边距负责控件外部布局框,填充负责控件内部的布局框,如上图。

注意: FireMonkey中的边距和填充的作用尊重CSS Box模型。如果你了解CSS,就较容易理解。

锚点(Anchors)

delphi ANDROID移动应用程序连接到MSSQL delphi10开发安卓应用_delphi app_02


当控件必须将其位置保持在距其父级边缘一定距离的位置,或者必须在保持其边缘与父级边缘之间的原始距离的同时拉伸时,需要使用锚。如果指定后,锚定的控件粘在容器的侧面并拉伸。使用Anchors属性设置控件的锚点,结合使用锚和嵌套容器,可以在FireMonkey中创建智能的可拉伸式布局。在运行时当调整父控件大小,锚定控件与其父控件的边缘之间保持设计时所指定的固定距离。在设计时,设置Anchors属性对窗体可能会没有视觉效果。

控件可以设置0-4个锚点,如果控件同时锚点固定到相对的边缘(Anchors = [akLeft,akRight]或Anchors = [akTop,akBottom]),则该控件将水平或垂直拉伸以保持与左侧或右侧、顶部或底部与其父对象的相对边缘保持固定的距离。控件可以锚定到其父级的所有4个边缘;在这种情况下,它会向各个方向延伸。默认情况下,控件固定在其容器的顶部和左侧边缘(Anchors = [akTop,akleft])。

使用对齐(Align属性)时,锚点会受到影响。

注意:请勿将滚动布局的子项(TScrollBox,TVertScrollBox等)锚定在右侧和底部边缘。如果将滚动布局子项的Anchors属性设置为akBottom,akRight或两者都设置,则在计算布局内容大小时,子项将继续拉伸以保持与布局边缘的固定距离。滚动布局的子级应仅锚定在左侧和顶部边缘。

缩放(Scale)和旋转(RotationAngle)

缩放和旋转两个常用属性会影响控件的最终渲染位置。

注意:缩放和旋转不会更改控件的位置或大小属性。
2D与3D控件的Scale属性由各自的实例表示:2D对象使用TPosition,3D对象使用TPosition3D。

delphi ANDROID移动应用程序连接到MSSQL delphi10开发安卓应用_界面布局设计_03


2D对象TPosition

delphi ANDROID移动应用程序连接到MSSQL delphi10开发安卓应用_界面布局设计_04


3D对象TPosition3D

其X,Y和Z值默认为1,这意味着该对象在所有维度上均未缩放。比例值是每个轴上的一个简单乘数。大于1的值将沿该轴延伸。小于1但大于零的值将沿该轴收缩或压缩。将任何轴缩设置为零将导致控件消失。按控件比例缩放时,需要将所有轴上的值设置为相同。

2D缩放始终从控件的原点(其内容框的左上方)锚定。负比例缩放以该原点为中心。例如,负X比例将导致控件向左下方渲染,并在内容框的左边缘翻转。3D缩放是从对象的中心开始的。

在2D旋转中,枢轴是可调的。所述RotationCenter属性也是TPosition,该值坐标:0,0表示左上角控制,当值设置为1,1后表示同右下角控制。默认为控件的中心,坐标值为:0.5,0.5。内容框的长宽比无关紧要。在该枢轴点上,RotationAngle以度为单位,顺时针旋转。

delphi ANDROID移动应用程序连接到MSSQL delphi10开发安卓应用_控件_05


在3D中,旋转始终从中心开始,其中RotationAngle为TPosition3D,在X,Y和Z轴上指定角度。旋转也遵循右手法则;例如,当X和Y旋转为零时,Z轴指向屏幕,Z轴上的正旋转顺时针旋转。

在2D中,需要注意,先缩放后旋转,因为缩放是始终从原点开始,并且旋转的枢轴是可调整的。在3D中,两者都从中心发生,因此顺序无关紧要。

使用FireMonkey的布局控件

FireMonkey布局控件用于对其他控件进行分组管理或控制,这是将它们作为一个整体进行排列和操作的容器。FireMonkey布局控件是非可视组件。较为复杂的界面,使用布局与前面介绍的一种或多种控件设置方式组合,则无需使用复杂的数学计算。

预定义布局控件

用于子控件的预定义布局的布局控件:
TFlowLayout:排列其子控件,就好像它们是段落中的单词一样。
TGridLayout:在大小相等的单元网格中排列子控件。所有控件都会自动调整大小以适合单元格。使用这种布局时,将自动设置控件的对齐、位置和锚点属性,不能显式更改这些属性。使用TGridLayout时,控件的大小会受到影响并自动设置。
TGridPanelLayout:在网格面板中排列子控件。每个控件都放置在网格上的一个单元格内,但是您可以手动调整单元格内控件的大小。您可以指定一个控件可以跨越多个单元格。

滚动框布局控件

FireMonkey还提供了几种滚动框布局控件,滚动区域可包含较多的子控件。

滚动布局用于将多个控件(例如按钮,列表框,编辑框,单选按钮等)归为同一组可滚动父对象:

TScrollBox-基础的滚动布局控件。
THorzScrollBox-限于水平滚动的布局控件。
TVertScrollBox-限于垂直滚动的布局控件。
TFramedScrollBox-其背景与周围的框架不透明。
TFramedVertScrollBox-与周围的框架具有不透明的背景。
使用滚动框布局,窗体可以包含许多组织在可滚动区域中的控件,以便在窗体上占用更少的空间。滚动框的另一种用法是在一个窗体中创建多个滚动区域(视图)。这样的视图在商业文字处理器,电子表格和项目管理应用程序中很常见。

在iOS,Mac OS和Android上,滚动视图响应手势的速度和方向,以让人感觉自然的方式显示内容。FireMonkey提供了InertialMovement单元,可在Windows下实现滚动视图的平滑惯性移动。在TAniCalculations类中设置惯性滚动属性,可以自定义滚动视图响应于触摸输入(使用鼠标或手指)的惯性移动行为。使用TAniCalculations类,您可以在Windows平台上模拟滚动视图的平滑惯性移动。

相关或类似文章

1、Delphi D10.3 LayoutsPro 控件简介 -避免输入焦点被虚拟键盘遮挡 推荐到这里,不是因为控件,是因为这个DEMO里有较多的可用于界面布局学习的内容;

2、Delphi D10.1 移动开发中APP界面基本布局(一) 这就是文章前面提到的(一)。

3、Delphi D10.X VCL和FireMonkey之间的常见差异介绍