Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animating the addition of a string to a ListBox in FireMonkey

The following code nicely animates adding a new string to the end of a ListBox

procedure TForm6.AddItem(s: string);
var
  l : TListBoxItem;
  OldHeight : Single;
begin
  l := TListBoxItem.Create(Self);
  l.Text := s;
  OldHeight := l.Height;
  l.Height := 0;
  l.Parent := ListBox1;
  l.Opacity := 0;
  l.AnimateFloat('height', OldHeight, 0.5);
  l.AnimateFloat('Opacity', 1, 0.5);
end;

The item expands and fades in. However I want to be able to add the string into an arbitrary location in the ListBox - actually at the current ItemIndex. Does anyone know how to do this?

like image 320
Alister Avatar asked Jan 26 '12 21:01

Alister


2 Answers

To work around the fact that ListBox1.InsertObject and ListBox1.Items.Insert don't work you can do the following

procedure TForm1.AddItem(s: string);
var
  l : TListBoxItem;
  OldHeight : Single;
  I: Integer;
  index : integer;
begin
  l := TListBoxItem.Create(nil);
  l.Text := s;
  OldHeight := l.Height;
  l.Height := 0;
  l.Opacity := 0;
  l.Index := 0;
  l.Parent := ListBox1;

  Index := Max(0, ListBox1.ItemIndex);
  for I := ListBox1.Count - 1 downto Index + 1 do
  begin
    ListBox1.Exchange(ListBox1.ItemByIndex(i), ListBox1.ItemByIndex(i-1));
  end;
  ListBox1.ItemIndex := Index;
  l.AnimateFloat('height', OldHeight, 0.5);
  l.AnimateFloat('Opacity', 1, 0.5);
end;

but is a bit ridiculous. It (eventually) adds the string in position 0 if there is no item selected, otherwise adds it before the selected item. This solution reminds me too much of Bubble Sort. You will need to add the math unit to your uses clause for the max function to work.

This does indeed seem to be a bug in FireMonkey (check Quality Central #102122), However I suspect a future FireMonkey update will fix this. If anyone can see a better way of doing this....

I've also made a movie about this for those who are interested, which illustrates things more clearly.

like image 132
Alister Avatar answered Oct 14 '22 16:10

Alister


This should work, but it does nothing:

l := TListBoxItem.Create(ListBox1);
ListBox1.InsertObject(Max(ListBox1.ItemIndex, 0), l);

If I then call the following, I get an access violation:

ListBox1.Realign;

In fact, even this gives me an AV:

ListBox1.Items.Insert(0, 'hello');
ListBox1.Realign;

But this adds one, of course:

ListBox1.Items.Add('hello');

A bug perhaps?

like image 33
Marcus Adams Avatar answered Oct 14 '22 15:10

Marcus Adams