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

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


krapotkin

Вопрос

Всем привет!

После долгого творческого запоя я запилил альфу либы, которая позволяет юзать обычный, не-генномодифицированный 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) пока нет колонок и других особых изысков.

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

UPD.

ссылки на репозитории ниже

 

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

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

  • 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

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

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

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

Ссылка на комментарий
  • 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 эмодзи.

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

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

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

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