Перейти к содержанию
Fire Monkey от А до Я
  • 0

[TListBox] Как отобразить итемы в виде панелей?


uakmal

Вопрос

Рекомендуемые сообщения

  • 0
  • Администраторы

Вы бы не стеснялись и добавляли свои проекты со скриншотами в раздел http://fire-monkey.ru/forum/18-prilozheniia-napisannye-s-ispolzovaniem-firemonkey/

Ссылка на комментарий
  • 0

 

И да, еще один важный момент!

Вы можете в ListBoxItem легко и просто помещать любые элементы, что очень (очень!) сильно упрощает процесс проектирования/создания интерфейса.

attachicon.gif14.jpg

 

З.Ы. отмечу, однако, что не стоит злоупотреблять кол-вом компонентов, размещенных на ListBoxItem - это, как-раз, повлечет "тормоза" при отрисовке. )

 

Что за проект? Если не трудно скинь код реализации панелей в listbox.  Заранее спасибо!

 

Проект.

Кусок стиля:

  object TLayout
    StyleName = 'listboxitemmessagestylelight'
    EnableDragHighlight = False
    Padding.Left = 4.000000000000000000
    Padding.Top = 4.000000000000000000
    Padding.Right = 4.000000000000000000
    Padding.Bottom = 4.000000000000000000
    Position.X = 416.000000000000000000
    Position.Y = 392.000000000000000000
    Size.Width = 220.000000000000000000
    Size.Height = 70.000000000000000000
    Size.PlatformDefault = False
    Visible = False
    TabOrder = 91
    object TRectangle
      StyleName = 'rectMain'
      Align = Contents
      Corners = []
      EnableDragHighlight = False
      Fill.Color = claWhite
      HitTest = False
      Size.Width = 220.000000000000000000
      Size.Height = 70.000000000000000000
      Size.PlatformDefault = False
    end
    object TText
      StyleName = 'detail'
      Align = Client
      ClipChildren = True
      Cursor = crHandPoint
      EnableDragHighlight = False
      HitTest = False
      Margins.Right = 22.000000000000000000
      Size.Width = 136.000000000000000000
      Size.Height = 36.000000000000000000
      Size.PlatformDefault = False
      TextSettings.Trimming = Character
    end
    object TActiveStyleTextObject
      StyleName = 'text'
      Align = Top
      EnableDragHighlight = False
      Margins.Right = 22.000000000000000000
      Position.X = 58.000000000000000000
      Position.Y = 4.000000000000000000
      Size.Width = 136.000000000000000000
      Size.Height = 26.000000000000000000
      Size.PlatformDefault = False
      TextSettings.Font.Style = [fsBold]
      TextSettings.Trimming = Character
      TextSettings.WordWrap = False
      Shadow.Color = claBlack
      Shadow.Offset.XI = 1
      Shadow.Offset.YI = 1
      ShadowVisible = False
      ActiveTrigger = Selected
      ActiveColor = claBlack
      ActiveShadow.Color = claBlack
      ActiveShadow.Offset.XI = 1
      ActiveShadow.Offset.YI = 1
    end
    object TCircle
      StyleName = 'roundavatar'
      Align = MostLeft
      EnableDragHighlight = False
      Fill.Bitmap.WrapMode = TileStretch
      Fill.Kind = Bitmap
      HitTest = False
      Margins.Left = 2.000000000000000000
      Margins.Right = 4.000000000000000000
      Position.X = 6.000000000000000000
      Position.Y = 4.000000000000000000
      Size.Width = 48.000000000000000000
      Size.Height = 62.000000000000000000
      Size.PlatformDefault = False
      Stroke.Color = claGray
      Stroke.Thickness = 2.000000000000000000
    end
    object TText
      StyleName = 'btnclosemessage'
      Anchors = [akTop, akRight]
      EnableDragHighlight = False
      Opacity = 1.000000000000000000
      Position.X = 194.000000000000000000
      Position.Y = 4.000000000000000000
      Size.Width = 26.000000000000000000
      Size.Height = 26.000000000000000000
      Size.PlatformDefault = False
      Text = #58882
      TextSettings.Font.Family = 'spherelive'
      TextSettings.Font.Size = 26.000000000000000000
      TextSettings.WordWrap = False
    end
  end

Фрагменты кода:

procedure TfmMissMessages.MissMessageApplyStyle(Sender: TObject);
var
  StyleObject : TFmxObject;
begin
  (Sender as TListBoxItem).OnClick := MessageItemClick;

  StyleObject := TListBoxItem(Sender).FindStyleResource('btnclosemessage') as TText;
  if Assigned(StyleObject) then
    TText(StyleObject).OnClick := DelMissMessageItemClick;

  StyleObject := TListBoxItem(Sender).FindStyleResource('roundavatar') as TCircle;
  if Assigned(StyleObject) then
    try
      TCircle(StyleObject).Fill.Bitmap.Bitmap.Canvas.BeginScene();
      TCircle(StyleObject).Fill.Bitmap.Bitmap := {тут ваш битмап};
    finally
      TCircle(StyleObject).Fill.Bitmap.Bitmap.Canvas.EndScene;
    end;
end;

procedure TfmMissMessages.AddMissMessageItem(......... AText: string);
var
  newItem : TListBoxItem;
  newHeight : Integer;
  StyleObject: TFmxObject;
begin
  ..........

  newItem := TListBoxItem.Create(nil);
  newItem.AutoTranslate := False;
  newItem.ClipChildren := True;
  newItem.CanFocus := False;
  newItem.EnableDragHighlight := False;
  newItem.Height := C_HeightItemMessage;
  newItem.Margins.Bottom := 5;
  newItem.StyledSettings := [TStyledSetting.Family, TStyledSetting.Style, TStyledSetting.FontColor];
  newItem.TextSettings.HorzAlign := TTextAlign.Center;
  newItem.Text := AText;
  newItem.HitTest := True;
  newItem.OnClick := MessageItemClick;
  newItem.OnApplyStyleLookup := MissMessageApplyStyle;

  StyleObject := newItem.FindStyleResource('btnclosemessage') as TText;
  if Assigned(StyleObject) then
    TText(StyleObject).OnClick := DelMissMessageItemClick;

  StyleObject := newItem.FindStyleResource('roundavatar') as TCircle;
  if Assigned(StyleObject) then
    try
      TCircle(StyleObject).Fill.Bitmap.Bitmap.Canvas.BeginScene();
      TCircle(StyleObject).Fill.Bitmap.Bitmap := {тут ваш битмап};
    finally
      TCircle(StyleObject).Fill.Bitmap.Bitmap.Canvas.EndScene;
    end;

  lbxMissMessage.BeginUpdate;
  lbxMissMessage.AddObject(newItem);
  lbxMissMessage.EndUpdate;
end;

procedure TfmMissMessages.DelMissMessageItem(Sender: TListBoxItem);
var
  newHeight : Integer;
begin
  if not Assigned(Sender as TListBoxItem) then
    Exit;
  .............
  lbxMissMessage.Items.Delete(TListBoxItem(Sender).Index);
end;

Извините, некоторые фрагменты кода удалены... Но думаю и так будет все понятно.

Изменено пользователем AlexG
Ссылка на комментарий
  • 0

Я не спорю насчет удобности реализации, тут листвью не конкурент листбоксу. Просто в мобильных платформах Листбокс очень сильно проседает (подтормаживает при скролах), если много элементов.

Ссылка на комментарий
  • 0

Я не спорю насчет удобности реализации, тут листвью не конкурент листбоксу. Просто в мобильных платформах Листбокс очень сильно проседает (подтормаживает при скролах), если много элементов.

Согласен, согласен.

Ссылка на комментарий
  • 0

Интересно, что стилизованный ListBox не скролится под iOS в полноэкранном режиме. Можно проверить на примере http://fire-monkey.ru/topic/1456-tlistbox-kak-otobrazit-itemy-v-vide-panelei/#entry7419

Пробовал BorderStyle с None, так и FullScreen:=True как в данном примере http://cc.embarcadero.com/item/30023. На Android проблем с прокруткой нет.

Изменено пользователем Andrew
Ссылка на комментарий
  • 0

Не смотрел ваш пример, но у меня ListBox нормально скролится на IOS. BorderStyle = None.

Использовал пример пользователя enatechno: http://fire-monkey.ru/topic/1456-tlistbox-kak-otobrazit-itemy-v-vide-panelei/#entry7419

В моих примерах тоже самое. Если в ListBoxItem имеется, например, TRectangle с включеным свойством HitTest=True, прокрутка не будет работать в полноэкранном режиме iOS. Проверялось на iOS 6, 7 и 8. Стоит вернуть для BorderStyle = Sizeable - прокрутка снова работает. Поэтому для полноэкранного приложения пришлось отказаться от OnClick/OnTap и использовать OnChange.

Изменено пользователем Andrew
Ссылка на комментарий
  • 0

P.S. TGridLayout не лучший выбор при большом количестве итемов. Так как листбокс реально грузит стили только для видимой части итемов. И при прокрутке только меняет стили местами. А TGridLayout загрузит все элементы. В итоге проигрышь по памяти и по скорости.

Согласен, что TGridPanelLayout проигрывает по памяти. Но за счет того, что листбокс занимается выгрузкой и загрузкой при скролле, мы и видим его притормаживание. Соответственно, автор должен решить, готов ли он платить памятью за плавный скролл? 

 

Для экономии памяти не обязательно грузить все панельки в TGridPanelLayout сразу. Достаточно загрузить порцию для 1.5-2 экранов (в указанном автором примере это будет 9-18 шт), а потом при скролле вниз подгружать по 6-9 шт. 

Автор привел пример с категориями ('Десерты', 'Салаты', ...). Это значит, что при перемещениях по категориям и подкатегориям, скорее всего, ему не придется подгружать большие порции для первых нескольких экранов.  Конечно же было проще анализировать задачу, если б автор указал среднее количество панелек для каждой категории/подкатегории. Для данной задачи важен также и размер картинок в панельках.

Повторю, я видел работающий пример. Все работало довольно шустро и плавно для 200 панелек в одной категории. (попробуйте сделать такое в листбокс и посмотрите на плавность скролла). 

 

У листбокса для этой задачи (категории/подкатегории) есть "подводные камни". Например: невозможно в событии OnItemClick перезаполнить содержимое этого листбокс без AV. Т.к. после этого обработчика в TCustomListBox.MouseUp (хе7) происходит попытка обратится к несуществующему Item-у:

if Assigned(OnItemClick) then
  OnItemClick(Self, Item);
P := Item.ScreenToLocal(LocalToScreen(TPointF.Create(X, Y))); // тут AV т.к. нет проверки, существует ли Item (а он будет уничтожен при перезаполнении листбокс)
Item.MouseUp(Button, Shift, P.X, P.Y);

Да, с листвью сложней, но со временем почти все списки в приложении пришлось переделать на ListView ради производительности. Сделать с LV можно почти все что можно сделать с LB, просто сложней.

 

Полностью поддерживаю. Но судя по теме, автор еще не настолько опытен в FMX, чтоб рекомендовать ему ListView для решения данной задачи.

Изменено пользователем enatechno
Ссылка на комментарий
  • 0
В 25.06.2015 в 00:39, uakmal сказал:

Снимок экрана 2015-06-25 в 0.32.33.png

И как такую красоту сделать на ListView (Ладно без горизонтального скроллинга)?

Изменено пользователем Axbor
Подправил
Ссылка на комментарий
  • 0
  • Модераторы
18 минут назад, Axbor сказал:

И как такую красоту сделать на ListView (Ладно без горизонтального скроллинга)?

 

Ссылка на комментарий
Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...