Xamarin.Forms: 無限滾動的ListView(懶載入方式)

芝麻麻雀發表於2021-01-29

說明

在本部落格中,學習如何在Xamarin.Forms應用程式中設計一個可擴充套件的無限滾動的ListView。這個無限滾動函式在預設的Xamarin.Forms不存在,因此我們需要為此新增外掛。在這裡我們需要知道無限滾動時如何工作的。首先,顯示固定的資料。一旦使用者滾動到末尾,我們可以在列表的末尾新增更多的資料,這樣,列表就會不斷滾動,直到資料結束。

讓我們開始吧

第一步

建立一個新的Xamarin.Forms工程,開啟Visual Studio,點選新建->專案->在對話方塊中選擇移動應用(Xamarin.Forms),並點選下一步**

(未使用原文圖片)

第二步

接下來,出現一個新的對話方塊,在這裡給出應用程式和解決方案的名稱,名字為:XFInfiniteScroll,然後點選建立

(未使用原文圖片)

第三步

之後,在新的對話方塊視窗中,選擇你的Xamarin.Forms應用模板型別和平臺之後點選確定,在這裡,我選擇選項卡式模板和Android,iOS平臺。因為這裡選擇空模板時,沒有成功,改選用選項卡模板

(未使用原文圖片)

第四步

在專案建立完成之後,安裝Xamarin.Forms.Extended.Infinitescrolling NuGet包。右鍵點選解決方案並選擇管理解決方案的NuGet程式包,注:需要選中包括預發行版選項

第五步

現在,在專案XFInfiniteScroll 選中Models資料夾,右擊新增一個類,名稱為:InfiniteItems,程式碼如下:

namespace XFInfiniteScroll.Models
{
    public class InfiniteItems
    {
        public string Id { get; set; }
        public string Text { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
    }
}

第六步

繼續在專案XFInfiniteScroll中,新增一個資料夾,名稱為:FakeDataSource,在資料夾中新增一個相當於提供模擬資料的類,名稱為:InfiniteDataItems,程式碼如下:

namespace XFInfiniteScroll.FakeDataSource
{
    public static class InfiniteDataItems
    {
        public static List<InfiniteItems> GetItems()
        {
            var _items = new List<InfiniteItems>();
            _items.Add(new InfiniteItems { Id = "1", Text = "Item1", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "2", Text = "Item2", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "3", Text = "Item3", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "4", Text = "Item4", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "5", Text = "Item5", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "6", Text = "Item6", Title = "FirstItemGronew InfiniteItemsup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "7", Text = "Item7", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "8", Text = "Item8", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "9", Text = "Item9", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "10", Text = "Item10", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "11", Text = "Item11", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "12", Text = "Item12", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "13", Text = "Item13", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "14", Text = "Item14", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "15", Text = "Item15", Title = "FirstItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "16", Text = "Item16", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "17", Text = "Item17", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "18", Text = "Item18", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "19", Text = "Item19", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "20", Text = "Item20", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "21", Text = "Item21", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "22", Text = "Item22", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "23", Text = "Item23", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "24", Text = "Item24", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "25", Text = "Item25", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "26", Text = "Item26", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "27", Text = "Item27", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "28", Text = "Item28", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "29", Text = "Item29", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "30", Text = "Item30", Title = "SecondItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "31", Text = "Item31", Title = "ThirdItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "32", Text = "Item32", Title = "ThirdItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "33", Text = "Item33", Title = "ThirdItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "34", Text = "Item34", Title = "ThirdItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "35", Text = "Item35", Title = "ThirdItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "36", Text = "Item36", Title = "ThirdItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "37", Text = "Item37", Title = "ThirdItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "38", Text = "Item38", Title = "ThirdItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "39", Text = "Item39", Title = "ThirdItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "40", Text = "Item40", Title = "FourthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "41", Text = "Item41", Title = "FourthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "42", Text = "Item42", Title = "FourthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "43", Text = "Item43", Title = "FourthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "45", Text = "Item44", Title = "FourthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "46", Text = "Item45", Title = "FourthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "47", Text = "Item46", Title = "FourthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "48", Text = "Item47", Title = "FourthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "49", Text = "Item48", Title = "FourthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "50", Text = "Item50", Title = "FifthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "51", Text = "Item51", Title = "FifthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "52", Text = "Item52", Title = "FifthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "53", Text = "Item53", Title = "FifthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "54", Text = "Item54", Title = "FifthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "55", Text = "Item55", Title = "FifthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "56", Text = "Item56", Title = "FifthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "57", Text = "Item57", Title = "FifthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "58", Text = "Item58", Title = "FifthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "59", Text = "Item59", Title = "FifthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "60", Text = "Item60", Title = "FifthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "61", Text = "Item61", Title = "SixthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "62", Text = "Item62", Title = "SixthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "63", Text = "Item63", Title = "SixthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "64", Text = "Item64", Title = "SixthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "65", Text = "Item65", Title = "SixthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "66", Text = "Item66", Title = "SixthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "67", Text = "Item67", Title = "SixthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "68", Text = "Item68", Title = "SixthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "69", Text = "Item69", Title = "SixthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "70", Text = "Item70", Title = "SixthItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "71", Text = "Item71", Title = "SeventhItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "72", Text = "Item72", Title = "SeventhItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "73", Text = "Item73", Title = "SeventhItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "74", Text = "Item74", Title = "SeventhItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "75", Text = "Item75", Title = "SeventhItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "76", Text = "Item76", Title = "SeventhItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "77", Text = "Item77", Title = "SeventhItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "78", Text = "Item78", Title = "SeventhItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "79", Text = "Item79", Title = "SeventhItemGroup", Description = "Test Items" });
            _items.Add(new InfiniteItems { Id = "80", Text = "Item80", Title = "SeventhItemGroup", Description = "Test Items" });

            return _items;
        }

        public static async Task<List<InfiniteItems>> GetItemsAsync(int pageIndex, int pageSize)
        {
            await Task.Delay(2000);
            var _items = GetItems();
            return _items.Skip(pageIndex * pageSize).Take(pageSize).ToList();
        }
    }
}

第七步

由於本專案採用的是選項卡模板,並且目前已使用Shell方式(可以參考:Xamarin.Forms Shell
修改AppShell.xaml檔案程式碼如下:

    <TabBar>
        <Tab Title="Infinite Scroll" Icon="icon_about.png">
            <ShellContent Title="Single">
                <local:SingleViewPage>
                </local:SingleViewPage>
            </ShellContent>
            <ShellContent Title="Group">
                <local:GroupViewPage>
                </local:GroupViewPage>
            </ShellContent>
        </Tab>
        <ShellContent
            Title="About"
            ContentTemplate="{DataTemplate local:AboutPage}"
            Icon="icon_about.png"
            Route="AboutPage" />
        <ShellContent
            Title="Browse"
            ContentTemplate="{DataTemplate local:ItemsPage}"
            Icon="icon_feed.png" />

    </TabBar>

此處,對於TabbedPage的用法出現錯誤,因此只能採用此種方法處理頁面的佈局

在資料夾Views中分別新增SingleViewPageGroupViewPage內容頁。直接在下面圖片中修改檔名即可。

SingleViewPage頁面佈局

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="XFInfiniteScroll.Views.SingleViewPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:extended="clr-namespace:Xamarin.Forms.Extended;assembly=Xamarin.Forms.Extended.InfiniteScrolling"
    BackgroundColor="Red">
    <ContentPage.Content>
        <ListView
            x:Name="ListSingleItems"
            HasUnevenRows="True"
            HorizontalOptions="FillAndExpand"
            VerticalOptions="FillAndExpand">
            <ListView.Behaviors>
                <extended:InfiniteScrollBehavior IsLoadingMore="{Binding IsWorking}">
                </extended:InfiniteScrollBehavior>
            </ListView.Behaviors>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid Padding="12">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="20" />
                                <RowDefinition Height="20" />
                            </Grid.RowDefinitions>
                            <Label Grid.Row="0" Text="{Binding Text}">
                            </Label>
                            <Label Grid.Row="1" Text="{Binding Description}">
                            </Label>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
            <ListView.Footer>
                <Grid Padding="6">
                    <Label
                        HorizontalOptions="Center"
                        IsVisible="{Binding IsWorking}"
                        Text="Loading..."
                        VerticalOptions="Center">
                    </Label>
                </Grid>
            </ListView.Footer>
        </ListView>
    </ContentPage.Content>
</ContentPage>

GroupViewPage頁面佈局

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="XFInfiniteScroll.Views.GroupViewPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:extended="clr-namespace:Xamarin.Forms.Extended;assembly=Xamarin.Forms.Extended.InfiniteScrolling">
    <ContentPage.Content>
        <ListView
            x:Name="GroupItems"
            HasUnevenRows="True"
            HorizontalOptions="FillAndExpand"
            IsGroupingEnabled="True"
            VerticalOptions="FillAndExpand">
            <ListView.Behaviors>
                <extended:InfiniteScrollBehavior IsLoadingMore="{Binding IsWorking}" />
            </ListView.Behaviors>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid Padding="12">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*">
                                </ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="20">
                                </RowDefinition>
                                <RowDefinition Height="20">
                                </RowDefinition>
                            </Grid.RowDefinitions>
                            <Label
                                Grid.Row="0"
                                Text="{Binding Text}"
                                TextColor="Black">
                            </Label>
                            <Label
                                Grid.Row="1"
                                Text="{Binding Description}"
                                TextColor="Black">
                            </Label>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
            <ListView.GroupHeaderTemplate>
                <DataTemplate>
                    <ViewCell Height="25">
                        <Grid BackgroundColor="White">
                            <Label
                                FontAttributes="None"
                                FontSize="16"
                                HorizontalTextAlignment="Center"
                                Text="{Binding Header}"
                                TextColor="Blue"
                                VerticalTextAlignment="Center">
                            </Label>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.GroupHeaderTemplate>
            <ListView.Footer>
                <Grid Padding="6">
                    <Label
                        HorizontalOptions="Center"
                        IsVisible="{Binding IsWorking}"
                        Text="Load..."
                        TextColor="Black"
                        VerticalOptions="Center">
                    </Label>
                </Grid>
            </ListView.Footer>
        </ListView>
    </ContentPage.Content>
</ContentPage>

對於後臺程式碼,可以在GitHub上面參考。https://github.com/mzy666888/XFInfiniteScroll

第八步

現在,可以執行你的Xamarin.Forms應用程式,並可以看到以下的輸出內容。
在本機上執行介面:
視訊地址:https://www.zhihu.com/zvideo/1338425998501240832

看一下原文中的動圖顯示

iOS

Android

原文地址https://xmonkeys360.com/2021/01/04/xamarin-forms-infinite-scroll-listview-lazy-loading/

相關文章