【问题标题】:Resize a TLayout according to the number of labels in Firemonkey根据 Firemonkey 中的标签数量调整 TLayout 的大小
【发布时间】:2015-04-15 03:43:26
【问题描述】:

这是我在 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 是一个动态数组,其元素数量并不总是相同,因此我根据标签数量调整 TLayout (Layout1) 内容的 TPanel (Panel1) 大小;

Panel1.Height := Layout1.ChildrenRect.Height

当 Layout1 中的标签数量增加时,这可以正常工作,但是当标签数量较少时,Layout1.ChildrenRect.Height 没有效果并且不缩小它,Layout1 的高度始终保持较高的值。

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

【问题讨论】:

  • 您是说释放/删除控件后 ChildrenRect 是错误的吗?如果是这样,您如何释放它们以及在什么平台上释放它们?
  • 你好 Mike,我每次调用 Layout1.ChildrenRect.Height 之前都使用 Layout1.DeleteChildren 释放/删除控件,在 Windows 和 Android 上进行了测试。

标签: layout resize height firemonkey tpanel


【解决方案1】:

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

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;

【讨论】:

    【解决方案2】:

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

    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;
    

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

    【讨论】:

    • 非常感谢 Mike 的帮助,我在过去 3 天里一直在尝试提示并输入此代码 Layout1.DeleteChildren; Layout1.Size.Height := 0;似乎 Layout1.ChildrenRect.Height 重新计算大小,我认为它是不是最好的方法,而是一个临时解决方案。我认为您的解决方案是目前的解决方案。
    • 为什么不从答案中获取代码,删除对 AbsoluteRect 的调用并在 (0,0,0,0) 处初始化一个矩形?例程的其余部分应该可以正常工作,只需将 TControl 作为参数而不是隐式 Self。
    猜你喜欢
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    相关资源
    最近更新 更多