根据 Firemonkey 中的标签数量调整 TLayout 的大小

Resize a TLayout according to the number of labels in Firemonkey

这是我在 Firemonkey 中的示例代码;

var
   f: integer; 
   Label1: TLabel;
   MyStringArray: TArray<String>;
   Panel1: TPanel;
   Layout1: TLayout;
begin
   Layout1.Align := TAlignLayout.Client;
   MyStringArray := ['aa','bb','cc','dd','ee','ff'];
   f:= 10;
   Layout1.BeginUpdate;
   for i := 0 to length(MyStringArray) - 1 do
   begin
        Label1 := TLabel.Create(Self);
        Label1.Name := 'Label' + i.ToString;
        Label1.Text := 'Label_' + MyStringArray[i];
        Label1.Position.Y := f;
        Label1.Align := TAlignLayout.Top;
        Label1.Parent := Layout1;
        inc(f, 15);
   end;
   Layout1.EndUpdate;
end; 

MyStringArray 是一个动态数组,并不总是具有相同数量的元素,因此我根据标签数量调整了 TPanel (Panel1) 的大小,其中包含 TLayout (Layout1) 的内容;

Panel1.Height := Layout1.ChildrenRect.Height

当Layout1的label数量增加时,这个可以正常工作,但是当label数量较少时,Layout1.ChildrenRect.Height没有效果,不会收缩,Layout1的高度总是保持较高的值。

是否有任何解决方案或其他替代方法?谢谢 问候。

我刚刚提交了以下错误报告。与此同时,我建议您自己计算边界,甚至可以从以下代码开始:

FMX TControl.ChildrenRect 的文档指出:

"指定当前控件的子控件所占据的矩形区域。 ChildrenRect 是通过对控件的子控件所占据的矩形进行并集运算得到的矩形。" - http://docwiki.embarcadero.com/Libraries/XE7/en/FMX.Controls.TControl.ChildrenRect

但是,代码实际上在计算中包含了它自己的边界:

function TControl.GetChildrenRect: TRectF;
var
  I: Integer;
  Control: TControl;
begin
  Result := AbsoluteRect;  <---*****This line
  { children }
  if not (ClipChildren or SmallSizeControl) and (FControls <> nil) then
    for I := GetFirstVisibleObjectIndex to GetLastVisibleObjectIndex - 1 do
    begin
      Control := FControls[I];
      if Control.Visible then
        Result := UnionRect(Result, Control.GetChildrenRect);
    end
end;

如果这是预期的行为,那么文档需要更新,否则就是实现中的错误。

我希望这段代码对此有所帮助。 对于更多的编辑,我深表歉意,这是最后一次,但我再次尝试,代码并不完全正确。

type
  TControlHelper = class helper for TControl
  public
    function ChildrenWidth: Single; 
    function ChildrenHeight: Single; 
  end;

function TControlHelper.ChildrenWidth: Single;
var
  VIndex: Integer;
  VControl: TControl;
  VRect: TRectF;
begin
  VRect := TRectF.Empty;
  if not ( ClipChildren or SmallSizeControl ) and ( Controls <> nil ) then
  begin
    for VIndex := GetFirstVisibleObjectIndex to GetLastVisibleObjectIndex - 1 do
    begin
      VControl := Controls[ VIndex ];
      if VControl.Visible then
        VRect := UnionRect( VRect, VControl.Margins.MarginRect( TRectF.Create( VControl.Position.Point, VControl.Width, VControl.Height ) ) );
    end;
    Result := VRect.Width + Padding.Right;
  end;
end;

function TControlHelper.ChildrenHeight: Single;
var
  VIndex: Integer;
  VControl: TControl;
  VRect: TRectF;
begin
  VRect := TRectF.Empty;
  if not ( ClipChildren or SmallSizeControl ) and ( Controls <> nil ) then
  begin
    for VIndex := GetFirstVisibleObjectIndex to GetLastVisibleObjectIndex - 1 do
    begin
      VControl := Controls[ VIndex ];
      if VControl.Visible then
        VRect := UnionRect( VRect, VControl.Margins.MarginRect( TRectF.Create( VControl.Position.Point, VControl.Width, VControl.Height ) ) );
    end;
    Result := VRect.Height + Padding.Bottom;
  end;
end;