XE ListBox实现伸缩效果

功能:实现年月日压缩,初始化时item是所有年,点击年展开月,点击月展开天,再点击则收缩。

思路:实际上一开始是将所有item显示,只是将月日的item.height赋值为0,

     记录每一行的item的index,包括年,月,日,

   找到年的item,点击时,显示月的item,赋month.height即可,其他同理。

    接下来就是处理边界值。

unit listbox_test;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 
  FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, StrUtils,
  FMX.Layouts, FMX.ListBox, FMX.Memo, FMX.Controls.Presentation, FMX.ScrollBox;

type
  TListBoxFortest = class(TForm)
    ListBox1: TListBox;
    Layout1: TLayout;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure ListBox1ItemClick(const Sender: TCustomListBox;
      const Item: TListBoxItem);
  private
    { Private declarations }

  public
    { Public declarations }
  end;

var
  ListBoxFortest: TListBoxFortest;
  Year  : Array[ 0..2 ] Of string = ('2015', '2014', '2013' );
  Month : Array[ 0..3 ] Of Integer = (1, 2, 3, 4);
  Day   : Array[ 0..4 ] Of Integer = (10, 11, 12, 13, 14);
  YearIndex : Array of Integer ;
  MonthIndex : Array of Array of Integer ;    //二维
  ExpandYear   : Integer;
  ExpandMonth  : Integer;
implementation

{$R *.fmx}

procedure TListBoxFortest.FormCreate(Sender: TObject);
 var
    yItem : TListBoxItem;
    mItem : TListBoxItem;
    dItem : TListBoxItem;
    iyear : integer;
    imonth : integer;
    iday : integer;
begin
  //设置默认值
  ExpandYear  := -1;
  ExpandMonth := -1;

  //初始化长度
  setlength(YearIndex, Length(Year));
  setlength(MonthIndex, Length(Year), Length(Month));

   with ListBox1 do begin
    BeginUpdate;
    for iyear := 0 to Length(Year) - 1 do begin
      yItem := TListBoxItem.Create(nil);
      yItem.Parent := ListBox1;
      yItem.Name := 'year' + Year[iyear] ;
      yItem.Text := 'year' + Year[iyear] ;
      yItem.Height := 40;
      YearIndex[iyear] := listbox1.Items.Count - 1;

        for imonth := 0 to Length(Month) - 1 do begin
          mItem := TListBoxItem.Create(nil);
          mItem.Parent := ListBox1;
          mItem.Name := 'month' + Month[imonth].ToString ;
          mItem.Text := '    month' + Month[imonth].ToString ;
          mItem.Height := 0;
          MonthIndex[iyear,imonth] := listbox1.Items.Count - 1;

          for iday := 0 to Length(Day) - 1 do begin
            dItem := TListBoxItem.Create(nil);
            dItem.Parent := ListBox1;
            dItem.Name := 'day' + Day[iday].ToString ;
            dItem.Text := '        day' + Day[iday].ToString ;
            dItem.Height := 0;
          end;
      end;
    end;
    EndUpdate;
  end;

  for iyear := 0 to Length(Year) - 1 do begin
    self.Memo1.Lines.Add( 'year' + Year[iyear] + ' : ' + YearIndex[iyear].ToString);
    for imonth := 0 to Length(Month) - 1 do begin
       self.Memo1.Lines.Add( 'month' + Month[imonth].ToString + ' : ' + MonthIndex[iyear,imonth].ToString);
    end;
  end;
end;

procedure TListBoxFortest.ListBox1ItemClick(const Sender: TCustomListBox;
  const Item: TListBoxItem);
var
  SeletedItemName : string;
  SeletedItemIndex: Integer;
  EndIndex        : Integer;
  FindItemIndex   : Integer;
  SubItemIndex    : Integer;
  temp    : Integer;
  temp_1  : Integer;
begin
  SeletedItemName  := ListBox1.ListItems[listBox1.ItemIndex].Name;  //选中的item名
  SeletedItemIndex := ListBox1.ListItems[listBox1.ItemIndex].Index; //选中的item索引

  if LeftStr(SeletedItemName, 4) = 'year' then
  begin
  for FindItemIndex:=0 to Length(YearIndex) - 1 do
  begin
    if YearIndex[FindItemIndex] = SeletedItemIndex then    //年的索引
      break;
  end;

  if ListBox1.ListItems[SeletedItemIndex + 1].Height = 30 then
    ExpandYear := FindItemIndex
  else
    ExpandYear := -1;

  if ExpandYear <> -1 then
    begin
      if FindItemIndex = Length(YearIndex) - 1 then
        EndIndex := ListBox1.Items.Count - 1
      else
        EndIndex := YearIndex[FindItemIndex + 1] - 1;

      with ListBox1 do begin
        BeginUpdate;
        for SubItemIndex := SeletedItemIndex + 1 to EndIndex do
        begin
          ListBox1.ListItems[SubItemIndex].Height := 0;
          ListBox1.ListItems[SubItemIndex].Visible := false;
        end;
        EndUpdate;
      end;
      ExpandYear := -1;
    end
  else
    begin
      temp := Length(MonthIndex[FindItemIndex]);     // 选中的该年 月索引的个数
      with ListBox1 do begin
        BeginUpdate;
        for SubItemIndex := 0 to temp - 1 do
        begin
          temp_1 := MonthIndex[FindItemIndex,SubItemIndex];    // 遍历选中的Item下一级(月)的每个itemindex
            ListBox1.ListItems[temp_1].Height := 30;
            ListBox1.ListItems[temp_1].Visible := true;
          end;
            ExpandYear := FindItemIndex;                  // 展开年的ItemIndex
          EndUpdate;
        end;
     end;
  end;

  for temp := 0 to Length(Year) - 1 do
      for temp_1 := 0 to Length(Month) - 1 do
        if SeletedItemIndex = MonthIndex[temp,temp_1] then  begin
          ExpandYear :=  temp;                  // 展开的年itemindex
          break;
        end;

  if (LeftStr(SeletedItemName,5) = 'month') and (ExpandYear <> -1) then
  begin
    temp := Length(MonthIndex[ExpandYear]);
    for FindItemIndex := 0 to temp - 1 do
    begin
      if MonthIndex[ExpandYear, FindItemIndex] = SeletedItemIndex then     // 展开的月itemindex
        break;
    end;

    if ListBox1.ListItems[SeletedItemIndex + 1].Height = 30 then
        ExpandMonth := FindItemIndex
    else
        ExpandMonth := -1;

    if FindItemIndex <> temp -1 then         // 处理边界值
      EndIndex := MonthIndex[ExpandYear, FindItemIndex + 1] - 1            // 该月中天的最后索引
    else begin
      if ExpandYear <> Length(Year) - 1 then
        EndIndex := YearIndex[ExpandYear + 1] - 1
        else
          EndIndex := listBox1.Items.Count - 1;
    end;

    // 天的索引为月点击(SubItemIndex)MItemIndex+1 - 下一个(EndIndex)MItemIndex + 1 之间的索引
    with ListBox1 do
    begin
      BeginUpdate;
      for SubItemIndex := MonthIndex[ExpandYear, FindItemIndex] + 1 to EndIndex do  // 将该月的下一级从第一个到最后一个遍历显示
      begin
        if ExpandMonth = -1 then
          begin
            ListBox1.ListItems[SubItemIndex].Height := 30;
            ListBox1.ListItems[SubItemIndex].Visible := true;
          end
        else
          begin
            ListBox1.ListItems[SubItemIndex].Height := 0;
            ListBox1.ListItems[SubItemIndex].Visible := false;
          end;
      end;
      if ExpandMonth = -1 then
        ExpandMonth := FindItemIndex
      else
        ExpandMonth := -1;
      EndUpdate;
    end;
  end;
end;


end.
原文地址:https://www.cnblogs.com/studypanp/p/4931097.html