Перейти к содержанию
  • Регистрация
  • 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

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


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

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

  • 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
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

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


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

А можете сделать как замену... DBGrid?

Ну чтобы данные запроса из базы SQLite3 брал и отрисовывал по мере загрузки.

Можно с фиксированной высотой, главное результаты ни одним большим запросом брать, а по мере прокрутки, чтобы было больше похоже на DBGrid.

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


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

запрос он всегда один, большой или малый. просто записи с сервера фетчатся по кускам. но для локальной SQL это как-то вообще не актуально )

кроме того, не понял, что вам мешает в адаптере брать данные с датасета?

вообще ничего менять не надо

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


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

понятно, буду иметь ввиду

мне пока еще рано говорить о БД, т.к. непонятно когда выйдет 64-битный компилятор для Андроид

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


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

ставлю на конец сентября )) в виде hot-top-secret-special-beta-fix  )))

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


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

конец сентября ))

Пруфы Билли, нам нужны пруфы! ))

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


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

ставлю на конец сентября )) в виде hot-top-secret-special-beta-fix  )))

вашими бы устами, да мед пить)

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


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

Обновил репозиторий.

Добавил метод AfterLayout для условного форматирования элементов после раскладки по итему LV

https://bitbucket.org/vkrapotkin/vklistview/src/master/

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


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

У меня ругается на отсутствие JsonableObject. В x-superobject вроде такого нет. Где взять?

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


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

Там же в соседнем репозитории д.б.

https://bitbucket.org/vkrapotkin/jsonableobject/src/master/

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

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


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

Вылетает AV на GetValue(ItemSpaces.X), ItemSpaces нигде до этого не инициализируется вроде.

procedure TVK_LVPattern.SetupListView(const LV: TListView);
var
  i: Integer;
begin
  FNowParsing.Clear;

  LV.ItemSpaces.Left := GetValue(ItemSpaces.X);
  LV.ItemSpaces.Top := GetValue(ItemSpaces.Y);
  LV.ItemSpaces.Right := GetValue(ItemSpaces.X + ItemSpaces.W);
  LV.ItemSpaces.Bottom := GetValue(ItemSpaces.Y + ItemSpaces.H);
end;

 

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


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

под виндой нормально, на андроиде проверю попозже.

но TVK_LVPattern.itemspaces это record поэтому вроде бы и не нужно

а LV.ItemSpaces вроде должен сам ListView инициализировать

Если раньше найдешь, сигналь...

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


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

под виндой нормально, на андроиде проверю попозже.

но TVK_LVPattern.itemspaces это record поэтому вроде бы и не нужно

а LV.ItemSpaces вроде должен сам ListView инициализировать

Если раньше найдешь, сигналь...

Вот оно где image.thumb.png.92d322aeac516e06489c5fff46c90562.png

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


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

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


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

    • От 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 пользователей онлайн

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

×
×
  • Создать...