Ответ косвенно был дан в теме Автоматический переход на вторую строку TLabel
Поэтому на базе этого ответа его легко модифицировать для этой задачи. Идея простая в момент загрузки стиля и изменения размеров TListBoxItem, вычислять высоту занимаемого текста и на основании этих данных переопределять высоту итема.
Практика
1. Для определения размеров текст используем TTextLayout. Лучше создавать объект этого класса один раз. Поскольку в нашем случае он будет использоваться часто.
procedure TForm1.FormCreate(Sender: TObject);
begin
// FTextLyout: TTextLayout - поле формы
FTextLyout := TTextLayoutManager.DefaultTextLayout.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FreeAndNil(FTextLyout);
end;
2. Пишем свой обработчик, который мы будем вызывать по достижению двух событий:
Изменение размера TListBoxItem. В этом случае нужно перевычислить высоту итема.
При загрузки нового стиля итема, нам нужно заново вычислить высоту итема. Поскольку стиль может содержать новые настройки отображения текста (шрифт, размер и тд.)
Я назвал это событие CalculateItemHeght:
procedure TForm1.CalculateItemHeight(Sender: TObject);
var
ListItem: TListBoxItem;
begin
if Sender is TListBoxItem then
begin
ListItem := Sender as TListBoxItem;
FTextLyout.BeginUpdate;
try
// Инициализируем текстовый слой для корректного вычисления
// размеров отображаемого текста
FTextLyout.Text := ListItem.Text;
FTextLyout.MaxSize := TPointF.Create(ListItem.Width, 1000);
FTextLyout.WordWrap := ListItem.WordWrap;
FTextLyout.Font := ListItem.Font;
FTextLyout.HorizontalAlign := ListItem.TextAlign;
FTextLyout.VerticalAlign := ListItem.VertTextAlign;
finally
FTextLyout.EndUpdate;
end;
// Получаем высоту текста при текущих настройках итема
ListItem.Height := FTextLyout.Height;
end;
end;
Обратите внимание, что этот код работает для горизонтальной ориентации TListBoxItem и обычного TListBoxItem итема без картинок. Поэтому я для упрощения понимания кода, принимаю за ширину текста ширину самого итема. Но как вы понимаете, текст в итеме имеет еще свои отступы и может располагаться, например, справа от изображения. В этом случае этот в этот код нужно будет добавить определение текущих размеров стилевого объекта текста, отвечающего за вывод текста в TListBoxItem.
Но в вашем примере этого не нужно.
3. Вешаем наш обработчик на два события каждого итема TListBoxItem.OnResize и TListBoxItem.OnApplyStyleLookup.
Результат