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

ненавижу Deploy 

опять потерялся файл pattern.json, поэтому не создавался шаблон в целом, и парсер его тоже

приложил. у меня запустилось штатно. проверьте plz

Ссылка на комментарий
  • 0
48 минут назад, krapotkin сказал:

ненавижу Deploy 

опять потерялся файл pattern.json, поэтому не создавался шаблон в целом, и парсер его тоже

приложил. у меня запустилось штатно. проверьте plz

Предлагаю улучшение )

function TVK_LV_BaseAdapter<TDataItem>.AddPatternFromFile(
  const Filename: string): TVK_LVPattern;
begin
  if Not TFile.Exists(Filename) then
    raise Exception.Create('Template file not found');
  result := TVK_LVPattern.CreateFromFile(Filename);
  result.LV := LV;
  Patterns.Add(result);
end;

 

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

Понял в чем дело - шаблоны лежат тут \vkrapotkin-vklistview-2389334d1383\Demo\Win32\Debug , а exe файл компилятор создает тут \vkrapotkin-vklistview-2389334d1383\Demo\

В настройках проекта, в Delphi Compiler, Output Direcrory = '', вместо '.\$(Platform)\$(Config)' по умолчанию.

 

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

да. из-за перехода на новую версию IDE видимо при upgrade проекта у меня слетели настройки, которые были в .dproj 

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

проверку добавлю. хотя теперь в CreateFromFile тоже есть Exception

 

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

еще один пример раскладки из реального проекта

image.png.24766623a986065242ab0be1d98bac7d.png

    {
      "Columns":[],
      "Variables": 
      [ 
        {"Y_UNIT":"12"}, 
        {"GAP":"8"}, 
        {"ITEM_H":"2*GAP+5*Y_UNIT"}, 
        {"IMG_H":"76"}, 
        {"IMG_W":"76"}, 
        {"STOCK_SIZE":"48"}, 
        {"PRICE_COLW":"53"} 
      ], 
      "Objects":
      [
        {"Name":"ID","Kind":"data"},
    ,
        {"Name":"img","Kind":"image",
         "Place":{"X":"0","Y":"0","W":"IMG_W","H":"IMG_H"},
        }
    ,
        {"Name":"Text","Kind":"text","TextHAlign":"leading","TextVAlign":"leading",
          "Place":{"X":"img.right","Y":"GAP","W":"itemwidth - IMG_W - GAP - 2*PRICE_COLW - GAP","H":"52"},
          "WordWrap":true, 
          "Color":"black",
          "Font":{"Size":12}
        }
    ,
        {"Name":"earlier","Kind":"text","TextHAlign":"leading","TextVAlign":"leading",
          "Place":{"X":"text.left","Y":"ITEM_H-2*GAP+2","W":"itemwidth - 2*PRICE_COLW","H":"Y_UNIT"},
          "WordWrap":false, 
          "Color":"green",
          "Font":{"Size":10}
        }
    ,
        {"Name":"price1","Kind":"text","TextHAlign":"trailing","TextVAlign":"trailing",
          "Place":{"X":"itemwidth-GAP-PRICE_COLW-W","Y":"GAP+2*Y_UNIT","W":"auto","H":"Y_UNIT*1.5", "priority":"WXYH"},
          "WordWrap":false, 
          "Color":"black",
          "Font":{"Size":15}
        }
    ,
        {"Name":"imgstrike","Kind":"image",
         "Place":{"X":"price1.x-5","Y":"price1.y","W":"price1.w+8","H":"price1.h"},
        }
    ,
        {"Name":"price2","Kind":"text","TextHAlign":"trailing","TextVAlign":"trailing",
          "Place":{"X":"price1.right-W","Y":"ITEM_H-GAP-Y_UNIT*1.5","W":"auto","H":"Y_UNIT*1.5", "priority":"WXYH"},
          "WordWrap":false, 
          "Color":"black",
          "Font":{"Size":15, "style":"bold"}
        }
    ,
        {"Name":"qty","Kind":"text","TextHAlign":"trailing","TextVAlign":"center",
          "Place":{"X":"itemwidth-PRICE_COLW-GAP","Y":"GAP","W":"PRICE_COLW","H":"2*Y_UNIT"},
          "WordWrap":false, 
          "Color":"black",
          "Font":{"Size":27, "style":"bold"}
        }
    ,
        {"Name":"imgstock","Kind":"image",
         "Place":{"X":"itemwidth-STOCK_SIZE-3","Y":"ITEM_H-STOCK_SIZE-4","W":"STOCK_SIZE","H":"STOCK_SIZE"},
        }
      ],
      "ItemHeight":"ITEM_H",
      "ItemSpaces":    {"X":"0","Y":"0","W":"0","H":""}, 
      "SideSpace":"0" 
    }

 

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

Всем хай!

Использую этод код в нашем проекте (БОЛЬШОЕ спасибо за исходники!).

Описал шаблон pattern.json, разнам полям назначил разный размер шрифта.
Поля создаются, текст присваивается, но по непонятной для меня причине размер шрифта на правильный меняется только после возникновения события OnResize, причем меняется только для видимых в данный момент итемов.

Проблема была в том, что по непонятным причинам в стайлбуке для итемов был выставлен размер шрифта=16, т.е. не дефолтный.
Как только убрал 16 и оставил дефолтный (12, емнип), все стало работать как надо.

Буду благодарен если кто-то сможет пояснить причину такого, чтобы пофиксить для будущих проектов!

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

P.S.

по факту использования мне показалось, что удобнее использовать не отдельный JSON файл, а прямо в коде константой задавать JSON строкой.

(Видимо сказались приключения с деплоем)))

Ссылка на комментарий
  • 0
5 часов назад, krapotkin сказал:

P.S.

по факту использования мне показалось, что удобнее использовать не отдельный JSON файл, а прямо в коде константой задавать JSON строкой.

(Видимо сказались приключения с деплоем)))

Или получать по http с сервера - тут вообще простор, можно дизайн списка менять на лету ))))

Ссылка на комментарий
  • 0
2 часа назад, krapotkin сказал:

Безусловно)

Смотрю в секции Variables можно на лету вычисления делать. Через как арифметика считается (чтоб по исходникам не искать)? просто интересно.

И можно ли там использовать динамические параметры? Типа ширины ListView (или итема с учетом отступов)? Было бы вообще прикольно. Я обычно размер картинки как раз вычисляю динамически, в зависимости от ширины (типа 30% от ширины итема).

 

ЗЫ Присмотрелся, вижу itemwidth - видимо это как раз то что мне нужно.

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

там из нетривиального есть itemwidth и remain = itemwidth - <элемент>.X

itemwidth считается с учетом отступов, т.е. значение чистое, правильное

вопрос про арифметику не совсем понял. там используется мой собственный парсер выражений

Для текста задается H = "Auto" - с автоматическим расчетом высоты

Изменено пользователем krapotkin
Ссылка на комментарий
  • 0
Ссылка на комментарий
  • 0
2 часа назад, krapotkin сказал:

demo listview при запуске выдаёт ошибку при вызове Adapter.AddPatternFromFile(ExePath()+'pattern.json') в  XSuperObject.

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

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

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

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

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

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

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

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

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

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