Delphi 默认字体大小不会对我们不利 Drawable.Font.Size:=10+随机(4)*4; Drawable.TagFloat:=Drawable.Font.Size; 如果Text.Length ItemAppearanceObjects.ItemEditObjects.ObjectsCollection=< 项目 AppearanceObjectName='Text1' AppearanceClassName='TTextObjectAppearance' 结束> 结束 对象工具栏1:t工具栏 Padding.Top=4.000000000000000000000000 Padding.Bottom=4.000000000000000000000000 大小.宽度=510.000000000000000000 大小.高度=44.000000000000000000000000 Size.PlatformDefault=False TabOrder=1 对象标签1:TLabel 对齐=内容 大小.宽度=510.000000000000000000 大小.高度=44.000000000000000000000000 Size.PlatformDefault=False StyleLookup='toollabel' TextSettings.HorzAlign=Center Text='可变行高演示' 结束 对象按钮1:t按钮 对齐=右 页边距。右侧=5.000000000000000000000000 位置X=448.000000000000000000000000000000 位置Y=4.000000000000000000000000 大小.宽度=57.000000000000000000 大小.高度=36.000000000000000000000000 Size.PlatformDefault=False StyleLookup='listitembutton' TabOrder=1 Text='填充列表' OnClick=按钮1单击 结束 结束 结束 你的循环中只有一个输入错误。@Olivier,你能说得具体点吗。我检查了它哪一个是打字错误?在Items数组中使用I代替1。 unit MainForm; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.Generics.Collections, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls, FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base, FMX.ListView, Markov; type TVariableHeight = class(TForm) Button1: TButton; ListView1: TListView; ToolBar1: TToolBar; Label1: TLabel; procedure Button1Click(Sender: TObject); procedure ListView1UpdateObjects(const Sender: TObject; const AItem: TListViewItem); private FChain: TChain; FBitmaps: TDictionary<Integer, TBitmap>; FText: TArray<string>; procedure ReadText; function GetDimensionBitmap(const Width, Height: Single): TBitmap; public function GetTextHeight(const D: TListItemText; const Width: Single; const Text: string): Integer; destructor Destroy; override; end; var VariableHeight: TVariableHeight; implementation uses System.IOUtils, FMX.TextLayout; {$R *.fmx} // Create a new item with random text of random length procedure TVariableHeight.Button1Click(Sender: TObject); begin ReadText; ListView1.Items.Add.Data['txtMain'] := FText[Random(Length(FText))]; // with classic appearances, use Text property //ListView1.Items.Add.Text := FChain.Generate(Random(100) + 5); end; function TVariableHeight.GetDimensionBitmap(const Width, Height: Single): TBitmap; procedure Arrow(C: TCanvas; P: array of TPointF); begin C.DrawLine(P[0], P[1], 1.0); C.DrawLine(P[0], P[2], 1.0); C.DrawLine(P[0], P[3], 1.0); end; var EndP1, EndP2: TPointF; TextBitmap: TBitmap; IntHeight: Integer; begin IntHeight := Trunc(Height); if FBitmaps = nil then FBitmaps := TDictionary<Integer, TBitmap>.Create; if not FBitmaps.TryGetValue(IntHeight, Result) then begin Result := TBitmap.Create(Trunc(Width), IntHeight); FBitmaps.Add(IntHeight, Result); if Result.Canvas.BeginScene then begin Result.Canvas.Clear(TAlphaColorRec.Null); Result.Canvas.Stroke.Color := TAlphaColorRec.Darkgray; // Draw the arrows EndP1 := TPointF.Create(Width/2, 0); EndP2 := TPointF.Create(Width/2, Height); Arrow(Result.Canvas, [EndP1, TPointF.Create(Width/2, Height/2 - Width/2), EndP1 + TPointF.Create(-2, 5), EndP1 + TPointF.Create(2, 5)]); Arrow(Result.Canvas, [EndP2, TPointF.Create(Width/2, Height/2 + Width/2), EndP2 + TPointF.Create(-2, -5), EndP2 + TPointF.Create(2, -5)]); // Draw the dimension text TextBitmap := TBitmap.Create(Trunc(Width), Trunc(Width)); try if TextBitmap.Canvas.BeginScene then with TextBitmap.Canvas do begin Clear(TAlphaColorRec.Null); Fill.Color := TAlphaColorRec.Darkgray; FillText(TextBitmap.BoundsF, ''.Format('%d', [IntHeight]), False, 1, [], TTextAlign.Center, TTextAlign.Center); EndScene; end; TextBitmap.Rotate(90); Result.Canvas.DrawBitmap(TextBitmap, TextBitmap.BoundsF, TextBitmap.BoundsF.CenterAt(Result.BoundsF), 1); finally TextBitmap.Free; end; Result.Canvas.EndScene; end; end; end; destructor TVariableHeight.Destroy; var Key: Integer; begin FChain.Free; if FBitmaps <> nil then for Key in FBitmaps.Keys do FBitmaps[Key].Free; FBitmaps.Free; inherited; end; // Calculate height for text drawable D function TVariableHeight.GetTextHeight(const D: TListItemText; const Width: single; const Text: string): Integer; var Layout: TTextLayout; begin // Create a TTextLayout to measure text dimensions Layout := TTextLayoutManager.DefaultTextLayout.Create; try Layout.BeginUpdate; try // Initialize layout parameters with those of the drawable Layout.Font.Assign(D.Font); Layout.VerticalAlign := D.TextVertAlign; Layout.HorizontalAlign := D.TextAlign; Layout.WordWrap := D.WordWrap; Layout.Trimming := D.Trimming; Layout.MaxSize := TPointF.Create(Width, TTextLayout.MaxLayoutSize.Y); Layout.Text := Text; finally Layout.EndUpdate; end; // Get layout height Result := Round(Layout.Height); // Add one em to the height Layout.Text := 'm'; Result := Result + Round(Layout.Height); finally Layout.Free; end; end; procedure TVariableHeight.ListView1UpdateObjects(const Sender: TObject; const AItem: TListViewItem); var Drawable: TListItemText; SizeImg: TListItemImage; Text: string; AvailableWidth: Single; begin SizeImg := TListItemImage(AItem.View.FindDrawable('imgSize')); AvailableWidth := TListView(Sender).Width - TListView(Sender).ItemSpaces.Left - TListView(Sender).ItemSpaces.Right - SizeImg.Width; ShowMessage(TListView(Sender).Height.ToString); // Find the text drawable which is used to calcualte item size. // For dynamic appearance, use item name. // For classic appearances use TListViewItem.TObjectNames.Text // Drawable := TListItemText(AItem.View.FindDrawable(TListViewItem.TObjectNames.Text)); Drawable := TListItemText(AItem.View.FindDrawable('txtMain')); Text := Drawable.Text; // Randomize the font when updating for the first time if Drawable.TagFloat = 0 then begin Drawable.Font.Size := 1; // Ensure that default font sizes do not play against us Drawable.Font.Size := 10 + Random(4) * 4; Drawable.TagFloat := Drawable.Font.Size; if Text.Length < 100 then Drawable.Font.Style := [TFontStyle.fsBold]; end; // Calculate item height based on text in the drawable AItem.Height := GetTextHeight(Drawable, AvailableWidth, Text); Drawable.Height := AItem.Height; Drawable.Width := AvailableWidth; SizeImg.OwnsBitmap := False; SizeImg.Bitmap := GetDimensionBitmap(SizeImg.Width, AItem.Height); end; procedure TVariableHeight.ReadText; const Delimiters: array of char = [#10, #13]; var Reader: TStreamReader; Stream: TResourceStream; begin if Length(FText) = 0 then begin Stream := TResourceStream.Create(HInstance, 'Blabla', RT_RCDATA); Reader := TStreamReader.Create(Stream); try FText := Reader.ReadToEnd.Split(Delimiters, TStringSplitOptions.ExcludeEmpty) finally Reader.Close; Reader.Free; Stream.Free; end; end; end; end. object VariableHeight: TVariableHeight Left = 0 Top = 0 Caption = 'VariableHeight' ClientHeight = 480 ClientWidth = 510 FormFactor.Width = 320 FormFactor.Height = 480 FormFactor.Devices = [Desktop] DesignerMasterStyle = 0 object ListView1: TListView ItemAppearanceClassName = 'TDynamicAppearance' ItemEditAppearanceClassName = 'TDynamicAppearance' HeaderAppearanceClassName = 'TListHeaderObjects' FooterAppearanceClassName = 'TListHeaderObjects' OnUpdateObjects = ListView1UpdateObjects Align = Client Size.Width = 510.000000000000000000 Size.Height = 436.000000000000000000 Size.PlatformDefault = False TabOrder = 0 ItemAppearanceObjects.ItemObjects.ObjectsCollection = < item AppearanceObjectName = 'txtMain' AppearanceClassName = 'TTextObjectAppearance' Appearance.TextAlign = Leading Appearance.WordWrap = True Appearance.Height = 44.000000000000000000 Appearance.VertAlign = Center end item AppearanceObjectName = 'imgSize' AppearanceClassName = 'TImageObjectAppearance' Appearance.ScalingMode = Original Appearance.Width = 30.000000000000000000 Appearance.Align = Trailing end> ItemAppearanceObjects.ItemEditObjects.ObjectsCollection = < item AppearanceObjectName = 'Text1' AppearanceClassName = 'TTextObjectAppearance' end> end object ToolBar1: TToolBar Padding.Top = 4.000000000000000000 Padding.Bottom = 4.000000000000000000 Size.Width = 510.000000000000000000 Size.Height = 44.000000000000000000 Size.PlatformDefault = False TabOrder = 1 object Label1: TLabel Align = Contents Size.Width = 510.000000000000000000 Size.Height = 44.000000000000000000 Size.PlatformDefault = False StyleLookup = 'toollabel' TextSettings.HorzAlign = Center Text = 'Variable Row Height Demo' end object Button1: TButton Align = Right Margins.Right = 5.000000000000000000 Position.X = 448.000000000000000000 Position.Y = 4.000000000000000000 Size.Width = 57.000000000000000000 Size.Height = 36.000000000000000000 Size.PlatformDefault = False StyleLookup = 'listitembutton' TabOrder = 1 Text = 'Fill List' OnClick = Button1Click end end end
.FMX文件Delphi 默认字体大小不会对我们不利 Drawable.Font.Size:=10+随机(4)*4; Drawable.TagFloat:=Drawable.Font.Size; 如果Text.Length ItemAppearanceObjects.ItemEditObjects.ObjectsCollection=< 项目 AppearanceObjectName='Text1' AppearanceClassName='TTextObjectAppearance' 结束> 结束 对象工具栏1:t工具栏 Padding.Top=4.000000000000000000000000 Padding.Bottom=4.000000000000000000000000 大小.宽度=510.000000000000000000 大小.高度=44.000000000000000000000000 Size.PlatformDefault=False TabOrder=1 对象标签1:TLabel 对齐=内容 大小.宽度=510.000000000000000000 大小.高度=44.000000000000000000000000 Size.PlatformDefault=False StyleLookup='toollabel' TextSettings.HorzAlign=Center Text='可变行高演示' 结束 对象按钮1:t按钮 对齐=右 页边距。右侧=5.000000000000000000000000 位置X=448.000000000000000000000000000000 位置Y=4.000000000000000000000000 大小.宽度=57.000000000000000000 大小.高度=36.000000000000000000000000 Size.PlatformDefault=False StyleLookup='listitembutton' TabOrder=1 Text='填充列表' OnClick=按钮1单击 结束 结束 结束 你的循环中只有一个输入错误。@Olivier,你能说得具体点吗。我检查了它哪一个是打字错误?在Items数组中使用I代替1。 unit MainForm; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.Generics.Collections, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls, FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base, FMX.ListView, Markov; type TVariableHeight = class(TForm) Button1: TButton; ListView1: TListView; ToolBar1: TToolBar; Label1: TLabel; procedure Button1Click(Sender: TObject); procedure ListView1UpdateObjects(const Sender: TObject; const AItem: TListViewItem); private FChain: TChain; FBitmaps: TDictionary<Integer, TBitmap>; FText: TArray<string>; procedure ReadText; function GetDimensionBitmap(const Width, Height: Single): TBitmap; public function GetTextHeight(const D: TListItemText; const Width: Single; const Text: string): Integer; destructor Destroy; override; end; var VariableHeight: TVariableHeight; implementation uses System.IOUtils, FMX.TextLayout; {$R *.fmx} // Create a new item with random text of random length procedure TVariableHeight.Button1Click(Sender: TObject); begin ReadText; ListView1.Items.Add.Data['txtMain'] := FText[Random(Length(FText))]; // with classic appearances, use Text property //ListView1.Items.Add.Text := FChain.Generate(Random(100) + 5); end; function TVariableHeight.GetDimensionBitmap(const Width, Height: Single): TBitmap; procedure Arrow(C: TCanvas; P: array of TPointF); begin C.DrawLine(P[0], P[1], 1.0); C.DrawLine(P[0], P[2], 1.0); C.DrawLine(P[0], P[3], 1.0); end; var EndP1, EndP2: TPointF; TextBitmap: TBitmap; IntHeight: Integer; begin IntHeight := Trunc(Height); if FBitmaps = nil then FBitmaps := TDictionary<Integer, TBitmap>.Create; if not FBitmaps.TryGetValue(IntHeight, Result) then begin Result := TBitmap.Create(Trunc(Width), IntHeight); FBitmaps.Add(IntHeight, Result); if Result.Canvas.BeginScene then begin Result.Canvas.Clear(TAlphaColorRec.Null); Result.Canvas.Stroke.Color := TAlphaColorRec.Darkgray; // Draw the arrows EndP1 := TPointF.Create(Width/2, 0); EndP2 := TPointF.Create(Width/2, Height); Arrow(Result.Canvas, [EndP1, TPointF.Create(Width/2, Height/2 - Width/2), EndP1 + TPointF.Create(-2, 5), EndP1 + TPointF.Create(2, 5)]); Arrow(Result.Canvas, [EndP2, TPointF.Create(Width/2, Height/2 + Width/2), EndP2 + TPointF.Create(-2, -5), EndP2 + TPointF.Create(2, -5)]); // Draw the dimension text TextBitmap := TBitmap.Create(Trunc(Width), Trunc(Width)); try if TextBitmap.Canvas.BeginScene then with TextBitmap.Canvas do begin Clear(TAlphaColorRec.Null); Fill.Color := TAlphaColorRec.Darkgray; FillText(TextBitmap.BoundsF, ''.Format('%d', [IntHeight]), False, 1, [], TTextAlign.Center, TTextAlign.Center); EndScene; end; TextBitmap.Rotate(90); Result.Canvas.DrawBitmap(TextBitmap, TextBitmap.BoundsF, TextBitmap.BoundsF.CenterAt(Result.BoundsF), 1); finally TextBitmap.Free; end; Result.Canvas.EndScene; end; end; end; destructor TVariableHeight.Destroy; var Key: Integer; begin FChain.Free; if FBitmaps <> nil then for Key in FBitmaps.Keys do FBitmaps[Key].Free; FBitmaps.Free; inherited; end; // Calculate height for text drawable D function TVariableHeight.GetTextHeight(const D: TListItemText; const Width: single; const Text: string): Integer; var Layout: TTextLayout; begin // Create a TTextLayout to measure text dimensions Layout := TTextLayoutManager.DefaultTextLayout.Create; try Layout.BeginUpdate; try // Initialize layout parameters with those of the drawable Layout.Font.Assign(D.Font); Layout.VerticalAlign := D.TextVertAlign; Layout.HorizontalAlign := D.TextAlign; Layout.WordWrap := D.WordWrap; Layout.Trimming := D.Trimming; Layout.MaxSize := TPointF.Create(Width, TTextLayout.MaxLayoutSize.Y); Layout.Text := Text; finally Layout.EndUpdate; end; // Get layout height Result := Round(Layout.Height); // Add one em to the height Layout.Text := 'm'; Result := Result + Round(Layout.Height); finally Layout.Free; end; end; procedure TVariableHeight.ListView1UpdateObjects(const Sender: TObject; const AItem: TListViewItem); var Drawable: TListItemText; SizeImg: TListItemImage; Text: string; AvailableWidth: Single; begin SizeImg := TListItemImage(AItem.View.FindDrawable('imgSize')); AvailableWidth := TListView(Sender).Width - TListView(Sender).ItemSpaces.Left - TListView(Sender).ItemSpaces.Right - SizeImg.Width; ShowMessage(TListView(Sender).Height.ToString); // Find the text drawable which is used to calcualte item size. // For dynamic appearance, use item name. // For classic appearances use TListViewItem.TObjectNames.Text // Drawable := TListItemText(AItem.View.FindDrawable(TListViewItem.TObjectNames.Text)); Drawable := TListItemText(AItem.View.FindDrawable('txtMain')); Text := Drawable.Text; // Randomize the font when updating for the first time if Drawable.TagFloat = 0 then begin Drawable.Font.Size := 1; // Ensure that default font sizes do not play against us Drawable.Font.Size := 10 + Random(4) * 4; Drawable.TagFloat := Drawable.Font.Size; if Text.Length < 100 then Drawable.Font.Style := [TFontStyle.fsBold]; end; // Calculate item height based on text in the drawable AItem.Height := GetTextHeight(Drawable, AvailableWidth, Text); Drawable.Height := AItem.Height; Drawable.Width := AvailableWidth; SizeImg.OwnsBitmap := False; SizeImg.Bitmap := GetDimensionBitmap(SizeImg.Width, AItem.Height); end; procedure TVariableHeight.ReadText; const Delimiters: array of char = [#10, #13]; var Reader: TStreamReader; Stream: TResourceStream; begin if Length(FText) = 0 then begin Stream := TResourceStream.Create(HInstance, 'Blabla', RT_RCDATA); Reader := TStreamReader.Create(Stream); try FText := Reader.ReadToEnd.Split(Delimiters, TStringSplitOptions.ExcludeEmpty) finally Reader.Close; Reader.Free; Stream.Free; end; end; end; end. object VariableHeight: TVariableHeight Left = 0 Top = 0 Caption = 'VariableHeight' ClientHeight = 480 ClientWidth = 510 FormFactor.Width = 320 FormFactor.Height = 480 FormFactor.Devices = [Desktop] DesignerMasterStyle = 0 object ListView1: TListView ItemAppearanceClassName = 'TDynamicAppearance' ItemEditAppearanceClassName = 'TDynamicAppearance' HeaderAppearanceClassName = 'TListHeaderObjects' FooterAppearanceClassName = 'TListHeaderObjects' OnUpdateObjects = ListView1UpdateObjects Align = Client Size.Width = 510.000000000000000000 Size.Height = 436.000000000000000000 Size.PlatformDefault = False TabOrder = 0 ItemAppearanceObjects.ItemObjects.ObjectsCollection = < item AppearanceObjectName = 'txtMain' AppearanceClassName = 'TTextObjectAppearance' Appearance.TextAlign = Leading Appearance.WordWrap = True Appearance.Height = 44.000000000000000000 Appearance.VertAlign = Center end item AppearanceObjectName = 'imgSize' AppearanceClassName = 'TImageObjectAppearance' Appearance.ScalingMode = Original Appearance.Width = 30.000000000000000000 Appearance.Align = Trailing end> ItemAppearanceObjects.ItemEditObjects.ObjectsCollection = < item AppearanceObjectName = 'Text1' AppearanceClassName = 'TTextObjectAppearance' end> end object ToolBar1: TToolBar Padding.Top = 4.000000000000000000 Padding.Bottom = 4.000000000000000000 Size.Width = 510.000000000000000000 Size.Height = 44.000000000000000000 Size.PlatformDefault = False TabOrder = 1 object Label1: TLabel Align = Contents Size.Width = 510.000000000000000000 Size.Height = 44.000000000000000000 Size.PlatformDefault = False StyleLookup = 'toollabel' TextSettings.HorzAlign = Center Text = 'Variable Row Height Demo' end object Button1: TButton Align = Right Margins.Right = 5.000000000000000000 Position.X = 448.000000000000000000 Position.Y = 4.000000000000000000 Size.Width = 57.000000000000000000 Size.Height = 36.000000000000000000 Size.PlatformDefault = False StyleLookup = 'listitembutton' TabOrder = 1 Text = 'Fill List' OnClick = Button1Click end end end,delphi,firemonkey,tlistview,Delphi,Firemonkey,Tlistview,.FMX文件 object VariableHeight: TVariableHeight Left = 0 Top = 0 Caption = 'VariableHeight' ClientHeight = 480 ClientWidth = 510 FormFactor.Width = 320 FormFactor.Height = 480 FormFactor.Devices = [Desktop] DesignerMasterStyle = 0 o
object VariableHeight: TVariableHeight
Left = 0
Top = 0
Caption = 'VariableHeight'
ClientHeight = 480
ClientWidth = 510
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
DesignerMasterStyle = 0
object ListView1: TListView
ItemAppearanceClassName = 'TDynamicAppearance'
ItemEditAppearanceClassName = 'TDynamicAppearance'
HeaderAppearanceClassName = 'TListHeaderObjects'
FooterAppearanceClassName = 'TListHeaderObjects'
OnUpdateObjects = ListView1UpdateObjects
Align = Client
Size.Width = 510.000000000000000000
Size.Height = 436.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
ItemAppearanceObjects.ItemObjects.ObjectsCollection = <
item
AppearanceObjectName = 'txtMain'
AppearanceClassName = 'TTextObjectAppearance'
Appearance.TextAlign = Leading
Appearance.WordWrap = True
Appearance.Height = 44.000000000000000000
Appearance.VertAlign = Center
end
item
AppearanceObjectName = 'imgSize'
AppearanceClassName = 'TImageObjectAppearance'
Appearance.ScalingMode = Original
Appearance.Width = 30.000000000000000000
Appearance.Align = Trailing
end>
ItemAppearanceObjects.ItemEditObjects.ObjectsCollection = <
item
AppearanceObjectName = 'Text1'
AppearanceClassName = 'TTextObjectAppearance'
end>
end
object ToolBar1: TToolBar
Padding.Top = 4.000000000000000000
Padding.Bottom = 4.000000000000000000
Size.Width = 510.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
object Label1: TLabel
Align = Contents
Size.Width = 510.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
StyleLookup = 'toollabel'
TextSettings.HorzAlign = Center
Text = 'Variable Row Height Demo'
end
object Button1: TButton
Align = Right
Margins.Right = 5.000000000000000000
Position.X = 448.000000000000000000
Position.Y = 4.000000000000000000
Size.Width = 57.000000000000000000
Size.Height = 36.000000000000000000
Size.PlatformDefault = False
StyleLookup = 'listitembutton'
TabOrder = 1
Text = 'Fill List'
OnClick = Button1Click
end
end
end
对象可变高度:TVariableHeight
左=0
Top=0
标题='VariableHeight'
ClientHeight=480
ClientWidth=510
FormFactor.Width=320
FormFactor.Height=480
FormFactor.Devices=[桌面]
DesignerMasterStyle=0
对象列表视图1:TListView
ItemAppearanceClassName='TDynamicAppearance'
ItemEditAppearanceClassName='TDynamicAppearance'
HeaderAppearanceClassName='tListHeaderObject'
FooterAppearanceClassName='tListHeaderObject'
onUpdate对象=ListView1Update对象
Align=客户端
大小.宽度=510.000000000000000000
大小.高度=436.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Size.PlatformDefault=False
TabOrder=0
ItemAppearanceObjects.ItemObjects.ObjectsCollection=<
项目
AppearanceObjectName='txtMain'
AppearanceClassName='TTextObjectAppearance'
外观.TextAlign=前导
Appearance.WordWrap=True
外观.高度=44.000000000000000000000000
外观。垂直对齐=中心
结束
项目
AppearanceObjectName='imgSize'
AppearanceClassName='TImageObjectAppearance'
外观.缩放模式=原始
外观.宽度=30.000000000000000000000000
外观.Align=training
结束>
ItemAppearanceObjects.ItemEditObjects.ObjectsCollection=<
项目
AppearanceObjectName='Text1'
AppearanceClassName='TTextObjectAppearance'
结束>
结束
对象工具栏1:t工具栏
Padding.Top=4.000000000000000000000000
Padding.Bottom=4.000000000000000000000000
大小.宽度=510.000000000000000000
大小.高度=44.000000000000000000000000
Size.PlatformDefault=False
TabOrder=1
对象标签1:TLabel
对齐=内容
大小.宽度=510.000000000000000000
大小.高度=44.000000000000000000000000
Size.PlatformDefault=False
StyleLookup='toollabel'
TextSettings.HorzAlign=Center
Text='可变行高演示'
结束
对象按钮1:t按钮
对齐=右
页边距。右侧=5.000000000000000000000000
位置X=448.000000000000000000000000000000
位置Y=4.000000000000000000000000
大小.宽度=57.000000000000000000
大小.高度=36.000000000000000000000000
Size.PlatformDefault=False
StyleLookup='listitembutton'
TabOrder=1
Text='填充列表'
OnClick=按钮1单击
结束
结束
结束
你的循环中只有一个输入错误。@Olivier,你能说得具体点吗。我检查了它哪一个是打字错误?在Items数组中使用I代替1。
unit MainForm;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
System.Generics.Collections,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.Controls.Presentation, FMX.StdCtrls, FMX.ListView.Types,
FMX.ListView.Appearances, FMX.ListView.Adapters.Base, FMX.ListView,
Markov;
type
TVariableHeight = class(TForm)
Button1: TButton;
ListView1: TListView;
ToolBar1: TToolBar;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure ListView1UpdateObjects(const Sender: TObject;
const AItem: TListViewItem);
private
FChain: TChain;
FBitmaps: TDictionary<Integer, TBitmap>;
FText: TArray<string>;
procedure ReadText;
function GetDimensionBitmap(const Width, Height: Single): TBitmap;
public
function GetTextHeight(const D: TListItemText; const Width: Single; const Text: string): Integer;
destructor Destroy; override;
end;
var
VariableHeight: TVariableHeight;
implementation
uses
System.IOUtils, FMX.TextLayout;
{$R *.fmx}
// Create a new item with random text of random length
procedure TVariableHeight.Button1Click(Sender: TObject);
begin
ReadText;
ListView1.Items.Add.Data['txtMain'] := FText[Random(Length(FText))];
// with classic appearances, use Text property
//ListView1.Items.Add.Text := FChain.Generate(Random(100) + 5);
end;
function TVariableHeight.GetDimensionBitmap(const Width, Height: Single): TBitmap;
procedure Arrow(C: TCanvas; P: array of TPointF);
begin
C.DrawLine(P[0], P[1], 1.0);
C.DrawLine(P[0], P[2], 1.0);
C.DrawLine(P[0], P[3], 1.0);
end;
var
EndP1, EndP2: TPointF;
TextBitmap: TBitmap;
IntHeight: Integer;
begin
IntHeight := Trunc(Height);
if FBitmaps = nil then
FBitmaps := TDictionary<Integer, TBitmap>.Create;
if not FBitmaps.TryGetValue(IntHeight, Result) then
begin
Result := TBitmap.Create(Trunc(Width), IntHeight);
FBitmaps.Add(IntHeight, Result);
if Result.Canvas.BeginScene then
begin
Result.Canvas.Clear(TAlphaColorRec.Null);
Result.Canvas.Stroke.Color := TAlphaColorRec.Darkgray;
// Draw the arrows
EndP1 := TPointF.Create(Width/2, 0);
EndP2 := TPointF.Create(Width/2, Height);
Arrow(Result.Canvas,
[EndP1, TPointF.Create(Width/2, Height/2 - Width/2),
EndP1 + TPointF.Create(-2, 5), EndP1 + TPointF.Create(2, 5)]);
Arrow(Result.Canvas,
[EndP2, TPointF.Create(Width/2, Height/2 + Width/2),
EndP2 + TPointF.Create(-2, -5), EndP2 + TPointF.Create(2, -5)]);
// Draw the dimension text
TextBitmap := TBitmap.Create(Trunc(Width), Trunc(Width));
try
if TextBitmap.Canvas.BeginScene then
with TextBitmap.Canvas do
begin
Clear(TAlphaColorRec.Null);
Fill.Color := TAlphaColorRec.Darkgray;
FillText(TextBitmap.BoundsF, ''.Format('%d', [IntHeight]), False, 1,
[], TTextAlign.Center, TTextAlign.Center);
EndScene;
end;
TextBitmap.Rotate(90);
Result.Canvas.DrawBitmap(TextBitmap, TextBitmap.BoundsF,
TextBitmap.BoundsF.CenterAt(Result.BoundsF), 1);
finally
TextBitmap.Free;
end;
Result.Canvas.EndScene;
end;
end;
end;
destructor TVariableHeight.Destroy;
var
Key: Integer;
begin
FChain.Free;
if FBitmaps <> nil then
for Key in FBitmaps.Keys do
FBitmaps[Key].Free;
FBitmaps.Free;
inherited;
end;
// Calculate height for text drawable D
function TVariableHeight.GetTextHeight(const D: TListItemText; const Width: single; const Text: string): Integer;
var
Layout: TTextLayout;
begin
// Create a TTextLayout to measure text dimensions
Layout := TTextLayoutManager.DefaultTextLayout.Create;
try
Layout.BeginUpdate;
try
// Initialize layout parameters with those of the drawable
Layout.Font.Assign(D.Font);
Layout.VerticalAlign := D.TextVertAlign;
Layout.HorizontalAlign := D.TextAlign;
Layout.WordWrap := D.WordWrap;
Layout.Trimming := D.Trimming;
Layout.MaxSize := TPointF.Create(Width, TTextLayout.MaxLayoutSize.Y);
Layout.Text := Text;
finally
Layout.EndUpdate;
end;
// Get layout height
Result := Round(Layout.Height);
// Add one em to the height
Layout.Text := 'm';
Result := Result + Round(Layout.Height);
finally
Layout.Free;
end;
end;
procedure TVariableHeight.ListView1UpdateObjects(const Sender: TObject;
const AItem: TListViewItem);
var
Drawable: TListItemText;
SizeImg: TListItemImage;
Text: string;
AvailableWidth: Single;
begin
SizeImg := TListItemImage(AItem.View.FindDrawable('imgSize'));
AvailableWidth := TListView(Sender).Width - TListView(Sender).ItemSpaces.Left
- TListView(Sender).ItemSpaces.Right - SizeImg.Width;
ShowMessage(TListView(Sender).Height.ToString);
// Find the text drawable which is used to calcualte item size.
// For dynamic appearance, use item name.
// For classic appearances use TListViewItem.TObjectNames.Text
// Drawable := TListItemText(AItem.View.FindDrawable(TListViewItem.TObjectNames.Text));
Drawable := TListItemText(AItem.View.FindDrawable('txtMain'));
Text := Drawable.Text;
// Randomize the font when updating for the first time
if Drawable.TagFloat = 0 then
begin
Drawable.Font.Size := 1; // Ensure that default font sizes do not play against us
Drawable.Font.Size := 10 + Random(4) * 4;
Drawable.TagFloat := Drawable.Font.Size;
if Text.Length < 100 then
Drawable.Font.Style := [TFontStyle.fsBold];
end;
// Calculate item height based on text in the drawable
AItem.Height := GetTextHeight(Drawable, AvailableWidth, Text);
Drawable.Height := AItem.Height;
Drawable.Width := AvailableWidth;
SizeImg.OwnsBitmap := False;
SizeImg.Bitmap := GetDimensionBitmap(SizeImg.Width, AItem.Height);
end;
procedure TVariableHeight.ReadText;
const
Delimiters: array of char = [#10, #13];
var
Reader: TStreamReader;
Stream: TResourceStream;
begin
if Length(FText) = 0 then
begin
Stream := TResourceStream.Create(HInstance, 'Blabla', RT_RCDATA);
Reader := TStreamReader.Create(Stream);
try
FText := Reader.ReadToEnd.Split(Delimiters, TStringSplitOptions.ExcludeEmpty)
finally
Reader.Close;
Reader.Free;
Stream.Free;
end;
end;
end;
end.
object VariableHeight: TVariableHeight
Left = 0
Top = 0
Caption = 'VariableHeight'
ClientHeight = 480
ClientWidth = 510
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
DesignerMasterStyle = 0
object ListView1: TListView
ItemAppearanceClassName = 'TDynamicAppearance'
ItemEditAppearanceClassName = 'TDynamicAppearance'
HeaderAppearanceClassName = 'TListHeaderObjects'
FooterAppearanceClassName = 'TListHeaderObjects'
OnUpdateObjects = ListView1UpdateObjects
Align = Client
Size.Width = 510.000000000000000000
Size.Height = 436.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
ItemAppearanceObjects.ItemObjects.ObjectsCollection = <
item
AppearanceObjectName = 'txtMain'
AppearanceClassName = 'TTextObjectAppearance'
Appearance.TextAlign = Leading
Appearance.WordWrap = True
Appearance.Height = 44.000000000000000000
Appearance.VertAlign = Center
end
item
AppearanceObjectName = 'imgSize'
AppearanceClassName = 'TImageObjectAppearance'
Appearance.ScalingMode = Original
Appearance.Width = 30.000000000000000000
Appearance.Align = Trailing
end>
ItemAppearanceObjects.ItemEditObjects.ObjectsCollection = <
item
AppearanceObjectName = 'Text1'
AppearanceClassName = 'TTextObjectAppearance'
end>
end
object ToolBar1: TToolBar
Padding.Top = 4.000000000000000000
Padding.Bottom = 4.000000000000000000
Size.Width = 510.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
object Label1: TLabel
Align = Contents
Size.Width = 510.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
StyleLookup = 'toollabel'
TextSettings.HorzAlign = Center
Text = 'Variable Row Height Demo'
end
object Button1: TButton
Align = Right
Margins.Right = 5.000000000000000000
Position.X = 448.000000000000000000
Position.Y = 4.000000000000000000
Size.Width = 57.000000000000000000
Size.Height = 36.000000000000000000
Size.PlatformDefault = False
StyleLookup = 'listitembutton'
TabOrder = 1
Text = 'Fill List'
OnClick = Button1Click
end
end
end