Xamarin.Forms Views介紹(六)——ListView

ListView用來顯示列表數(shù)據(jù)贮喧,適合單一類型數(shù)據(jù)集合铲球。

ListView屬性

  • Footer :object類型野蝇,獲取名扛、設(shè)置列表底部的字符串或視圖谅年。
  • FooterTemplate :DataTemplate類型,獲取肮韧、設(shè)置列表底部數(shù)據(jù)模版融蹂。
  • Header :object類型,獲取弄企、設(shè)置列表頂部的字符串或視圖超燃。
  • HeaderTemplate :DataTemplate類型,獲取拘领、設(shè)置列表定部數(shù)據(jù)模版意乓。
  • HasUnevenRows :bool類型,表示列表是否有不均勻的行高院究,默認(rèn)值false洽瞬,設(shè)置為true后ListView每行的高度會因為內(nèi)容不同而提供不同高度。

可以在運行時通過Cell.ForceUpdateSize
方法更新cell大小业汰。

  • IsGroupingEnabled :bool類型伙窃,表示是否對列表進行分組。
  • GroupDisplayBinding:綁定分組頭的值样漆。
  • GroupHeaderTemplate:DataTemplate類型为障,分組頭的數(shù)據(jù)模版。
  • GroupShortNameBinding:綁定分組跳轉(zhuǎn)列表中的值放祟。
  • IsPullToRefreshEnabled :bool類型鳍怨,表示列表是否可以進行下拉刷新。
  • IsRefreshing :bool類型跪妥,表示列表是否正在刷新鞋喇。
  • RowHeight :表示列表行高。
  • SelectedItem :object類型眉撵,表示列表當(dāng)前選中對象侦香。
  • SeparatorColor :表示列表分割欄的顏色落塑。
  • SeparatorVisibility :SeparatorVisibility枚舉,表示分割欄的顯示方式罐韩。

ListView事件

  • ItemAppearing :ListView元素顯示時觸發(fā)憾赁,ListView滑動使Item顯示在屏幕內(nèi)。
  • ItemDisappearing :ListView元素消失時觸發(fā)散吵,ListView滑動使Item消失在屏幕內(nèi)龙考。
  • ItemSelected :新的Item元素被選中時觸發(fā)。
  • ItemTapped :ListView的元素Item被點擊是觸發(fā)矾睦。
  • Refreshing :ListView刷新事件晦款。

ListView基本使用

填充ListView顯示的數(shù)據(jù)有兩種方式:設(shè)置ListView的ItemsSource和Data Binding。Data Binding后面介紹枚冗。ItemsSource類型是IEnumerable柬赐。
XAML定義ListView會默認(rèn)填充整個屏幕

<ListView x:Name="listView"/>

通過C#代碼設(shè)置ItemsSource:

listView.ItemsSource = new List<string>() {
    "List Item 1","List Item 2","List Item 3","List Item 4","List Item 5"
};
ListView效果

IOS會有多余分割線顯示可以通過代碼隱藏分割線listView.SeparatorVisibility = SeparatorVisibility.None;

默認(rèn)情況下ItemSource集合提供的數(shù)據(jù)調(diào)用ToString方法顯示在TextCell上,即
ListView每行是一個TextCell官紫。

定義XAML時設(shè)置ItemsSource:

<ListView>
    <ListView.ItemsSource>
        <x:Array Type="{x:Type x:String}">
            <x:String>Item 1</x:String>
            <x:String>Item 2</x:String>
            <x:String>Item 3</x:String>
            <x:String>Item 4</x:String>
            <x:String>Item 5</x:String>
            <x:String>Item 6</x:String>
        </x:Array>
    </ListView.ItemsSource>
</ListView>

ListView 結(jié)合 Data Binding使用

ListView的數(shù)據(jù)源(ItemsSource)不僅可以是簡單的字符串集合也可以是自定義的Model類集合肛宋,要顯示類集合數(shù)據(jù)時需要結(jié)合Data Binding實現(xiàn),演示一個TextCell顯示Text和Detail的示例束世。

Data Source設(shè)置代碼酝陈,ListViewItem是一個簡單的Model類不再展示:

在定義ItemSource的數(shù)據(jù)集合時推薦用ObservableCollection<T>代替List<T>,ObservableCollection實現(xiàn)了INotifyPropertyChanged接口能夠通知數(shù)據(jù)的變化,提供更新功能毁涉。

在XAML代碼中定義ListVIew時應(yīng)顯示指出TextCell的展現(xiàn)形式沉帮。設(shè)置ListView.ItemTemplate,DataTemplate元素節(jié)點內(nèi)定義一個TextCell,綁定 TextCell的Text和Detail屬性為對應(yīng)Model的屬性贫堰。

<ListView x:Name="listView">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextCell Text="{Binding Title}" Detail="{Binding Detail}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

ListView Selected事件

當(dāng)用戶點擊ListView的Item時觸發(fā)ListView的ItemTapped事件穆壕,SelectedItem值發(fā)生改變還會觸發(fā)ItemSelected事件,用戶連續(xù)點擊同一個Item時ItemTapped觸發(fā)多次其屏,SelectedItem只會在第一次點擊時觸發(fā)喇勋。
如果想使ListView禁用ListView被取消ListView的選中效果

listView.ItemSelected += (sender, e) => {
    listView.SelectedItem = null;
};

ListView Cell介紹

前面有提到過TextCell,是Xamarin.Forms 提供的Cell子類可以幫助我們顯示更復(fù)雜的ListView偎行。

Xamarin.Forms提供給ListVIew常用的Cell有兩種:TextCellImageCell川背。SwitchCellEntryCell通常用在TableView中。

TextCell用來顯示文本蛤袒,并允許在第二行顯示詳細(xì)文本:
Text – 顯示在第一行的文本熄云,以較大字體顯示.
Detail – 以較小字體顯示在第二行的文本.
TextColor – Text文本顏色.
DetailColor – Detail文本顏色.

ImageCell與TextCell相比在Cell的左側(cè)可以顯示圖片信息。ImageCell顯示圖片在Windows Phone 8.1 下默認(rèn)不會縮放妙真,所以會有如下效果:

至于Windows Phone顯示效果沒有親自測試缴允,默認(rèn)不會縮放在官網(wǎng)中有提到,不開發(fā)Windows Phone可以不考慮珍德。

具體使用參考ListView 結(jié)合 Data Binding使用练般。更復(fù)雜的列表效果需自定義單元格健蕊,繼承ViewCell實現(xiàn)期望的效果。自定義單元格更多信息參考:https://developer.xamarin.com/guides/xamarin-forms/user-interface/listview/customizing-cell-appearance/#Custom_Cells


ListView的Header和Footer

可以在ListView的頭部和尾部添加顯示簡單的文本或更加復(fù)雜的視圖布局踢俄。ListView的Header和Footer會隨ListView一起滾動。
如設(shè)置ListView的Header為一個簡單的字符串Footer為一個按鈕:

<ListView x:Name="listView">
    <ListView.Header>
        ListView Header
    </ListView.Header>
    <ListView.Footer>
        <Button Text="Load More"/>
    </ListView.Footer>
</ListView>

HeaderTemplate和FooterTemplate不是必須的晴及,涉及到數(shù)據(jù)綁定時才會用到都办。

如圖效果:


加載更多效果可以通過Footer設(shè)置為一個Button點擊加載跟多數(shù)據(jù)。


ListView分組

當(dāng)ListView展示大量數(shù)據(jù)時可以嘗試通過分組管理虑稼、展示數(shù)據(jù)琳钉,如iOS的通訊錄。
對ListView分組前蛛倦,必須先將數(shù)據(jù)進行分組歌懒,ListView分組的數(shù)據(jù)源應(yīng)該是集合的集合(collection of collections,后面給出示例)溯壶。準(zhǔn)備好數(shù)據(jù)源同時將ListView 的IsGroupingEnabled屬性設(shè)置為true及皂,表示ListView開啟分組功能。ListView提供了GroupDisplayBinding屬性且改,用來綁定每個分組的Title验烧,GroupShortNameBinding綁定一個索引字段。所以定義的GroupModel應(yīng)該包含一個Title屬性綁定到GroupDisplayBinding屬性(必須的)又跛,定義一個ShortName綁定到GroupShortNameBinding(可選值)碍拆,iOS會在右側(cè)提供一個索引列表。

本文示例慨蓝,ListView的item展現(xiàn)的是簡單的字符串感混,所以GroupModel定義繼承IEnumerable<string>,并定義Title和ShortName屬性用來綁定ListView的GroupDisplayBinding和GroupShortNameBinding屬性。定義一個IEnumerable<ItemModel>屬性表示沒個分組的數(shù)據(jù)礼烈,本例中ListView展示字符串?dāng)?shù)據(jù)弧满,所以定義為IEnumerable<sttring>。定義如下Model類:

public class ListViewGroup : ObservableCollection<string>
{
    public string GroupTitle
    {
        get;
        set;
    }

    public string ShortName
    {
        get;
        set;
    }

    public static ObservableCollection<ListViewGroup> Items
    {
        get;
        set;
    }

    static ListViewGroup()
    {
        Items = new ObservableCollection<ListViewGroup>();
        //創(chuàng)建虛擬數(shù)據(jù)
        var aGroup = new ListViewGroup
        {
            GroupTitle = "A Title",
            ShortName = "A"
        };
        aGroup.Add("Abs");
        aGroup.Add("Apple");
        aGroup.Add("Are");
        aGroup.Add("Add");
        Items.Add(aGroup);

        var bGroup = new ListViewGroup
        {
            GroupTitle = "B Title",
            ShortName = "B"
        };
        bGroup.Add("Bbs");
        bGroup.Add("Blue");
        bGroup.Add("Bar");
        bGroup.Add("Bana");
        Items.Add(bGroup);

        var cGroup = new ListViewGroup
        {
            GroupTitle = "C Title",
            ShortName = "C"
        };
        cGroup.Add("Cbs");
        cGroup.Add("Couple");
        cGroup.Add("Cut");
        cGroup.Add("Custum");
        Items.Add(cGroup);

        var dGroup = new ListViewGroup
        {
            GroupTitle = "D Title",
            ShortName = "D"
        };
        dGroup.Add("Dbs");
        dGroup.Add("Double");
        dGroup.Add("Delete");
        dGroup.Add("Developer");
        Items.Add(dGroup);
    }
}

XAML中綁定數(shù)據(jù)此熬,通過x:Static指定數(shù)據(jù)源為ListViewGroup的靜態(tài)屬性Items谱秽,設(shè)置IsGroupingEnabled為true,綁定GroupTitle的值到GroupDisplayBinding摹迷,同時綁定GroupShortNameBinding的值(不是必須的)疟赊,ListView.RowHeight屬性節(jié)點定義不同平臺Item顯示不同高度。結(jié)合Custum Cell知識峡碉,定義ItemTemplate的值:

<ListView ItemsSource="{x:Static local:ListViewGroup.Items}"
          IsGroupingEnabled="true"
          GroupDisplayBinding="{Binding GroupTitle}"
          GroupShortNameBinding="{Binding ShortName}">
     <ListView.RowHeight>
         <OnPlatform x:TypeArguments="x:Int32"
                     iOS="80"
                     Android="80"
                     WinPhone="90" />
     </ListView.RowHeight>

     <ListView.ItemTemplate>
         <DataTemplate>
             <ViewCell>
                 <ContentView Padding="5">
                    <Frame OutlineColor="Accent"
                           Padding="10">
                        <StackLayout Orientation="Horizontal">
                            <BoxView Color="#00ffdd"
                                     WidthRequest="50"
                                     HeightRequest="50" />
                            <Label Text="{Binding .}"
                                   FontSize="22"
                                   VerticalOptions="StartAndExpand" />
                         </StackLayout>
                     </Frame>
                 </ContentView>
             </ViewCell>
          </DataTemplate>
     </ListView.ItemTemplate>
        
</ListView>

Android近哟、iOS效果圖(GroupShortNameBinding屬性對Android平臺無效):

與定義ItemTemplate類似,ListView提供了GroupHeaderTemplate屬性方便我們自定義ListView的Group Header樣式鲫寄。示例代碼:

<ListView.GroupHeaderTemplate>
    <DataTemplate>
         <TextCell Text="{Binding Title}"
                   Detail="{Binding ShortName}"
                   TextColor="#f35e20"
                   DetailColor="#503026" />
    </DataTemplate>
</ListView.GroupHeaderTemplate>

ListView 刷新

設(shè)置ListView的IsPullToRefreshEnabled屬性為true吉执,使ListView支持下拉刷新疯淫。
下拉ListView有如下效果:

ListView 開啟下拉刷新

用戶下拉ListView會觸發(fā)Refreshing事件,在處理Refreshing事件重新加載數(shù)據(jù)后應(yīng)通過設(shè)置IsRefreshing為false或調(diào)用ListView的EndRefresh方法通知ListView數(shù)據(jù)加載完成以取消下拉加載的效果戳玫。

也可以通過調(diào)用ListView 的BeginRefresh方法觸發(fā)Refreshing事件熙掺。

ListView Context Actions

有時我們需要為ListView的每一項提供菜單行為,如Item的刪除咕宿。IOS為左滑動Item币绩,Android和Windows Phone為長按Item。

ListView Item菜單

Context Actions依靠MenuItem實現(xiàn)府阀,可以通過C#或XAML代碼定義缆镣。MenuItem提供了Clicked事件響應(yīng)MenuItem的點擊,MenuItem繼承BaseMenuItem试浙,有三個常用屬性屬性:

  • Text – string類型董瞻,表示MenuItem顯示文本.
  • Icon – FileImageSource類型,表示MenuItem圖標(biāo).
  • IsDestructive – bool類型,值為true時iOS平臺MenuItem以紅色背景渲染.

C# 定義Context Action

定義MenuItem添加到Cell的ContextActions屬性中即可。這里不再給出C#代碼設(shè)置ListView的ItemTemplate示例田巴,所以圖片代碼為代碼片段钠糊。可參考:http://stackoverflow.com/questions/38585153/implementing-xamarin-forms-context-actions

默認(rèn)情況下響應(yīng)MenuItem的點擊事件并不能判斷當(dāng)前MenuItem屬于哪個Cell壹哺,可以通過MenuItem的CommandParameter屬性綁定一個值確定操作的Cell眠蚂。參考MenuItem響應(yīng)事件。

XAML 定義Context Action:

<ListView x:Name="listView">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextCell Text="{Binding Title}" Detail="{Binding Detail}">
                <TextCell.ContextActions>
                <MenuItem Clicked="OnShare" CommandParameter="{Binding .}" Text="分享" />
                    <MenuItem Clicked="OnDelete" CommandParameter="{Binding .}" Text="刪除" IsDestructive="True" />
                </TextCell.ContextActions>
            </TextCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

ListView 性能優(yōu)化

應(yīng)用程序中使用ListView一定要確保ListView的性能(快速加載和平滑滾動)斗躏。Xamarin.Forms提供了Caching Strategy(緩存策略)優(yōu)化ListView使用性能,對應(yīng)ListView的CachingStrategy屬性逝慧。也可以通過ListView使用過程中的一些技巧提升ListView的性能。

Caching Strategy

ListView用來展示大量數(shù)據(jù)啄糙,默認(rèn)情況下ListView會為每條記錄創(chuàng)建一個Cell笛臣,耗費大量內(nèi)存,通過Caching Strategy減少內(nèi)存使用隧饼,提高ListView性能沈堡。ListViewCachingStrategy枚舉包含兩個值RetainElement和RecycleElement。

ListViewCachingStrategy枚舉

RetainElement:
為列表中的沒一項生成一個Cell燕雁,是ListView的默認(rèn)行為诞丽。如下情況應(yīng)使用該值:

  • 每個單元格(Cell)擁有大量的數(shù)據(jù)綁定(20-30+).
  • 單元格模版(Cell Template)變化頻繁。
  • 設(shè)置為RecycleElement值時ListView性能降低拐格,應(yīng)使用該值僧免。(When testing reveals that the RecycleElement value results in a reduced execution speed. )

RecycleElement:
設(shè)置為該值時ListView嘗試通過重復(fù)利用Cell減少內(nèi)存使用和提高執(zhí)行速度。RecycleElement不一定會提高ListView的使用性能捏浊,但如下情況應(yīng)使用該值:

  • 單元格有很少的數(shù)據(jù)綁定
  • 沒個單元格的數(shù)據(jù)源由Cell的BindingContext屬性提供
  • 沒個單元格擁有相同的單元格模版

XAML中通過代碼CachingStrategy="RecycleElement"指定CachingStrategy的模式懂衩。C#代碼中ListView沒有提供CachingStrategy屬性,設(shè)置CachingStrategy的值要在ListView 的構(gòu)造函數(shù)中傳入設(shè)置的值。

ListView設(shè)置CachingStrategy="RecycleElement"浊洞,簡單的顯示string集合出現(xiàn)元素顯示重復(fù)問題牵敷。

RecycleElement引起的問題

顯式設(shè)置ListView.ItemTemplate后運行正常。

<ListView x:Name="listView" CachingStrategy="RecycleElement">
    <ListView.ItemTemplate>
        <DataTemplate>
        <TextCell Text="{Binding .}"/>
        </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

自定義Cell時應(yīng)該重寫OnBindingContextChanged方法法希,以保證設(shè)置ListView的屬性CachingStrategy="RecycleElement"時顯示正常枷餐。


Improving ListView Performance

ListView使用過程中很多技巧可以幫助我們提高ListView的性能:

  • 對于綁定的數(shù)據(jù)源用IList<T> 集合代替 IEnumerable<T>集合。
  • 盡量使用Forms提供的Cell(TextCell / SwitchCell)苫亦,避免自定義Cell毛肋。
  • 自定Cell時減少布局嵌套和使用視圖,布局盡量使用AbsoluteLayout 和 Grid著觉,對于LayoutOptions屬性盡量設(shè)置為Fill。
  • 顯示不規(guī)律數(shù)據(jù)時用TableView代替ListView惊暴。
  • 減少Cell.ForceUpdateSize方法的調(diào)用饼丘。
  • 避免將ListView放置在ScrollView中使用。
  • 過于復(fù)雜的Cell辽话,盡量使用Custom Renderer(以后介紹)肄鸽。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市油啤,隨后出現(xiàn)的幾起案子典徘,更是在濱河造成了極大的恐慌,老刑警劉巖益咬,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逮诲,死亡現(xiàn)場離奇詭異,居然都是意外死亡幽告,警方通過查閱死者的電腦和手機梅鹦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來冗锁,“玉大人齐唆,你說我怎么就攤上這事《澈樱” “怎么了箍邮?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長叨叙。 經(jīng)常有香客問我锭弊,道長,這世上最難降的妖魔是什么擂错? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任廷蓉,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘桃犬。我一直安慰自己刹悴,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布攒暇。 她就那樣靜靜地躺著土匀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪形用。 梳的紋絲不亂的頭發(fā)上就轧,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音田度,去河邊找鬼妒御。 笑死,一個胖子當(dāng)著我的面吹牛镇饺,可吹牛的內(nèi)容都是我干的乎莉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼奸笤,長吁一口氣:“原來是場噩夢啊……” “哼惋啃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起监右,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤边灭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后健盒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绒瘦,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年扣癣,在試婚紗的時候發(fā)現(xiàn)自己被綠了椭坚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡搏色,死狀恐怖善茎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情频轿,我是刑警寧澤垂涯,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站航邢,受9級特大地震影響耕赘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜膳殷,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一操骡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦册招、人聲如沸岔激。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虑鼎。三九已至,卻和暖如春键痛,著一層夾襖步出監(jiān)牢的瞬間胧沫,已是汗流浹背滑燃。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留霜医,地道東北人晚顷。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓隧期,卻偏偏與公主長得像按声,于是被迫代替她去往敵國和親裸违。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理限府,服務(wù)發(fā)現(xiàn)夺颤,斷路器痢缎,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,162評論 25 707
  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一種新的協(xié)議胁勺。它實...
    香橙柚子閱讀 23,869評論 8 183
  • 何方僧侶攜我肌骨 來趕一場鮮花的超度 煙火不清不白。 木魚聲聲敲打鈍痛 四月所及孤墳遍野 經(jīng)綸又因誰焚唱独旷? 為這碌...
    故墻閱讀 229評論 11 8
  • 陌生人社會署穗,完全是信息不對稱的,隔閡的嵌洼。所以我們有名片案疲,展示我們的閃光點。 首先麻养,高手通過聲音能聽出他的籍貫褐啡。其次...
    夜雨狂歌如夢閱讀 206評論 0 0