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

TListView: список в виде CheckBox в ListViewItem


afors

Вопрос

Подскажите как реализовать список из CheckBox как на картинке. Думаю использовать ListView. Список не большой, до 300 элементов. Если можно пример динамического создания одного чекбокса в ListViewItem. Или может есть более удобные компоненты для реализации этой задачи?

Если подобная тема уже поднималась, то можно ссылку на нее...

ListViewCheckBox.png

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

Рекомендуемые сообщения

  • 0

У стандартного TListView уже все есть:

 

//устанавливаем режим редактирования у списка либо в редакторе свойств выставляем
ListView1.EditMode := True;
//...
//Получаем список всех выбранных элементов
ListView1.Items.CheckedIndexes(true);
//обращаться к свойству текущего элемента так:
  ListView1.Items.SetChecked(const Index: Integer; const Value: Boolean);
  ListView1.Items.GetChecked(const Index: Integer): Boolean;

 

1.PNG

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

Если именно как на приведенной вами картинке то вот так:

Делаете ListView с DynamicAppearance, включаете DesingMode, добавляете необходимые поля, включая TListItemAccessory с AccessoryType=Checkmark (он и будет отображать красивые галочки). Не забудьте дать названия добавленным элементам. В моем коде TListItemAccessory называется "ShowPool"

P.S. Вариант, предложенный выше, с ListView1.EditMode := True будет выглядеть страшненько, чекбоксы не очень хорошо смотрятся в интерфейсе приложений.

procedure TFormMain.FillSettingPools;
Var I : Integer;
    AItem : TListViewItem;
begin
  ListViewPools.BeginUpdate;
  ListViewPools.Items.Clear;
  for I := 0 to FPoolList.Count-1 do
  begin
    AItem:=ListViewPools.Items.Add;
    AItem.Data['CoinName']:=FPoolList.Items[I].CoinName;
    AItem.Data['CoinDetail']:=FPoolList.Items[I].Href;
    AItem.Data['ShowPool']:=FPoolList.Items[I].ShowPool;
    TListItemAccessory(AItem.View.FindDrawable('ShowPool')).Visible:=FPoolList.Items[I].ShowPool; //Boolean
  end;
  ListViewPools.EndUpdate;
end;

procedure TFormMain.ListViewPoolsUpdateObjects(const Sender: TObject;
  const AItem: TListViewItem);
Var AItemAccessory : TListItemAccessory;
begin
  AItemAccessory:=TListItemAccessory(AItem.View.FindDrawable('ShowPool'));
  if AItem.Data['ShowPool'].AsBoolean then
    AItemAccessory.Visible:=True
  Else
    AItemAccessory.Visible:=False;
end;

procedure TFormMain.ListViewPoolsItemClick(const Sender: TObject;
  const AItem: TListViewItem);
Var I : Integer;
    S : String;
    AListItemAccessory : TListItemAccessory;
    APool : TPool;
    AShowPool : Boolean;
begin
  AListItemAccessory:=TListItemAccessory(AItem.View.FindDrawable('ShowPool'));
  if AListItemAccessory<>nil then
  begin
    AShowPool:=AItem.Data['ShowPool'].AsBoolean;
    AShowPool:=Not AShowPool;
    AListItemAccessory.Visible:=AShowPool;
    AItem.Data['ShowPool']:=AShowPool;
    S:=AItem.Data['CoinName'].AsString;
    for I := 0 to FPoolList.Count-1 do
    begin
      If FPoolList.Items[I].CoinName.Equals(S) Then
      begin
        APool:=FPoolList.Items[I];
        APool.ShowPool:=AShowPool;
        FPoolList.Items[I]:=APool;
        Break;
      end;
    end;
  end;
  FillListViewPoolsMaster;
  SavePools;
end;

 

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

Что то у Евгения много лишнего в коде. Также вариант AItem.Data['ShowPool']:=AShowPool; медленный (т.к. в списке строк (TDictionary) ищется строка 'ShowPool' прямым перебором от начала до конца всего массива строк ), в моем случае гораздо быстрее.

Вот вариант с чекбоксами :

lvDetails.ItemAppearanceName := TAppearanceNames.ImageListItem; // или свой тип станадртный TAppearanceNames.ListItem
lvDetails.ItemAppearanceObjects.ItemObjects.Accessory.AccessoryType := TAccessoryType.Checkmark;

Все. теперь создаете OnItemClick - который будет включаь\выключать чекбокс 

procedure TfrmMain.lvDetailsItemClick(const Sender: TObject; const AItem: TListViewItem);
begin
  if aItem = nil then exit;


  if AItem.Objects.AccessoryObject.AccessoryType = TAccessoryType.Checkmark then
  begin
    AItem.Objects.AccessoryObject.Visible := not AItem.Objects.AccessoryObject.Visible;
   
   // When listview is resized because of rotation, accessory properties will be reset to default values
   // Save status to the Tag 
   AItem.Tag := integer(AItem.Objects.AccessoryObject.Visible);
  end;
end;

 

Добавляем событие OnUpdateObjects, на случай если девайс поменял ориентацию (в этом случае accessory свойства не сохраняются).

procedure TfrmMain.lvDetailsUpdateObjects(const Sender: TObject; const AItem: TListViewItem);
begin
  // In order for text to be truncated properly, shorten text object
  AItem.Objects.TextObject.Width := AItem.Objects.TextObject.Width - (2 +                 AItem.Objects.AccessoryObject.Width);
  

// Restore checked state when device is rotated.
  // When listview is resized because of rotation, accessory properties will be reset to default values
  if AItem.Objects.AccessoryObject.AccessoryType = TAccessoryType.Checkmark then
    AItem.Objects.AccessoryObject.Visible := Boolean(AItem.Tag);
end;

 

Проверяем наличие чекбокса:  

if ListView.Items[i].Objects.AccessoryObject.Visible then

 

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

Что то у Евгения много лишнего в коде. Также вариант AItem.Data['ShowPool']:=AShowPool; медленный (т.к. в списке строк (TDictionary) ищется строка 'ShowPool' прямым перебором от начала до конца всего массива строк ), в моем случае гораздо быстрее

TDictionary работает посредством хеш таблицы, и работает чертовски быстро (исключая некоторые специфичные моменты Collision resolution). А код просто выдрал из живого проекта, поэтому лишнее присутствует ;-)

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

TDictionary работает посредством хеш таблицы, и работает чертовски быстро 

Хэш нужно еще вычислить для строки. А потом все равно перелопатить весь массив последовательно (т.к. он не сортируется). Но для OnItemClick - это вообще не критично.

И такой перебор это стандартная фича для Data элементов. И доступ к элементам стиля также работает. Так что это стало уже стандартом. Не понимаю почему они не ввели возможность использовать числовые константы для этих целей.

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

Не могу понять, что я не так делаю.

Почему при щелчке мышкой по чекбоксу он не реагирует?

 

Screenshot_1.png

Screenshot_2.png

Проверьте свойства ListView - Selectable (вроде так называется)

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

Я знаю. И EditMode включено.

procedure TfmReference.actRefreshExecute(Sender: TObject);
Var
  sTableName: string;
begin
  sTableName := GetTableName;
  qRef.sql.Text := Format('select id, name from %s', [sTableName]);
  qRef.Open;
  ListView1.EditMode := not ListView1.EditMode;
  if ListView1.EditMode then ShowMessage('Режим редактирования включен');
end;

 

Screenshot_4.png

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

Нет такого свойства у TListView

Ошибся, правильно AllowSelection. А лучше приложите тестовый проект, так проще будет выяснить причину

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

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

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

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

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

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

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

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

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

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...