Jump to content
xorpas

Custom ListBox Layout in fmx

Recommended Posts

Hellow

 

I have A problem when customize Listbox item Using This tutorial   ListBox   All things Is ok But when scroll box the Listbox all object is empty

like this one

 

This is my Code  hier  

Var
  ListBoxItem: TListBoxItem;
  ItemText: TText;
  // if you get an error here, ensure that FMX.Objects is included in your uses above.
  Itembtn: TSpeedButton;
  ItemCircle: TCircle;
begin
  // First, we create an empty ListBoxItem with no parent
  ListBoxItem := TListBoxItem.Create(self);
  // now, we set a parent for this item
  // ListBox1.BeginUpdate;
  ListBoxItem.BeginUpdate;
  ListBoxItem.Parent := ListBox1;

  ListBoxItem.Height := 113;
  ListBoxItem.Width := 336;
  // Associate the Style you created with the ListBoxItem - not the ListBox itself.
  ListBoxItem.StyleLookup := 'NewList';

  // Next up, we're going to populate ItemText with the Caption of the Style using a style name lookup.
  ItemText := ListBoxItem.FindStyleResource('TxtUser') as TText;
  // We're going to set the text of the object to be whatever the caption should be.
  if Assigned(ItemText) then
    ItemText.Text := 'Hello World!';
  Itembtn := ListBoxItem.FindStyleResource('BtnAddFriend') as TSpeedButton;
  // We're going to set the text of the object to be whatever the caption should be.
  if Assigned(Itembtn) then
    Itembtn.Text := 'Hello World!';
  Itembtn := ListBoxItem.FindStyleResource('BtnRemove') as TSpeedButton;
  // We're going to set the text of the object to be whatever the caption should be.
  if Assigned(Itembtn) then
    Itembtn.Text := 'Hello World!';
  ItemCircle := ListBoxItem.FindStyleResource('Img') as TCircle;
  // We're going to set the text of the object to be whatever the caption should be.
  if Assigned(ItemCircle) then
    ItemCircle.Fill.Bitmap.Bitmap.LoadFromFile('E:\badger_1f9a1.png');
  ListBoxItem.EndUpdate;
  TabControl1.ActiveTab := TabUsers;

 

Untitled.png

Share this post


Link to post

I had this problem long time ago but don't remember how I manage it!

Indeed, a test with D10 reproduces this behavior (I only had to change a few lines of your program, and use default style removing default, renaming windows 7 to blank -> default).

If you read French (google trad can be a friend), I wrote a tutorial long time ago (https://delphi.developpez.com/tutoriels/firemonkey/intro-styles-firemonkey-xe4/).

 

Ideas : Try yo use standard stylenames i.e. txt,icon (especially this one)

 

mystyle :

image.thumb.png.7c0e8ae640a59d8966472b25c5676216.png

here icon and text can be accessed via
 

  ListboxItem.StylesData['txt']:='Data hello';
  ListBoxItem.ItemData.Bitmap.LoadFromFile('D:\XE8\icons8-planète-terre-48.png');

As you can see, stile using findstyleresource coding 

 

 

image.thumb.png.d54a5f9ed8d08e9c532402a7cb1d877c.png

it works better (only speedbutton hidden)

but if you code (here, I test my new style)

 ListboxItem.StylesData['button.text']:='Data btn';
 ListboxItem.StylesData['speedbtn.text']:='speed btn';

instead of sequence

//  Itembtn := ListBoxItem.FindStyleResource('button') as TSpeedButton;
//  if Assigned(Itembtn) then
//    Itembtn.Text := 'Btn Hello!';

the whole stuff works as expected.

 

Nowadays, I use more often Listview (dynamic appearance) than ListBox, Writing this other tutorial, I bang another time in this "empty object problem" I override also playing with link (disabling/enabling) and not only with the BeginUpdate/EndUpdate. 

However I never tested with the new versions to find out if this potential bug had been fixed.

Edited by Serge_G
  • Thanks 1

Share this post


Link to post

for listbox or listview,

every time you scroll,

OnApplyItemStyleLookup is triggered, when this event is triggered, for example, does the item in the listbox appear (can user see this listbox item),

You need to check the visible area, that is, the listbox will take its height, the listbox will take the position of the item and the listbox will update the number of items that fit inside the height

the style information and other item information that will appear on the screen,

for example update listboxitem.image or listboxitem.text/rectangle/button.

Don't do this to all items, your app will start to freeze while scrolling,

if you do this as i say, OnApplyItemStyleLookup It will not constantly update the same items that appear on the screen in every scroll, otherwise even if you slide the scroll by 1 pixel, it will always be triggered.

 

Procedure TfCountrySelection.ListBox_CountryList_OnApplyItemStyleLookup(Sender: TObject);
Var
 ListBoxItem:TListBoxItem;
 FlagStream:TMemoryStream;
 UlkeKodu:String;
 Flag:TObject;

Begin
 Try
  ListBoxItem:=TListBoxItem(Sender);

  UlkeKodu:=ListBoxItem.StylesData['country_code'].AsString;
  if Length(UlkeKodu)>0 then
  Begin
   if (Flags.GetCountryFlagStream(Trim(UlkeKodu), FlagStream)=True) then
   Begin
    Try
     Flag:=ListBoxItem.FindStyleResource('Flag');
     if (Flag<>Nil) And (Flag is TRectangle) then
     Begin
      TRectangle(Flag).Fill.Bitmap.Bitmap.LoadFromStream(FlagStream);
     End;
    Finally
     FlagStream.Free;
    End;
   End;
  End;

 Except
  On E:Exception Do
  Begin
   fDebug.AddExceptionLog('Exception! | '+Self.Name+'.ListBox_CountryList_OnApplyItemStyleLookup -> '+E.Message);
  End;
 End;
End;

 

 

Edited by okoca
  • Thanks 1

Share this post


Link to post
On 11/28/2021 at 7:15 AM, Serge_G said:

 ListboxItem.StylesData['button.text']:='Data btn';
 ListboxItem.StylesData['speedbtn.text']:='speed btn';

work great but can't access To btn  Is their a way   ?

 

 

Untitled.png

Share this post


Link to post
listboxitem.stylesdata['Btn.text']:='btn Hello';

I think there is also a way to fit image in the circle (fill.bitmap) but I still investigate

  • Thanks 1

Share this post


Link to post

Thank you VM , sorry men How about click button

Edited by xorpas

Share this post


Link to post
16 hours ago, xorpas said:

Thank you VM , sorry men How about click button

You mean how to assign event?

 

Ok, let me show you 2 methods in the same code

  private
    { Private declarations }
    procedure ItemApplyStyleLookup(Sender: TObject);
    procedure ItembuttonClick(Sender : TObject);
    procedure ItemSpeedButtonClick(Sender : TObject);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses System.Rtti;

procedure TForm1.AddItembtnClick(Sender: TObject);
Var
  ListBoxItem: TListBoxItem;
begin
  // First, we create an empty ListBoxItem with no parent
  ListBoxItem := TListBoxItem.Create(self);
  // now, we set a parent for this item
  ListBoxItem.BeginUpdate;
  ListBoxItem.Parent := ListBox1;
  ListBoxItem.Height := 113;
  ListBoxItem.Width := 336;
  ListBoxItem.StyleLookup := 'NewList';
  ListboxItem.StylesData['txt']:='Data hello';
  ListboxItem.StylesData['button.text']:='Data btn';
  ListboxItem.StylesData['speedbtn.text']:='speed btn';

  // First Method, using onApplyStyleLookup  
  ListBoxItem.OnApplyStyleLookup:=ItemApplyStyleLookup;
  ListBoxItem.StylesData['button.tag'] := ListBox1.Items.Count-1; // to get itemindex

  // Second method, direct with StylesData
  ListBoxItem.StylesData['speedbtn.tag'] := ListBox1.Items.Count-1; // to get itemindex
  ListBoxItem.StylesData['speedbtn.OnClick'] := TValue.From<TNotifyEvent>(ItemSpeedButtonClick);

  ListBoxItem.ItemData.Bitmap.LoadFromFile('D:\XE8\icons8-planète-terre-48.png');
  ListBoxItem.EndUpdate;
end;

procedure TForm1.ItemApplyStyleLookup(Sender: TObject);
var CustButton : TCustomButton;
    img : Timage;
    circle : TCircle;
begin
custButton:=TListboxItem(Sender).FindStyleResource('button') as TCustomButton;
if assigned(custbutton) then custButton.OnClick:=ItembuttonClick;
end;

procedure TForm1.ItembuttonClick(Sender: TObject);
begin
ShowMessage('Click on Button '+TCustomButton(Sender).Tag.ToString);
end;

procedure TForm1.ItemSpeedButtonClick(Sender: TObject);
begin
ShowMessage('Click on SpeedButton '+TCustomButton(Sender).Tag.ToString);
end;

Still working on image, thinking about a mask 

 

But, consider changing your mind. Instead of a TListBox and style you can use a VerticalScrollBox and Frame   

Edited by Serge_G
  • Thanks 1

Share this post


Link to post

Thank you Mr  serge it work , Ii their a tuto For a complete Using And access To Listboxitem ? ,I have more questions like how to change text Or color and some things like this

 

Share this post


Link to post
13 hours ago, xorpas said:

tuto For a complete Using And access To Listboxitem ?

I don't think there are much.

 

I wrote some  in French (https://delphi.developpez.com/tutoriels/firemonkey/intro-styles-firemonkey-xe4/) and I wrote also tips in my French blog https://www.developpez.net/forums/blogs/138527-sergiomaster/. But my predilection subject is more TListview than TListBox. It's true that I am thinking writing an opus on these 2 components, but it is a long process I can't insert in my professional agenda.

 

I still have some problems with TListview,  adding some more delay (and chapter) to the goal 

  • Thanks 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×