如何设置TvertScollBox以滚动Delphi FireMonkey中的项目

时间:2018-03-25 23:15:17

标签: delphi firemonkey delphi-xe8

我在TFlowLayout内有一个TVertScrollbox的表单。

我在运行时用TFlowLayout填充了一些帧,这些帧可以有不同的高度。

我想将VertScrollBox.ContentBounds设置为能够从添加的第一帧滚动到最后一帧。

似乎我必须使用CalcContentBounds的{​​{1}}。我怎么能这样做?

TVertScrollBox

Unit1.pas

procedure TForm1.Button2Click(Sender: TObject);
var
  fr:TfrFrameItem;
  i:integer;
begin
  FlowLayout1.BeginUpdate;
  for i:=FlowLayout1.ControlsCount-1 downto 0 do begin
    FlowLayout1.Controls[i].Free;
  end;
  for i:=0 to 100 do begin
    fr:=TfrFrameItem.Create(FlowLayout1);
    fr.Name:='fr'+FlowLayout1.ControlsCount.ToString();
    fr.Parent:=FlowLayout1;
    fr.Visible:=True;
  end;
  FlowLayout1.EndUpdate;
  VertScrollBox1.RealignContent;
end;

procedure TForm1.VertScrollBox1CalcContentBounds(Sender: TObject;
  var ContentBounds: TRectF);
begin
  ContentBounds.Bottom:=?????
end;

Unit1.fmx

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Layouts,
  FMX.Controls.Presentation, FMX.StdCtrls,Math, FMX.Objects, FMX.Edit,
  FMX.ListBox, FMX.ScrollBox, FMX.Memo, FMX.TabControl, FMX.MultiView;

type
  TForm1 = class(TForm)
    VertScrollBox1: TVertScrollBox;
    FlowLayout1: TFlowLayout;
    Panel1: TPanel;
    ToolBar1: TToolBar;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation
uses uFrameitem;
{$R *.fmx}

procedure TForm1.Button2Click(Sender: TObject);
var
  lFrame:TfrFrameItem;
  i:integer;
  lHeight:single;
begin

  FlowLayout1.BeginUpdate;
  try
    for i := FlowLayout1.ControlsCount - 1 downto 0 do
      FlowLayout1.Controls[i].Free;

    lHeight := 0;
    for i := 0 to 100 do
    begin
     lFrame := TfrFrameItem.Create(FlowLayout1);
     lFrame.Name := 'fr' + FlowLayout1.ControlsCount.ToString;
     lFrame.Parent := FlowLayout1;
     lFrame.Visible := True;
     lHeight := Max(lHeight, lFrame.Position.Y + lFrame.Height);
    end;
    FlowLayout1.Height := lHeight;
  finally
    FlowLayout1.EndUpdate;
  end;
  VertScrollBox1.RealignContent;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var i:integer;
begin
  for i:=FlowLayout1.ControlsCount-1 downto 0 do begin
    FlowLayout1.Controls[i].Free;
  end;
end;

end.

uFrameItem.pas

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 647
  ClientWidth = 1057
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  OnDestroy = FormDestroy
  DesignerMasterStyle = 0
  object VertScrollBox1: TVertScrollBox
    Align = Client
    Size.Width = 1057.000000000000000000
    Size.Height = 568.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 0
    Viewport.Width = 1057.000000000000000000
    Viewport.Height = 568.000000000000000000
    object FlowLayout1: TFlowLayout
      Align = Top
      Size.Width = 1057.000000000000000000
      Size.Height = 177.000000000000000000
      Size.PlatformDefault = False
      TabOrder = 0
      Justify = Left
      JustifyLastLine = Left
      FlowDirection = LeftToRight
    end
  end
  object Panel1: TPanel
    Align = Bottom
    Position.Y = 608.000000000000000000
    Size.Width = 1057.000000000000000000
    Size.Height = 39.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 2
  end
  object ToolBar1: TToolBar
    Size.Width = 1057.000000000000000000
    Size.Height = 40.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 3
    object Button2: TButton
      Align = Right
      Position.X = 977.000000000000000000
      Size.Width = 80.000000000000000000
      Size.Height = 40.000000000000000000
      Size.PlatformDefault = False
      TabOrder = 0
      Text = 'Preencher'
      OnClick = Button2Click
    end
  end
end

uFrameItem.fmx

unit uFrameItem;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 
  FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls,
  FMX.Controls.Presentation, FMX.Objects, FMX.Layouts;

type
  TfrFrameItem = class(TFrame)
    Layout1: TLayout;
    Rectangle1: TRectangle;
    Label1: TLabel;
    Label2: TLabel;
    Label4: TLabel;
    Layout2: TLayout;
    Label3: TLabel;
    Label6: TLabel;
    Layout3: TLayout;
    Label7: TLabel;
    Label8: TLabel;
    Button1: TButton;
    Rectangle2: TRectangle;
    Label5: TLabel;
    procedure Layout2Resize(Sender: TObject);
    procedure Label2Resize(Sender: TObject);
  private
    { Private declarations }
    function ListChildren(Obj : TFMXObject; Level : Integer):double;
  public
    { Public declarations }
  end;

implementation

{$R *.fmx}

function TfrFrameItem.ListChildren(Obj : TFMXObject; Level : Integer):double;
var  i: Integer;
begin
  for i := 0 to Obj.ChildrenCount-1 do begin
    if Obj.Children[i].Tag=1 then begin
      if (Obj.Children[i] is TLayout) then
        result:=result+TLayout(Obj.Children[i]).Height;
      if (Obj.Children[i] is TLabel) then
        result:=result+TLabel(Obj.Children[i]).Height;
      if (Obj.Children[i] is TImageControl) then
        result:=result+TImageControl(Obj.Children[i]).Height;
      if (Obj.Children[i] is TButton) then
        result:=result+TButton(Obj.Children[i]).Height;
    end;
    result:=result+ListChildren(Obj.Children[i],Level+1);
  end;
end;

procedure TfrFrameItem.Label2Resize(Sender: TObject);
const
  ExtraHeigthOfLayout = 10;
var
  Lbl: TLabel;
  Layout: TLayout;
begin
  Layout2Resize(Sender);
end;

procedure TfrFrameItem.Layout2Resize(Sender: TObject);
const
  ExtraHeigthOfLayout = 10;
var
  Lay: Tlayout;
  Layout: TLayout;
  i:integer;
  hh:double;
begin
  hh:=ListChildren(Layout1,0);
  Layout1.Height:=hh+60;
end;

end.

1 个答案:

答案 0 :(得分:0)

您根本不需要更改TVertScrollBox。它会自动调整其内容。您只需要更改TFlowLayout的大小。在这种情况下,只要表单的大小发生变化,就必须重新计算大小。

因此,您必须将VertScrollBox1.RealignContent替换为Self.Resize,然后指定表单OnResize事件。

procedure TForm1.FormResize(Sender: TObject);
begin
  if FlowLayout1.ControlsCount > 0 then
    FlowLayout1.Height := FlowLayout1.Controls.Last.BoundsRect.Bottom
  else
    FlowLayout1.Height := VertScrollBox1.Height; 
end;