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.