• 1
krapotkin

Фреймворк для стандартного ListView

Вопросы

Всем привет!

После долгого творческого запоя я запилил альфу либы, которая позволяет юзать обычный, не-генномодифицированный ListView.
Данные подаются в виде модели данных, описание раскладки итема лежит в JSON.


Для работы пишется примитивный наследник класса-адаптера, который биндит данные модели на элементы из JSON. Я решил, что руками делать это дешевле чем через RTTI

{ TMyAdapter }

procedure TMyAdapter.SetupDrawableContent(const ADrawable: TListItemDrawable;
  const AData: TMyData);
begin
  if SameText( ADrawable.Name, 'text') then
  begin
    (ADrawable as TListItemText).Text := AData.Text;
  end
  else if SameText( ADrawable.Name, 'detail') then
  begin
    (ADrawable as TListItemText).Text := AData.Detail;
  end
  else if SameText( ADrawable.Name, 'balance') then
  begin
    (ADrawable as TListItemText).Text := FormatFloat('0.00', AData.Balance);
  end
  else if SameText( ADrawable.Name, 'reserved') then
  begin
    (ADrawable as TListItemText).Text := FormatFloat('0.00', AData.Reserved);
  end

end;

Главная хитрость и отличие от стандартного DynamicAppearance+LiveBinding - переменная высота итемов ListView и использование арифметики в описании раскладки.

Можно указать Detail.Y  = Text.Bottom + 5, ItemHeight = Detail.Bottom + 10, Detail.W = ItemWidth/2 - X

    {"Kind":"rect","Name":"BonusRect","Value":"",
      "Place":{"X":"itemwidth*3/4","Y":"Text.Y","W":"ItemWidth/4-5","H":"50"},
      "BorderColor":"#FF005500", "Color":"lime",
       "LineWidth":3},

    {"TextHAlign":2,"TextVAlign":1,"Kind":"text","Name":"Balance","Value":"",
      "Place":{"X":"BonusRect.x+5","Y":"Text.Y","W":"BonusRect.w-10","H":"50"},
      "WordWrap":true,
      "Color"	:"Black",
      "Font":{"Size":18,"Style":""}}
  ],
  "ItemHeight":"detail.bottom+10",

Это дает довольно гибкую систему. Не на все случаи жизни, но все, что нужно, можно после автоматической раскладки дополнительно приписать в OnUpdateObjects 

Код для работы примерно такой

procedure TForm1.FormCreate(Sender: TObject);
begin
  data:= TMyDataList.CreateFromFile(ExePath()+'data.json');  // загрузка в модель данных
  Adapter := TMyAdapter.Create(lvWallets, data.Items, ExePath()+'pattern.json');  // создание адаптера и загрузка шаблона
  Adapter.Pattern.SetupListView(lvWallets);  // задать отступы и разную мелочь
  Adapter.ResetView(); // здесь в цикле из модели данных создается нужное количество итемов ListView
end;

procedure TForm1.lvWalletsUpdatingObjects(const Sender: TObject;
  const AItem: TListViewItem; var AHandled: Boolean);
begin
  Adapter.SetupContent(AItem);  // загрузить текст, картинки и другое содержимое в элементы итема
  Adapter.Pattern.DoLayout(AItem);  // поправить раскладку в соответствии с содержимым элементов итема
end;

Для использования кроме стандартных - текст, картинка, кнопка - создано несколько дополнительных элементов итема - прямоугольник, круг, уголок, линия.

Отличие от ModernLV - , 
1) все происходит без правки системных файлов
2) пока нет колонок и других особых изысков.

На результат работы смотреть тут. Исходники пока не причесаны, будут чуть позже

 

ListViewFramework.7z

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 ответов на этот вопрос

  • 0

Очень сильно жрет CPU при изменении размеров формы - 100% CPU

image.thumb.png.b576b9e46f2f09878c5f18d82577e71e.png

Изменено пользователем Евгений Корепов

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

ага тоже столкнулся. не профилировал пока, но в целом логично, он там выражения парсит непрерывно, размеры-то динамические, зависят от каждой строки данных

надо попробовать установить жесткие, посмотреть, как изменится нагрузка

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

вторая версия демо

-работа над ошибками

-устранил утечки памяти

-расширил функционал

-добавил картинки

-совместимость с Android

Приложил EXE и APK

Скорее всего, для 100500 записей не потянет, т.к. слишком много арифметики для раскладки каждого элемента на каждом итеме, но для сотни - хватает.

ListViewTest2.7z

pasFiles.rar

Изменено пользователем krapotkin

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
32 минуты назад, krapotkin сказал:

Скорее всего, для 100500 записей не потянет, т.к. слишком много арифметики для раскладки каждого элемента на каждом итеме, но для сотни - хватает.

В принципе до сотни и на ListBox потянет.... :))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
51 минуту назад, krapotkin сказал:

вторая версия демо

-работа над ошибками

-устранил утечки памяти

-расширил функционал

-добавил картинки

-совместимость с Android

Приложил EXE и APK

Скорее всего, для 100500 записей не потянет, т.к. слишком много арифметики для раскладки каждого элемента на каждом итеме, но для сотни - хватает.

ListViewTest2.7z

pasFiles.rar

Жрет проц не меньше первой версии. Еще заметил - если дать приложению побыть запущенным несколько минут, то изменение размеров становится почти не возможным, торможение увеличивается на порядок.

image.thumb.png.b2736e8abf7e6d9c3b0cac3ef52be7e1.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Спасибо за фидбек!

Имхо, пока изменение размеров не очень актуально. В целом под windows редко форма меняет размеры.  Я ориентировался больше на мобильную платформу.

А вот второе замечание немного напрягло. Попробую подержать 

OFF: Ухты! RYZEN 5

Изменено пользователем krapotkin

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Спасибо всем кто откликнулся!

Прочистил все))  производительность вернулась в норму. Счетчики в верхней панели 

Прокрутка гладкая. в примере 8 итемов раскопированы 200 раз.

Средняя затрата времени на один Item - 0.2 мсек

 

 

 

Screenshot_2019-03-13-18-03-08-864_ru.krapotkin.ListViewTest.png

QIP Shot - Screen 211.png

ListViewTest3.7z

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

а с картинками можно пример? 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
1 час назад, krapotkin сказал:

Спасибо всем кто откликнулся!

Прочистил все))  производительность вернулась в норму. Счетчики в верхней панели 

Прокрутка гладкая. в примере 8 итемов раскопированы 200 раз.

Средняя затрата времени на один Item - 0.2 мсек

 

 

 

Screenshot_2019-03-13-18-03-08-864_ru.krapotkin.ListViewTest.png

QIP Shot - Screen 211.png

ListViewTest3.7z

Стало гораздо-гораздо лучше. Больше 70% не грузит ядро. Может математику вычислений попробовать на другое ядро повесить, чтоб совсем хорошо было? 

И очень интересно на исходники взглянуть. Это возможно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
53 минуты назад, Евгений Корепов сказал:

Стало гораздо-гораздо лучше. Больше 70% не грузит ядро. Может математику вычислений попробовать на другое ядро повесить, чтоб совсем хорошо было? 

И очень интересно на исходники взглянуть. Это возможно?

Математика - математикой, мне вот интересно, что с картинками? потому как если их грузить сразу в ListView, то памяти не напасёшься, получается их надо подтягивать по мере надобности, поэтому и попросил вариант с картинками.

понятно, что с аватарами легкими все будет тип-топ, интересуют картинки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

В демке картинки под виндой есть под Андроид надо искать, куда делись 

Lazy loading реализовывать оно отдельно надо. Id вписать в итем легко. Дальше наворачивать буду.

Сразу все не взлетает

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Вот и картинки подвезли. Идиотский Deployment отказывается переписывать старые файлы на новые....
Пока полностью не удалил приложение, файл-описание раскладки был старый, без картинок

Как видно из заголовка 3000+ итемов с авторасчетом высоты. 6 секунд

Крутится плавно...

Screenshot_2019-03-14-00-08-34-052_ru.krapotkin.ListViewTest.png

ListViewTest.apk.rar

Изменено пользователем krapotkin

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Похожий контент

    • От Dmitry Stolyarov
      Добрый день, подскажите, пжл, новичку...
      Есть ListView и ImageList с двумя картинками. В ListView Item добавлен Image. ListView заполняю из БД и пытаюсь вывести картинку в зависимости от значения поля БД, но в независимости от значения БД выводится одна и та же картинка.. Такое нельзя провернуть?
      procedure TForm6.ListViewNAMEUpdateObjects(const Sender: TObject;
        const AItem: TListViewItem);
        var IItem:TListItemImage;
      begin
       IItem:= aItem.Objects.FindDrawable('Image4') as TListItemImage;
      if (IItem<>nil) then
      with FDQuery1 do
       begin
       First;
       while not Eof do
        begin
         if FDQuery1FK_PRICE.AsInteger = 1 then begin
          IItem.ImageIndex:=1
         end else
            begin
               IItem.OwnsBitmap := True;
           IItem.ImageIndex:=0;
            end;
         Next;
        end;
       end;
      end;
       
    • От gresaggr
      Добрый день.
      Как под FMX в ListView сделать подчеркивание Detail в рантайме?
      Пытался делать так:
      LV.ItemAppearanceObjects.ItemObjects.Detail.Font.Style := [TFontStyle.fsUnderline]
      но не срабатывает.
      P.S. Возможно это применить не ко всем строкам, а только к некоторым?
    • От ice donkey
      Заполняю ListView в рантайме:
       
       
      LiveBindings не подходит, поэтому есть вопрос: а как задать фиксированный заголовок - чтобы в списке все Items, начинающиеся с буквы А были как бы объединены под одним заголовком А? Который  в свою очередь смещался бы только заголовком Б (с Items, которые на букву Б) и так далее.
       
      Пример:
       
    • От Olexander Sagaydak
      Летом 2016 вопрос отображения объектов в ListView при создании Items уже обсуждался. Хочу ещё раз обсудить этот вопрос. А именно:
      Простой код 
      ListViewItem := ListView.Items.Add;
      ListViewItem.Objects.AccessoryObject.Visible := false; (или true, не важно)
      вторая строка не работает если до выполнения, ListView ни одного раза не отображался. Если же отображался хотя бы один раз - всё нормально.
      В предыдущих обсуждениях Krapotkin рекомендовал Resize и OnUpdateObjects. Если нет идей проще, то, конечно, воспользуюсь.  
       
    • От x11
      Если у элементов, идущих подряд одинаковый текст, то текст скрывается.
      Как это это отключить?
       
    • От x11
      Не понять, ни в справке найти, ни примеров, как получить текст из header.
      Как получить текст из какого-то элемента, есть пример:
      lvContacts.Items[li.Index].Objects.FindObjectT<TListItemText>('textTel').Text; а для заголовка ил подвала не нахожу примеров
    • От Erlan_krg
      Всем привет! Встретился с одной проблемой. Удаляю Item у ListView по нажатию кнопки, которая находится на ListViewItem
      procedure TfmAppointment.lvSelectedServicesButtonClick(const Sender: TObject;
        const AItem: TListItem; const AObject: TListItemSimpleControl);
      begin
          lvSelectedServices.BeginUpdate;
          if lvSelectedServices.ItemCount > 0 then
              lvSelectedServices.Items.Delete(AItem.Index);
          lvSelectedServices.EndUpdate;
      end;
      итем удаляется, но потом выскакивает ошибка Access violation at address 60BCB318 и то се бо се
       
      у ListView ItemAppearance выставлен на DynamicAppearance
      помимо родного объекта Text добавил еще один объект Text и кнопку
       
      но фишка в чем, если убрать дополнительный объект Text с ListWiewItem и удалить итем то ошибка не выскакивает)
       
      что за прикол?
    • От sinuke
      Доброго дня, форумчане
      Возникла проблема с тем, чтобы поменять местами два итема в ListView. ListView.Items не имеет метода Exchange, сами итемы не имеют метода Assign чтобы можно было один итем клонировать в другой / удалить / вставить
      У кого какие мысли? Как реализовать?
      Delphi 10.2 Tokyo
       
    • От x11
      Не могу понять, как записать текст в Footer text
       
       

    • От Mars M
      Загружаю большой список в ListView, время загрузки где то 5-7 секунд.
      Это много, по этому переделал что бы список загружался динамически, как к концу пролистывается, подгружаются новые данные.
      Все бы хорошо, но вот ScrollBar при загрузке новых данных меняет размер и позицию. 
      Это не очень нравиться
      Можно как то заранее настроить его размер под конечное число итемов?
      Или может как то по другому сделать.
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу