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

xenon54

Пользователи
  • Постов

    385
  • Зарегистрирован

  • Посещение

  • Победитель дней

    14

Сообщения, опубликованные xenon54

  1.  

    Я создаю TListViewItem и добавляю её в TListView, но как добавить картинку слева? Вот код создания ячейки:

    TListViewItem *Item = ListView1->Items->Add();
    Item->Text = "123";

     

     

     

    У TListBoxItem установи значение свойство StyleLookup в listboxitemnodetail и ItemData.Bitmap укажи картинку

    Проверял на XE7 Update 1

     

    Автор спросил про ListView, а вы ответили про ListBox, это разные вещи.

  2. Здравствуйте! Подскажите пожалуйста способ поменять  цвет фона у ListViewItem'а. С ListBox'om все просто, можно через стили все сделать, добавить например RectAngle в стили, и использовать его в RunTime, а как же быть с ListViewItem, ведь это не контрол? Использую модуль из примеров MultiDetailAppearanceU прям то что мне нужно. Мб как-то туда можно добавить что-то? у меня ничего не получается :( в StyleBook (использую iOSBlack.fsf)  в "listviewstyle.itembackground" есть свойство Color, но естественно оно меняет сразу у всех итемов стиль, и в рантайме не получается кстати поменять почему-то этот цвет.

    unit MultiDetailAppearanceU;
    
    interface
    
    uses FMX.ListView, FMX.ListView.Types, System.Classes, System.SysUtils,
    FMX.Types, System.UITypes, FMX.MobilePreview;
    
    type
    
      TMultiDetailAppearanceNames = class
      public const
        ListItem = 'MultiDetailItem';
        ListItemCheck = ListItem + 'ShowCheck';
        ListItemDelete = ListItem + 'Delete';
        Detail1 = 'det1';  // Name of MultiDetail object/data
        Detail2 = 'det2';
        Detail3 = 'det3';
      end;
    
    implementation
    
    uses System.Math, System.Rtti;
    
    type
    
      TMultiDetailItemAppearance = class(TPresetItemObjects)
      public const
        cTextMarginAccessory = 8;
        cDefaultImagePlaceOffsetX = -3;
        cDefaultImageTextPlaceOffsetX = 4;
        cDefaultHeight = 80;
        cDefaultImageWidth = 50;
        cDefaultImageHeight = 70;
      private
        FMultiDetail1: TTextObjectAppearance;
        FMultiDetail2: TTextObjectAppearance;
        FMultiDetail3: TTextObjectAppearance;
        procedure SetMultiDetail1(const Value: TTextObjectAppearance);
        procedure SetMultiDetail2(const Value: TTextObjectAppearance);
        procedure SetMultiDetail3(const Value: TTextObjectAppearance);
      protected
        function DefaultHeight: Integer; override;
        procedure UpdateSizes; override;
        function GetGroupClass: TPresetItemObjects.TGroupClass; override;
        procedure SetObjectData(const AListViewItem: TListViewItem; const AIndex: string; const AValue: TValue; var AHandled: Boolean); override;
      public
        constructor Create; override;
        destructor Destroy; override;
      published
        property Image;
        property MultiDetail1: TTextObjectAppearance read FMultiDetail1 write SetMultiDetail1;
        property MultiDetail2: TTextObjectAppearance read FMultiDetail2 write SetMultiDetail2;
        property MultiDetail3: TTextObjectAppearance read FMultiDetail3 write SetMultiDetail3;
        property Accessory;
      end;
    
      TMultiDetailDeleteAppearance = class(TMultiDetailItemAppearance)
      private const
        cDefaultGlyph = TGlyphButtonType.Delete;
      public
        constructor Create; override;
      published
        property GlyphButton;
      end;
    
      TMultiDetailShowCheckAppearance = class(TMultiDetailItemAppearance)
      private const
        cDefaultGlyph = TGlyphButtonType.Checkbox;
      public
        constructor Create; override;
      published
        property GlyphButton;
      end;
    
    
    const
      cMultiDetail1Member = 'Detail1';
      cMultiDetail2Member = 'Detail2';
      cMultiDetail3Member = 'Detail3';
    
    
    constructor TMultiDetailItemAppearance.Create;
    begin
      inherited;
      Accessory.DefaultValues.AccessoryType := TAccessoryType.More;
      Accessory.DefaultValues.Visible := True;
      Accessory.RestoreDefaults;
      Text.DefaultValues.VertAlign := TListItemAlign.Trailing;
      Text.DefaultValues.TextVertAlign := TTextAlign.Leading;
      Text.DefaultValues.Height := 76;  // Item will be bottom aligned, with text top aligned
      Text.DefaultValues.Visible := True;
      Text.RestoreDefaults;
    
      FMultiDetail1 := TTextObjectAppearance.Create;
      FMultiDetail1.Name := TMultiDetailAppearanceNames.Detail1;
      FMultiDetail1.DefaultValues.Assign(Text.DefaultValues);  // Start with same defaults as Text object
      FMultiDetail1.DefaultValues.Height := 56;  // Move text down
      FMultiDetail1.DefaultValues.IsDetailText := True; // Use detail font
      FMultiDetail1.RestoreDefaults;
      FMultiDetail1.OnChange := Self.ItemPropertyChange;
      FMultiDetail1.Owner := Self;
    
      FMultiDetail2 := TTextObjectAppearance.Create;
      FMultiDetail2.Name := TMultiDetailAppearanceNames.Detail2;
      FMultiDetail2.DefaultValues.Assign(FMultiDetail1.DefaultValues);  // Start with same defaults as Text object
      FMultiDetail2.DefaultValues.Height := 38; // Move text down
      FMultiDetail2.RestoreDefaults;
      FMultiDetail2.OnChange := Self.ItemPropertyChange;
      FMultiDetail2.Owner := Self;
    
      FMultiDetail3 := TTextObjectAppearance.Create;
      FMultiDetail3.Name := TMultiDetailAppearanceNames.Detail3;
      FMultiDetail3.DefaultValues.Assign(FMultiDetail2.DefaultValues);  // Start with same defaults as Text object
      FMultiDetail3.DefaultValues.Height := 20; // Move text down
      FMultiDetail3.RestoreDefaults;
      FMultiDetail3.OnChange := Self.ItemPropertyChange;
      FMultiDetail3.Owner := Self;
    
      // Define livebindings members that make up MultiDetail
      FMultiDetail1.DataMembers :=
        TObjectAppearance.TDataMembers.Create(
          TObjectAppearance.TDataMember.Create(
            cMultiDetail1Member, // Displayed by LiveBindings
            Format('Data["%s"]', [TMultiDetailAppearanceNames.Detail1])));   // Expression to access value from TListViewItem
      FMultiDetail2.DataMembers :=
        TObjectAppearance.TDataMembers.Create(
          TObjectAppearance.TDataMember.Create(
            cMultiDetail2Member, // Displayed by LiveBindings
            Format('Data["%s"]', [TMultiDetailAppearanceNames.Detail2])));   // Expression to access value from TListViewItem
      FMultiDetail3.DataMembers :=
        TObjectAppearance.TDataMembers.Create(
          TObjectAppearance.TDataMember.Create(
            cMultiDetail3Member, // Displayed by LiveBindings
            Format('Data["%s"]', [TMultiDetailAppearanceNames.Detail3])));   // Expression to access value from TListViewItem
    
      Image.DefaultValues.Width := cDefaultImageWidth;
      Image.DefaultValues.Height := cDefaultImageHeight;
      Image.RestoreDefaults;
    
      GlyphButton.DefaultValues.VertAlign := TListItemAlign.Center;
      GlyphButton.RestoreDefaults;
    
      // Define the appearance objects
      AddObject(Text, True);
      AddObject(MultiDetail1, True);
      AddObject(MultiDetail2, True);
      AddObject(MultiDetail3, True);
      AddObject(Image, True);
      AddObject(Accessory, True);
      AddObject(GlyphButton, IsItemEdit);  // GlyphButton is only visible when in edit mode
    end;
    
    constructor TMultiDetailDeleteAppearance.Create;
    begin
      inherited;
      GlyphButton.DefaultValues.ButtonType := cDefaultGlyph;
      GlyphButton.DefaultValues.Visible := True;
      GlyphButton.RestoreDefaults;
    end;
    
    constructor TMultiDetailShowCheckAppearance.Create;
    begin
      inherited;
      GlyphButton.DefaultValues.ButtonType := cDefaultGlyph;
      GlyphButton.DefaultValues.Visible := True;
      GlyphButton.RestoreDefaults;
    end;
    
    function TMultiDetailItemAppearance.DefaultHeight: Integer;
    begin
      Result := cDefaultHeight;
    end;
    
    destructor TMultiDetailItemAppearance.Destroy;
    begin
      FMultiDetail1.Free;
      FMultiDetail2.Free;
      FMultiDetail3.Free;
      inherited;
    end;
    
    procedure TMultiDetailItemAppearance.SetMultiDetail1(
      const Value: TTextObjectAppearance);
    begin
      FMultiDetail1.Assign(Value);
    end;
    
    procedure TMultiDetailItemAppearance.SetMultiDetail2(
      const Value: TTextObjectAppearance);
    begin
      FMultiDetail2.Assign(Value);
    end;
    
    
    procedure TMultiDetailItemAppearance.SetMultiDetail3(
      const Value: TTextObjectAppearance);
    begin
      FMultiDetail3.Assign(Value);
    end;
    
    
    procedure TMultiDetailItemAppearance.SetObjectData(
      const AListViewItem: TListViewItem; const AIndex: string;
      const AValue: TValue; var AHandled: Boolean);
    begin
      inherited;
    
    end;
    
    function TMultiDetailItemAppearance.GetGroupClass: TPresetItemObjects.TGroupClass;
    begin
      Result := TMultiDetailItemAppearance;
    end;
    
    procedure TMultiDetailItemAppearance.UpdateSizes;
    var
      LOuterHeight: Single;
      LOuterWidth: Single;
      LInternalWidth: Single;
      LImagePlaceOffset: Single;
      LImageTextPlaceOffset: Single;
    begin
      BeginUpdate;
      try
        inherited;
    
        // Update the widths and positions of renderening objects within a TListViewItem
        LOuterHeight := Height - Owner.ItemSpaces.Top - Owner.ItemSpaces.Bottom;
        LOuterWidth := Owner.Width - Owner.ItemSpaces.Left - Owner.ItemSpaces.Right;
        if Image.ActualWidth = 0 then
        begin
          LImagePlaceOffset := 0;
          LImageTextPlaceOffset := 0;
        end
        else
        begin
          LImagePlaceOffset := cDefaultImagePlaceOffsetX;
          LImageTextPlaceOffset := cDefaultImageTextPlaceOffsetX;
        end;
        Image.InternalPlaceOffset.X := GlyphButton.ActualWidth + LImagePlaceOffset;
        if Image.ActualWidth > 0 then
          Text.InternalPlaceOffset.X :=
            Image.ActualPlaceOffset.X +  Image.ActualWidth + LImageTextPlaceOffset
        else
          Text.InternalPlaceOffset.X :=
            0 + GlyphButton.ActualWidth;
        MultiDetail1.InternalPlaceOffset.X := Text.InternalPlaceOffset.X;
        MultiDetail2.InternalPlaceOffset.X := Text.InternalPlaceOffset.X;
        MultiDetail3.InternalPlaceOffset.X := Text.InternalPlaceOffset.X;
        LInternalWidth := LOuterWidth - Text.ActualPlaceOffset.X - Accessory.ActualWidth;
        if Accessory.ActualWidth > 0 then
          LInternalWidth := LInternalWidth - cTextMarginAccessory;
        Text.InternalWidth := Max(1, LInternalWidth);
        MultiDetail1.InternalWidth := Text.InternalWidth;
        MultiDetail2.InternalWidth := Text.InternalWidth;
        MultiDetail3.InternalWidth := Text.InternalWidth;
      finally
        EndUpdate;
      end;
    
    end;
    
    type
      TOption = TCustomListView.TRegisterAppearanceOption;
    const
      sThisUnit = 'MultiDetailAppearanceU';     // Will be added to the uses list when appearance is used
    initialization
      // MultiDetailItem group
      TCustomListView.RegisterAppearance(
        TMultiDetailItemAppearance, TMultiDetailAppearanceNames.ListItem,
        [TOption.Item], sThisUnit);
      TCustomListView.RegisterAppearance(
        TMultiDetailDeleteAppearance, TMultiDetailAppearanceNames.ListItemDelete,
        [TOption.ItemEdit], sThisUnit);
      TCustomListView.RegisterAppearance(
        TMultiDetailShowCheckAppearance, TMultiDetailAppearanceNames.ListItemCheck,
        [TOption.ItemEdit], sThisUnit);
    finalization
      TCustomListView.UnregisterAppearances(
        TArray<TCustomListView.TItemAppearanceObjectsClass>.Create(
          TMultiDetailItemAppearance, TMultiDetailDeleteAppearance,
          TMultiDetailShowCheckAppearance));
    end.
    
  3. Здравствуйте. Создаю Listboxitem'ы так:

    var
      LBItem    : TListBoxItem;
      l1,l2, l3 : TLabel;
      img : TImage;
    begin
    	LBItem := TListBoxItem.Create(ListBox1);
    	LBItem.Parent := ListBox1;
    	LBItem.height := 70;
    	LBItem.Tag := i;
    	LBItem.Margins.Left := 5;
    	LBItem.Margins.Right := 5;
    	LBItem.ItemData.Accessory := TListboxitemdata.TAccessory.aDetail;
    
    
    	img := TImage.Create(LBItem);
    	img.HitTest := false;
    	img.Parent := LBItem;
    	img.Width := 50;
    	img.Height := 70;
    	img.Bitmap.SetSize(50,50);
    	img.Position.X := 0;
    	img.Position.Y := -1;
    	img.Bitmap.LoadFromFile('......jpg');
    
    
    	l1 := TLabel.Create(LBItem);
    	l1.parent := LBItem;
    	l1.Position.x := 60;
    	l1.Position.y := 0;
    	l1.Width := ListBox1.Width - 120;
    	l1.AutoSize := false;
    	l1.WordWrap := false;
    	l1.StyledSettings := [];
    	l1.Font.Style := [TFontStyle.fsBold];
    	l1.Font.Size := 18;
    	l1.Height := 20;
    	l1.Text := '...';
    
    	l3 := TLabel.Create(LBItem);
    	l3.StyledSettings := [];
    	l3.parent := LBItem;
    	l3.Width := ListBox1.Width - 120;
    	l3.Position.x := 60;
    	l3.Position.y := 24;
    	l3.Font.Size := 12;
    	l3.FontColor := $FF999999;
    	l3.AutoSize := false;
    	l3.WordWrap := false;
    	l3.Height := 20;
    
    	l3.Text := '...';
    
    	l2 := TLabel.Create(LBItem);
    	l2.StyledSettings := [];
    	l2.parent := LBItem;
    	l2.Width := ListBox1.Width - 120;
    	l2.Position.x := 60;
    	l2.Position.y := 44;
    	l2.Font.Size := 12;
    	l2.FontColor := $FF999999;
    	l2.AutoSize := false;
    	l2.WordWrap := false;
    	l2.Height := 20;
    
    
    	l2.Text := '...';
    end;
    
    
    1. В соседней теме прочитал что если сделать стилизованный итем в котором будут эти лейблы и имейдж, то память при пролистывании будет выгружаться, а для картинок это весьма критично. Правильно ли я это понял? И если это так, то не будет ли тормозить при прокрутке этот листбокс постоянно подгружая и выгружая картинки? И еще вопрос, как правильно потом удалить такой ListBox чтобы освободить память которую скушали объекты внутри стилизованных ListBoxItemo'ов?
    2. При таком создании итемов (как в листинге), как правильно полностью освободить память которую они занимают и удалить объекты? Т.е. я хотел бы чтобы вначале этой процедуры было удаление либо полностью ListBox'a и заного создавать его и заполнять, либо удалить только итемы. 

    Пробовал разные походы:

    1. Через Release, но тут получается что удаление сработает с некой задержкой, а мне уже сейчас нужно создавать листбокс и заполнять его вполне тяжелыми итемами (из-за картинок) и получается что на момент конца нового заполнения листбокса, старый еще вполне себе может находиться в памяти. Собственно из-за этого частенько возникает "Memory warning". Все бы хорошо, метод работает и память освобождает, но он мне не подходит потому что память нужно очистить сдесь и  сейчас.
    2. Пробовал через DisposeOf, через раз при заполнении нового листбокса вылетает "Access...". Каюсь, не очень понимаю работу метода DisposeOf. Как я понял метод помечает объект как Disposed и вроде как вызывается деструктор (когда? через сколько? чего ждет?). Но как я прочитал это плохой метод потому что не освобождает память. В этом у меня есть некоторые сомнения, то ли я не так перевел, то ли ... Если есть кто хорошо понимает, объясните пожалуйста на пальцах суть метода DisposeOf.
    3. Пробовал просто занилить Listbox, но это совсем не помагает, ибо RefCount > 1, и соответственно ничего не происходит.
    4. метод Free просто вызывает деструктор, опять же деструктор удалит те самые label'ы и image'ы из listboxitem'ов? В общем с методом Free тоже не получается, срабатывает "Memory warning" ну и в последующем вылет приложения.

    Речь идет про IOS.

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