在 FMXUI 中,有 TListExView 和 TListViewEx 兩個ListView。其中第一個是對Delphi原有TListView的功能擴展版,用法和原有的基本一樣。TListViewEx 則是 FMXUI 原創的一個 ListView , 今天我們要介紹的就是它了。
# 一、 IListAdapter 數據適配器
TListViewEx 的設計思想與Java原生安卓開發類似,使用了數據與顯示分離的適配器模式。組件本身不存放數據,只負責顯示控制。用戶可以使用自帶的幾個簡單的數據適配器或者實現IListAdapter接口,打造自己的數據適配器。通過自帶義數據適配器,我們可以實現任意樣式的列表。所以,這里的 IListAdapter 接口的重要性不言而預。
我們來看看 IListAdapter 的定義:

~~~
/// <summary>
/// 列表適配器接口
/// </summary>
IListAdapter = interface
['{5CC5F4AB-2D8C-4A84-98A7-51566E38EA47}']
function GetCount: Integer;
function GetItemID(const Index: Integer): Int64;
function GetItem(const Index: Integer): Pointer;
function IndexOf(const AItem: Pointer): Integer;
function GetView(const Index: Integer; ConvertView: TViewBase; Parent: TViewGroup): TViewBase;
function GetItemViewType(const Index: Integer): Integer;
function IsEmpty: Boolean;
function IsEnabled(const Index: Integer): Boolean;
function ItemDefaultHeight: Single;
procedure Clear;
procedure Repaint;
procedure NotifyDataChanged;
property Count: Integer read GetCount;
property Items[const Index: Integer]: Pointer read GetItem; default;
end;
~~~

* GetCount: 返回數據的大小(總行數)
* GetItemID: 指定索引項數據的ID(可以直接使用索引號)
* GetItem: 獲取指定索引的數據
* IndexOf: 查找數據,返回索引號
* GetView: 根據索引號,返回對應的可視對象(這個超級重要!!)
* GetItemViewtype: 返回指定索引號的視圖類型(這個也是重點)
* IsEmpty: 判斷列表是否為空(Count = 0)
* IsEnabled: 判斷某行數據是否有效
* ItemDefaultHeight: 默認行高度(很重要,返回所有視圖類型中的最大默認行高)
* Clear: 清空數據
* Repaint: 重繪
* NotifyDataChanged: 通知列表框組件數據已經更新,需要重新繪制
* Count: 數據的總數
在接口中, 最常用的 GetView , GetItemViewType, ItemDefaultHeight , GetCount 這四個。一般情況我們只需要繼承 TListAdapterBase 或者 TListAdapter , 然后重載這四個函數就可以了。
# 二、 使用 ListView
我們實現如下效果。

## 第一步: 創建自定義列表項視圖。
添加一個Frame,命名為?CustomListView\_ListItem?。然后設計成這樣:

## 第二步: 創建數據適配器

~~~
type
TDataItem = record
Name: string;
Phone: string;
Color: TAlphaColor;
end;
TCustomListDataAdapter = class(TListAdapterBase)
private
[Weak] FList: TList<TDataItem>;
protected
function GetCount: Integer; override;
function ItemDefaultHeight: Single; override;
function GetItem(const Index: Integer): Pointer; override;
function IndexOf(const AItem: Pointer): Integer; override;
function GetView(const Index: Integer; ConvertView: TViewBase;
Parent: TViewGroup): TViewBase; override;
public
constructor Create(const AList: TList<TDataItem>);
end;
....
{ TCustomListDataAdapter }
constructor TCustomListDataAdapter.Create(const AList: TList<TDataItem>);
begin
FList := AList;
end;
function TCustomListDataAdapter.GetCount: Integer;
begin
if Assigned(FList) then
Result := FList.Count
else
Result := 0;
end;
function TCustomListDataAdapter.GetItem(const Index: Integer): Pointer;
begin
Result := nil;
end;
function TCustomListDataAdapter.GetView(const Index: Integer;
ConvertView: TViewBase; Parent: TViewGroup): TViewBase;
var
ViewItem: TCustomListView_ListItem;
Item: TDataItem;
begin
if (ConvertView = nil) or (not (ConvertView.ClassType = TCustomListView_ListItem)) then begin
ViewItem := TCustomListView_ListItem.Create(Parent);
ViewItem.Parent := Parent;
ViewItem.Width := Parent.Width;
ViewItem.CanFocus := False;
end else
ViewItem := TObject(ConvertView) as TCustomListView_ListItem;
Item := FList.Items[Index];
ViewItem.BeginUpdate;
ViewItem.TextView1.Text := Item.Name;
ViewItem.TextView2.Text := Item.Phone;
ViewItem.View1.Background.ItemDefault.Color := Item.Color;
ViewItem.EndUpdate;
Result := TViewBase(ViewItem);
end;
function TCustomListDataAdapter.IndexOf(const AItem: Pointer): Integer;
begin
Result := -1;
end;
function TCustomListDataAdapter.ItemDefaultHeight: Single;
begin
Result := 72;
end;
~~~

## 第三步、應用數據適配器
在窗口上添加 TListViewEx,命名為 ListView。 在窗口初始化事件中, 初始化數據適配器。
~~~
procedure TCustomListview.DoCreate;
begin
inherited;
FList := TList<TDataItem>.Create();
FAdapter := TCustomListDataAdapter.Create(FList);
end;
~~~
在窗口 Show 事件中,為 ListView 指定數據適配器。
~~~
procedure TCustomListview.DoShow;
begin
inherited;
ListView.Adapter := FAdapter;
AddItems(20); // 添加20行測試數據
end;
~~~
在窗口釋放事件中,釋放資源

~~~
procedure TCustomListview.DoFree;
begin
inherited;
ListView.Adapter := nil;
FAdapter := nil;
FreeAndNil(FList);
end;
~~~

添加測試數據的代碼

~~~
procedure TCustomListview.AddItems(const Count: Integer);
var
I: Integer;
Item: TDataItem;
begin
for I := 0 to Count - 1 do begin
Item.Name := '用戶名稱' + IntToStr(I);
if I mod 2 = 0 then
Item.Color := TAlphaColorRec.Crimson
else
Item.Color := TAlphaColorRec.Yellow;
Item.Phone := '131 0000 0000';
FList.Add(Item);
end;
FAdapter.NotifyDataChanged;
end;
~~~

注意:?數據變更后,需要及時調用 NotifyDataChanged 來通知 ListView 更新顯示。
# 三、 下拉刷新和上拉加載更多
TListViewEx 也實現了下拉刷新和上拉加載更多的功能。在屬性面板中啟用相應的選項即可。
* EnablePullRefresh: 是否啟用下拉刷新
* EnablePullLoad: 是否啟用上拉加載更多
* OnInitFooter: 加載自定義 Footer 事件, 如果不設置,將在需要時加載默認的 Footer
* OnInitHeader: 加載自定義 Header 事件, 如果不設置,將在需要時加載默認的 Header
* OnPullRefresh: 下拉刷新事件
* OnPullLoad: 上拉加載更多事件
TListViewEx 允許自定義 Footer 和 Header, 只需要在上述相應的事件中,初始化為對應的視圖就可以了。自定義視圖的實現方式也是新建一個 Frame 就可以了, 參考 ListItem 和默認的實現。不同的時需要實現?IListViewHeader?接口。
示例:

~~~
procedure TCustomListview.ListViewPullLoad(Sender: TObject);
begin
DelayExecute(1,
procedure (Sender: TObject)
begin
AddItems(20);
ListView.PullLoadComplete;
end
);
end;
procedure TCustomListview.ListViewPullRefresh(Sender: TObject);
begin
Hint('正在加載數據');
DelayExecute(2,
procedure (Sender: TObject)
begin
FList.Clear;
AddItems(20);
ListView.PullRefreshComplete;
end
);
end;
~~~
- 1.制作Android Splash啟動界面
- 2.delphi之完美Splash方案
- 3. Android實例-解決虛擬鍵盤遮擋問題
- 0.Android開發小技巧
- 設 置 您 的 開 發 環 境 Windows PC(Android)
- Delphi XE控件
- 手機屏幕自適應程序問題
- 手勢操作
- delphi xeandroid對硬件操作
- Datasnap
- Delphi XE 10 跨平臺三層數據庫應用教程
- 開發數據庫三層應用的DataSnap
- ListView
- delphi xe10之控件 listview 的強大功能
- FMX.TListView的基本用法
- 初探ListView 的使用方法
- Delphi 常用控件之TlistView總結
- ListView基本用法大全
- android實現透明度可以調整的對話框
- android 獲取網絡狀態
- FMXUI
- FMXUI - ListView用法簡介