可以尝试以下策略:
- 使用 ScaledLayout 并将其 Align 属性设置为 Fit。我想您还必须在其子项上使用 Align := None 和 no Anchors。
- 将它放在面板内并将其设置为 Align:=Client。
- 将面板放置在表单中
就我而言,我想在 TScrollBox 布局内制作一个可缩放面板(保留纵横比),因此我在该面板上使用 Align:=Center 并以编程方式设置其缩放比例以进行缩放。
请注意,Embarcadero 的 ScaledLayout 示例在这种情况下具有误导性,因为它设置了 ScaledLayout 的比例(这与 ScaledLayout 在调整大小时的子级缩放功能无关 - 他们可以在 TPanel 或任何其他容器上设置 Scale)
另一个令人困惑的方面是 Align := Scale at controls 与 Scaling 无关,而是在父调整大小时保持其相对位置和相对大小(即它们不缩放显示,它们实际上调整大小)时调整子控件的大小。
更新:
我发现当使用上述策略放大/缩小时,滚动条的行为与预期相反。我意识到它与未调整大小的外部面板有关,而只是设置了它的比例(请注意,由于它在我的情况下位于滚动框中,因此我将其设置为 Align:=Center,而不是 Align:=Client 就像您在表单)
因此,我使用了另一个 TScaleLayout 而不是外部面板,因为它具有额外有用的属性 OriginalWidth/OriginalHeight 可以保持控件的原始大小。这是基于在放大/缩小时应用的新比例计算新大小所必需的(不使用它的 Scale 属性,因为 Embarcadero 的示例误导性地暗示,除了 Unit/-Unit 轴比例值以支持负比例 [aka轴翻转]):
procedure TForm2.FormCreate(Sender: TObject);
begin
BeginUpdate;
Zoomer.Align := TAlignLayout.Center; //at design mode we have it set to TAlignLayout.Client
UpdateZoomFromTrackbars;
EndUpdate;
end;
procedure TForm2.SetZoom(const Value: Single);
begin
SetZoom(Value, Value);
end;
procedure TForm2.SetZoom(const ValueX, ValueY: Single);
begin
if (ValueX <> 0) and (ValueY <>0) then //FMX has bug where Scale won't work anymore if set to 0
begin
BeginUpdate;
//update track bars
trackZoomX.BeginUpdate; trackZoomX.ValueRange.Value := ValueX; trackZoomX.EndUpdate;
trackZoomY.BeginUpdate; trackZoomY.ValueRange.Value := ValueY; trackZoomY.EndUpdate;
with Zoomer do
begin
Size.Size := TSizeF.Create(OriginalWidth * abs(ValueX), OriginalHeight * abs(ValueY)); //don't use Scale to resize (won't work well here), ScaledLayout scales its contents automatically
Scale.Point := TPointF.Create(sign(ValueX), sign(ValueY));
end;
//ScrollBox.InvalidateContentSize;
EndUpdate;
end;
end;
procedure TForm2.UpdateZoomFromTrackbars;
begin
SetZoom(trackZoomX.Value, trackZoomY.Value);
end;
procedure TForm2.ScrollBoxResize(Sender: TObject);
begin
var scrollBoxSize := ScrollBox.Size.Size;
if not scrollBoxSize.IsZero then
begin
BeginUpdate;
Zoomer.Size.Size := scrollBoxSize;
with Zoomer do
begin
OriginalWidth := Width;
OriginalHeight := Height;
end;
UpdateZoomFromTrackbars;
//ScrollBox.InvalidateContentSize;
EndUpdate;
end;
end;
procedure TForm2.trackZoomXTracking(Sender: TObject);
begin
if trackZoomX.IsUpdating then exit;
BeginUpdate;
if switchSyncAxes.IsChecked then
trackZoomY.Value := trackZoomX.Value;
UpdateZoomFromTrackbars;
EndUpdate;
end;
procedure TForm2.trackZoomYTracking(Sender: TObject);
begin
if trackZoomY.IsUpdating then exit;
BeginUpdate;
if switchSyncAxes.IsChecked then
trackZoomX.Value := trackZoomY.Value;
UpdateZoomFromTrackbars;
EndUpdate;
end;