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

xenon54

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

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

  • Посещение

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

    14

Весь контент xenon54

  1. Автор спросил про ListView, а вы ответили про ListBox, это разные вещи.
  2. У TListView.items есть метод clear. Он освобождает память.
  3. xenon54

    ListItemBackground

    Здравствуйте! Подскажите пожалуйста способ поменять цвет фона у 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.
  4. Похоже что все оказалось проще простого. У ListBox'a также как и у ListView есть метод items.clear. "Memory warning" больше не срабатывает.
  5. Здравствуйте. Создаю 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; В соседней теме прочитал что если сделать стилизованный итем в котором будут эти лейблы и имейдж, то память при пролистывании будет выгружаться, а для картинок это весьма критично. Правильно ли я это понял? И если это так, то не будет ли тормозить при прокрутке этот листбокс постоянно подгружая и выгружая картинки? И еще вопрос, как правильно потом удалить такой ListBox чтобы освободить память которую скушали объекты внутри стилизованных ListBoxItemo'ов? При таком создании итемов (как в листинге), как правильно полностью освободить память которую они занимают и удалить объекты? Т.е. я хотел бы чтобы вначале этой процедуры было удаление либо полностью ListBox'a и заного создавать его и заполнять, либо удалить только итемы. Пробовал разные походы: Через Release, но тут получается что удаление сработает с некой задержкой, а мне уже сейчас нужно создавать листбокс и заполнять его вполне тяжелыми итемами (из-за картинок) и получается что на момент конца нового заполнения листбокса, старый еще вполне себе может находиться в памяти. Собственно из-за этого частенько возникает "Memory warning". Все бы хорошо, метод работает и память освобождает, но он мне не подходит потому что память нужно очистить сдесь и сейчас. Пробовал через DisposeOf, через раз при заполнении нового листбокса вылетает "Access...". Каюсь, не очень понимаю работу метода DisposeOf. Как я понял метод помечает объект как Disposed и вроде как вызывается деструктор (когда? через сколько? чего ждет?). Но как я прочитал это плохой метод потому что не освобождает память. В этом у меня есть некоторые сомнения, то ли я не так перевел, то ли ... Если есть кто хорошо понимает, объясните пожалуйста на пальцах суть метода DisposeOf. Пробовал просто занилить Listbox, но это совсем не помагает, ибо RefCount > 1, и соответственно ничего не происходит. метод Free просто вызывает деструктор, опять же деструктор удалит те самые label'ы и image'ы из listboxitem'ов? В общем с методом Free тоже не получается, срабатывает "Memory warning" ну и в последующем вылет приложения. Речь идет про IOS.
×
×
  • Создать...