Reputation: 2420
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:
(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 !
Upvotes: 2
Views: 4268
Reputation: 99
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 ;
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
Upvotes: 4
Reputation: 289
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;
Upvotes: 0