2

I'm making a RSS feed app with Delphi XE7 (Firemonkey) and the articles are displayed with a Listbox : (Text of ListBoxItem for titles and Details of ListBoxItem for articles). But as you can see in this screenshot:

1
(source: evolutiongraph.fr)

the articles are too long and do not come back to the line. The propertie WordWrap for ListBox doesn't exists. So I was looking for a way to solve this problem and I didn't find.

Can you help me ? And if it's impossible to do that way, can you propose me another way to display articles ? Thank you !

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
user54517
  • 2,020
  • 5
  • 30
  • 47

2 Answers2

4

Using a TListBox (as you did) :

At runtime, ListBoxItems already have a calculated style stored in aListBoxItem.StyledSettings. To change a setting at runtime, you first have to remove it from the list of styled settings.

For example, if you want to change the FontColor, first remove the 'styled' fontcolor:

aListboxItem.StyledSettings := aListboxItem.StyledSettings - [TStyledSetting.FontColor];

Then apply another one:

aListboxItem.FontColor := TAlphaColors.Green;

The WordWrap property is defined in TStyledSetting.Other. To change it:

aListboxItem.StyledSettings := aListboxItem.StyledSettings - [TStyledSetting.Other];

aListboxItem.WordWrap := True;

The TStyledSetting constants and corresponding TTextSettings properties are listed here in Delphi's doc.

On accessing TListBoxItem properties : theListBox.Items[i] gives access to item content, not the item itself. To grab a ListboxItem as a control, and then act on its properties, you can use:

aListboxItem := theListBox.ListItems[i]; 

or

aListboxItem := theListBox.ItemByIndex(i);

Both giving exactly the same result, I cannot say if one is better.

On text height : Once the text is wrapped in the control, you will probably need to adjust the control's height to show the entire text. This can be done OnApplyStyleLookup event, using a TTextLayout :

uses 
... ,FMX.TextLayout;

procedure TfrmForm1.ListBoxItem1ApplyStyleLookup(Sender: TObject);
var
  myLayout: TTextLayout;
  i: integer;
  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 ;

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.

N.B.: You may have to specify the font size at runtime before measuring the text height, or to set different from default at design time. On my testing device (Samsung Note 2), the default font size is measured 14 ( ListBoxItem1.Font.Size = 14 ) but it's rendered as 18. And it's not a scale issue. Then, the calculation for myLayout.TextHeight is done with Font.Size = 14 while the ListBoxItem will still render Font.Size = 18, still not fitting. It can be useful to reset Font.Size just before layout calculations by adding :

ListBoxItem1.StyledSettings := ListBoxItem1.StyledSettings - [TStyledSetting.Size] ;
ListBoxItem1.Font.Size := ListBoxItem1.Font.Size ;

Alternatively, you can use a TListView :

TListView is better suited for long lists and the WordWrap property can be set at design time. To find it in the Object Inspector go to :

ListView1 > ItemAppearanceObjects > ItemObjects > Text > WordWrap

Resizing will still be needed to fit the text height.


Examples of what can be done with ListBox and ListView in this CodeRage video. https://www.youtube.com/watch?v=XRj3qjUjBlc

  • Thanks a lot for taking your time to help me, I really appreciate. I'm reading your answere and I'll try all that. Thanks again. – user54517 Jul 22 '15 at 10:22
  • @user54517 : You're welcome. I just encountered the same issue few days ago and I managed to solve it. StackOverflow is SO useful for me, I really have to give back when I can. I would be pleased if it solves your problem. – Frédéric Hebrard Jul 22 '15 at 10:41
0

You can try to use ListBoxItem.WordWrap. More detail in site http://docwiki.embarcadero.com/

Try write similar function:

for I:= 0 To ListBox1.Items.Count - 1 Do
  ListBox1.Items[I].WordWrap := True;
androschuk.a
  • 289
  • 10
  • 22
  • As I said in my post, above, this property does not exists for the ListBox. I thought of a condition, but I don't know if it's correct : something like "If the length of the item is superior to the lenght of the screen, execute the WrapText fonction http://www.delphibasics.co.uk/RTL.asp?Name=WrapText (WrapText(string, LengthOfTheItem - Sreensize) – user54517 Feb 14 '15 at 10:03
  • It's not in the TListBox, it's in the TListBoxItem. Create each item in code and set it at creation time. – Mike Sutton Feb 14 '15 at 19:11
  • I do not create items manually, but dynamically : it's a RSS feed – user54517 Feb 14 '15 at 20:17
  • Why does it matter where you create the items? Manually or at designtime? Why does that change anything? – David Heffernan Feb 15 '15 at 10:13
  • Manually, when I put the ListBoxItem.TextSettings.WordWrap to True in the designer, it works perfectly. But when I do it with the code, it does not work. – user54517 Feb 15 '15 at 20:00
  • See also related question: [How to change properties of a TlistBoxItem in a android app in runtime?](http://stackoverflow.com/questions/27062707/how-to-change-properties-of-a-tlistboxitem-in-a-android-app-in-runtime) – androschuk.a Feb 16 '15 at 00:56
  • @user "It does not work" are the most useless 4 words in the history of problem description. We don't know what you did, we don't know what happened, we don't know how that failed to meet expections. It didn't work? So fix it. – David Heffernan Feb 16 '15 at 09:29
  • Hum...how to explain clearly...When I add a ListBoxItem with the designer, and then put the WordWrap property to True, the WordWrap is activated : it WORKS : http://www.evolutiongraph.fr/chevereto/images/2015/02/16/Capture.jpg But, when I put in my code the property to True, the WordWrap is not activated : it DOESN'T work http://www.evolutiongraph.fr/chevereto/images/2015/02/16/CaptureqXAbm.jpg – user54517 Feb 16 '15 at 14:14
  • Maybe if you set style options WordWrap is turned off. Check WordWrap after create manualy. `ShowMessage(BoolToStr(LItem.TextSettings.WordWarp))` – androschuk.a Feb 17 '15 at 03:17
  • I realize that when I change other properties, they are not taken into account. For exemple `LItem.TextSettings.Font.Size:=19;` does not change anything :( – user54517 Feb 17 '15 at 18:00
  • Look [this post](http://stackoverflow.com/questions/21360778/how-to-adjust-listbox-items-height-to-fit-the-text-in-firemonkey-android) maybe you will find answer. – androschuk.a Feb 18 '15 at 04:28
  • Nothing about WordWrap :( – user54517 Feb 18 '15 at 11:23
  • After days and days of research, I still have found nothing ... if anyone has an idea ... – user54517 Mar 11 '15 at 17:58