1
votes

I'm using this code to add an item to a listbox, but I can't figure out how to dynamically resize the height of the item to fit the text:

procedure TmForm.AddItemBtnClick(Sender: TObject);
var
  Item: TListBoxItem;
begin
  Item := TListBoxItem.Create(nil);
  Item.Parent := SomeListBox;
  Item.StyleLookup := 'listboxitemstyle';
  Item.Text :=
              'Pe cararea lunga scurta se ducea un om venind, si-n tacerea lui ' +
              'profunda se auzea borborosind. Cantr-o noapte intunecoasa soarel' +
              'e lucea pe cer, iara eu cu barca in casa ma plimbam ca un boier.';
  Item.WordWrap := true;
  Item.StyledSettings := [TStyledSetting.ssFamily] + [TStyledSetting.ssStyle] + [TStyledSetting.ssFontColor];
  Item.Font.Size := 14;
end;

I tried using the code from this example (modified for TListBoxItem), but it didn't work.

Edit: The height of the ListBoxItem can be set by just adding Item.Height := 100; at the end of the code above, but I need to know the height of text to decide what size the ListBoxItem needs to be, so to clarify my question, how do I get the height of the text in the list box item?

4

4 Answers

1
votes

Pop your resizing code in the OnApplyStyleLookup event.

Written off the top of my head and way past bedtime:

procedure TForm1.ListBoxItemApplyStyleLookup(Sender: TObject);
var O: TFMXObject;
begin
  O := (Sender as TListBoxItem).FindStyleResource('text');
  if O is TText then
    (Sender as TListBoxItem).Height := (O as TText).Height;
end;

You will, of course, need to set the event for every item you create.

1
votes

As mentioned by Mike Sutton, it can be done OnApplyStyleLookup event. I do it using a TTextLayout :

uses 
... ,FMX.TextLayout;

procedure TfrmForm1.ListBoxItem1ApplyStyleLookup(Sender: TObject);
var
  myLayout: TTextLayout;
  aPoint: TPointF;
begin

  myLayout := TTextLayoutManager.DefaultTextLayout.Create;
  myLayout.BeginUpdate;

  // Setting the layout MaxSize
  aPoint.X := ListBoxItem1.Width;
  aPoint.Y := TfrmForm1.Height;
  myLayout.MaxSize := aPoint;

  myLayout.Text := ListBoxItem1.Text;
  myLayout.WordWrap := True ;
  myLayout.Font := ListBoxItem1.Font;
  myLayout.HorizontalAlign := ListBoxItem1.TextSettings.HorzAlign;
  myLayout.VerticalAlign := ListBoxItem1.TextSettings.VertAlign;
  myLayout.Padding := ListBoxItem1.Padding;
  // set other properties as needed        

  myLayout.EndUpdate;

  ListBoxItem1.Height := Trunc(myLayout.TextHeight) + 3 ; // +3px to be sure to see entire text

end;

Note that MaxSize is limitating. For example, aPoint.Y will limit the final TextHeight. You should set it large because, whatever TextHeight should be, if myLayout.TextHeight is larger than myLayout.MaxSize.Y then myLayout.TextHeight will be set to myLayout.MaxSize.Y.

Here's a list of TTextLayout properties.

0
votes

Here is the Mike Sutton's code, improved and tested by me. Works for case of an Item with a Detail text (.ItemData.Detail). The variant with TextLayout did not work for me.

This code is tested for Windows and Android application.

procedure TTestForm.ListBoxItem1ApplyStyleLookup(Sender: TObject);
var item: TListBoxItem absolute Sender;

  function CalcHeight( SubStyle: String ): Single;
  var Obj: TFMXObject; T: TText absolute Obj;
  begin
    Obj := item.FindStyleResource(SubStyle);
    if Obj is TText
    then Result := T.Canvas.TextHeight(T.Text)
                 + T.Margins.Top + T.Margins.Bottom
                 + T.Padding.Top + T.Padding.Bottom
    else Result := 0;
  end;

begin
  item.Height := CalcHeight('text')
               + CalcHeight('detail');
end;
-1
votes

There are one important thing about changing size of control: "For mobile platform, firemonkey fix height and with some controls". Because:

  1. UI Style Guidline for each platform define rules about size of standart controls.
  2. Firemonkey uses raster style, so you cannot change some control size, because you will lost a quality of view

However, you can remove this contraints. Look at the my solution this (Auto translated with Google): Can not increase the height TProgressBar

This article about TProgressBar, But you can use this approach also for a TListBoxItem.