user2088476
user2088476

Reputation: 613

Delphi Firemonkey TFlowLayout automatically adjust height to content

I am using a TFlowLayout to display a number of boxes. When the screen is resized the FlowLayout adjusts the number of boxes per line automatically. However I want to adjust the height of the surrounding element (TTreeViewItem) automatically. I achieved this by adding an event:

procedure TDeviceTreeView.DeviceTreeViewResize(Sender: TObject);
  begin
    height := ChildrenRect.Height;
  end;

This works halfways: the size is adjusted to grow when the elements in the flow layout need more lines. However it never shrinks.

Upvotes: 1

Views: 3702

Answers (2)

rodolfoThePig
rodolfoThePig

Reputation: 73

I know why. If you look at TControl.GetChildrenRect you will see:

function TControl.GetChildrenRect: TRectF;
var
  I: Integer;
  Control: TControl;
begin
  Result := AbsoluteRect;
  { 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;

Note that the base rectangle is:

 Result := AbsoluteRect;

And from that it will loop through the child controls, always adding (union) to the first rect. This causes the behavior you are experiencing: if the ChildControl's rect surpasses the FlowLayout's rect it increases, but will never decrease because the FlowLayout.AbsoluteRect is the starting rect in the function.

What you can do to solve that in a simple way is calculating the "ChildRect" yourself.

procedure TDeviceTreeView.DeviceTreeViewResize(Sender: TObject);
var childrenRect: TRectF;
begin
  if ((csLoading in FlowLayout1.ComponentState) = False) then // You might want to check for csLoading to avoid unecessary calls to resize
  begin
    childrenRect := TRectF.Empty;
    for i := 0 to FlowLayout1.ControlsCount - 1 do
      childrenRect := TRectF.Union(childrenRect, FlowLayout1.Controls[i].ChildrenRect);
    FlowLayout1.Height := childrenRect.Height;
  end;
end;

Upvotes: 2

Mariusz Pluciennik
Mariusz Pluciennik

Reputation: 107

You need to set TTreeViewItem property Align:alTop. In FMX it looks like: TTreeViewItem.Align:=talignlayout(1);

Upvotes: 0

Related Questions