• Stars
    star
    134
  • Rank 262,081 (Top 6 %)
  • Language
    C#
  • License
    MIT License
  • Created over 6 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A small library to quickly and easily add infinite/endless scrolling support to any Xamarin.Forms ListView.

Infinite Scrolling

Build status NuGet NuGet Pre Release

A small library to quickly and easily add infinite/endless scrolling support to any Xamarin.Forms ListView.

Usage

Adding infinite scrolling support to a ListView is done in two steps. First we add the InfiniteScrollBehavior to the ListView's behaviors:

<!-- xmlns:scroll="clr-namespace:Xamarin.Forms.Extended;assembly=Xamarin.Forms.Extended.InfiniteScrolling" -->

<!-- a normal list view -->
<ListView CachingStrategy="RecycleElement" ItemsSource="{Binding Items}">

    <!-- the behavior that will enable infinite scrolling -->
    <ListView.Behaviors>
        <scroll:InfiniteScrollBehavior />
    </ListView.Behaviors>

    ...

</ListView>

And then, we need to make use of the InfiniteScrollCollection<T> as our collection type (instead of ObservableCollection<T> or List<T>):

using Xamarin.Forms.Extended.InfiniteScrolling;

public class MainViewModel : BaseViewModel
{
    private const int PageSize = 20;

    public MainViewModel()
    {
        Items = new InfiniteScrollCollection<DataItem>
        {
            OnLoadMore = async () =>
            {
                // load the next page
                var page = Items.Count / PageSize;
                var items = await dataSource.GetItemsAsync(page + 1, PageSize);

                // return the items that need to be added
                return items;
            }
        };
    }

    public InfiniteScrollCollection<DataItem> Items { get; }
}

That's it! All we needed was the behavior and the collection type. The rest is automatically handled for us. If we need to manually trigger the list to load more, for example to initialize the list, we can just use the LoadMoreAsync method:

Items.LoadMoreAsync();

Loading Placeholder

Although this library does not provide any placeholders by default, we can easily add one by making use of the IsLoadingMore property of InfiniteScrollBehavior and the ListView footer:

<ListView ...>

    <!-- the behavior bound to IsWorking -->
    <ListView.Behaviors>
        <scroll:InfiniteScrollBehavior IsLoadingMore="{Binding IsWorking}" />
    </ListView.Behaviors>

    <!-- the "loading..." view, with visibility bound to IsWorking -->
    <ListView.Footer>
        <Grid Padding="6" IsVisible="{Binding IsWorking}">
            <!-- set the footer to have a zero height when invisible -->
            <Grid.Triggers>
                <Trigger TargetType="Grid" Property="IsVisible" Value="False">
                    <Setter Property="HeightRequest" Value="0" />
                </Trigger>
            </Grid.Triggers>
            <!-- the loading content -->
            <Label Text="Loading..." VerticalOptions="Center" HorizontalOptions="Center" />
        </Grid>
    </ListView.Footer>

</ListView>

Advanced Usage

The way the custom collection works is to implement various interfaces that the behavior is listening for. We can use these interfaces to convert any collection into a infinite-loading collection:

IInfiniteScrollLoader

The IInfiniteScrollLoader interface is required as it is the primary means in which the behavior lets the collection know to load more data:

public interface IInfiniteScrollLoader
{
    // returns true if the list should load more
    bool CanLoadMore { get; }

    // the method that actually loads more data
    Task LoadMoreAsync();
}

Depending on what the user does with the list view, the behavior will first check the CanLoadMore property to see if more data needs to be loaded. If this property returns true, then the behavior will call the LoadMoreAsync method. This method can perform any loading from anywhere (a database or remote service) and then add new items to the list.

IInfiniteScrollLoading

The IInfiniteScrollLoading interface is optional and provides the behavior with notifications if the starts loading more data - without the list view asking for more:

public interface IInfiniteScrollLoading
{
    // the collection is loading more
    bool IsLoadingMore { get; }

    // the collection either began or completed a load
    event EventHandler<LoadingMoreEventArgs> LoadingMore;
}

If this interface is implemented, the behavior can be aware of events that were not triggered by the list view, but by a view model or code behind. When the collection wants to load more data, it needs to first raise the LoadingMore event with new LoadingMoreEventArgs(true). This is used to let the behavior know that it should not load items if the user scrolls since it is already happening. As soon as the load operation completes, the event should be raised again, but this time with the arguments new LoadingMoreEventArgs(false).

The IsLoadingMore property should accurately reflect the current state of loading. As soon as a load starts, the IsLoadingMore property must return true, and when loading completes, return false. This is because the behavior can, at any time, request the loading state without having to listen to the events. This is most important for the cases where the list obtains it's items via data binding, but the binding changes. At this point, the events may not be attached and there is no way for the behavior to know if a load operation has started or completed.

IInfiniteScrollDetector

The IInfiniteScrollDetector interface is optional and provides the behavior with an alternate means with which to check if the list needs to load more items based on the current scroll position:

public interface IInfiniteScrollDetector
{
    // returns true if the current item is at the point that more items are needed
    bool ShouldLoadMore(object currentItem);
}

Typically, this interface is not needed as the behavior will be watching the scroll can detect when more items are needed. However, the automatice detection requires that the items source implement the IList interface. This is usually true for an ObservableCollection<T> or List<T>, but there may be some instances where this is not the collection type. Or, we wish to have more control over when more items are loaded.

Implementing Interfaces

A possible implementation of all these interfaces might be:

public class InfiniteScrollCollection<T> : 
    ObservableCollection<T>, // the base collection type
    IInfiniteScrollLoader,   // [required]
    IInfiniteScrollLoading,  // [optional]
    IInfiniteScrollDetector  // [optional]
{
    // for tracking the state of a load operation
    private bool isLoadingMore;

    public InfiniteScrollCollection()
    {
    }

    public InfiniteScrollCollection(IEnumerable<T> collection)
        : base(collection)
    {
    }

    // we can load forever
    public bool CanLoadMore => true;

    // the list has determined that we need more items
    public async Task LoadMoreAsync()
    {
        // we are starting a load, set the property and raise the event
        isLoadingMore = true;
        LoadingMore?.Invoke(this, new LoadingMoreEventArgs(true));

        // load more items
        var newItems = await LoadMoreDataFromSomewhereAsync();

        // add the new items to the list
        foreach (item in newItems)
        {
            Add(item);
        }

        // we have finished our load, set the property and raise the event
        isLoadingMore = false;
        LoadingMore?.Invoke(this, new LoadingMoreEventArgs(false));
    }

    // whether or not we are loading items
    public bool IsLoadingMore => isLoadingMore;

    // the event that informs the list that we are fetching more items
    public event EventHandler<LoadingMoreEventArgs> LoadingMore;

    // whether or not we have run out of items
    public bool ShouldLoadMore(object currentItem)
    {
        // there are no items in the list
        if (Count == 0)
            return true;

        // the current item is the last item in the list
        return this[Count - 1] == currentItem;
    }
}

More Repositories

1

SkiaSharpFiddle

A SkiaSharp Playground
C#
137
star
2

square-bindings

Xamarin.Android and Xamarin.iOS binding for https://github.com/square
C#
70
star
3

CreatingPlatformPlugins

A set of examples and documentation to aid in the development of cross-platform libraries and plugins.
C#
49
star
4

SkiaSharpBlazorWebAssembly

C#
31
star
5

Mono.Data.Sqlite.Orm

A small and light SQLite ORM for use in any .NET project
C#
31
star
6

FlappyBird

The "official" FlappyBird clone - made with SkiaSharp
C#
30
star
7

Microsoft-Band-SDK-Bindings

The Xamarin bindings for the Microsoft Band SDK
C#
30
star
8

SkiaSharpGraphics

Declarative SkiaSharp drawings - eg SVG or XAML
C#
28
star
9

SkiaSharpDemo

A set of simple demonstration apps, each of which show how to do a few tasks using SkiaSharp.
C#
25
star
10

Mono.Data.Sqlite

Mono.Data.Sqlite for restricted systems such as Silverlight/Windows Phone/WinRT
C#
24
star
11

Android.Play.ExpansionLibrary

MOVED to xamarin/XamarinComponents
C#
21
star
12

MultiSelectListView

An example app to show one way in which to create a multi-select ListView in Xamarin.Forms.
C#
21
star
13

catj

Displays JSON files in a flat format.
C#
20
star
14

SkiaSharpAnimatedBackgrounds

Cool animated backgrounds for Xamarin.Forms with SkiaSharp.
C#
20
star
15

Socket.IO.Client

Xamarin bindings for the Socket.IO Clients
PowerShell
19
star
16

Flurry.Analytics

The Flurry Analytics Agent allows you to track the usage and behavior of your Android, iOS or Windows Phone application on users' phones for viewing in the Flurry Analytics system.
C#
19
star
17

CommandLineApp

Your first app made with System.CommandLine
C#
15
star
18

Xamarin.Android.Bindings.Generators

A MSBuild Task to make Xamarin.Android binding projects easier
C#
13
star
19

SkiaSharpUnoBlazorApp

A possible scenario with a SkiaSharp drawing (powered by Uno Platform) in a Blazor app
C#
12
star
20

Genetics

Attribute based view, resource and event injection for Xamarin.Android
C#
11
star
21

SkiaSharpUnityDemo

A simple demonstration app to show an example of a SkiaSharp being used with Unity.
C#
10
star
22

StickyHeader

A very simple library that allows you to stick any View as a header of a ListView, RecyclerView or ScrollView.
C#
9
star
23

skiasharp-samples

The samples for the SkiaSharp repository.
C#
9
star
24

Mono.ApiTools.NuGetDiff

A library to help with .NET API development and and NuGet diff-ing.
C#
8
star
25

RangedObservableCollection

A small extension to ObservableCollection that allows for multiple items to be added, removed or replaced in a single operation.
C#
8
star
26

SkiaSharp-Docker

A sample that shows a minimal SkiaSharp container.
C#
8
star
27

BlazorWebAssemblyDemos

HTML
8
star
28

Microsoft.Devices.Radio.FMRadio

C#
8
star
29

BlazorSkiaSharp

HTML
7
star
30

SkiaSharpImageMerger

C#
7
star
31

SkiaSharpLottieSample

Just a quick .NET MAUI sample showing some initial Lottie playback.
C#
7
star
32

Microsoft-OneDrive-SDK-Bindings

A Xamarin.Android binding for the OneDrive Picker for Android
C#
6
star
33

System.Drawing.Wrappers

C#
6
star
34

vkontakte-bindings

DEPRECTAED - moved to official Xamarin Components repo
C#
6
star
35

SkiaSharpFormsRendererDemo

A simple demonstration app to show an example of a SkiaSharp custom renderer.
C#
6
star
36

Xunit.Runner.Devices

A device runner for the xUnit.net unit testing framework.
C#
6
star
37

SkiaSharpMultiThreadedLists

A small example of how SkiaSharp can be used with multiple threads to draw items in a list.
C#
6
star
38

Xamarin.SimplePing

[MOVED]
C#
5
star
39

FunnyLoader

Loading indicator for Xamarin.Forms with over 200 random messages .
C#
5
star
40

NativeAndroidWithMaui

C#
5
star
41

Saltarelle.PathJs

A Saltarelle wrapper fo PathJS
C#
5
star
42

nano-api-scan

A .NET Core tool to detect any Win32 APIs that are not available on Windows Nano Server.
C#
5
star
43

EmbeddedFormsDemo

A simple demonstration app to show how to embed Xamarin.Forms pages into a native app.
C#
5
star
44

BlazorAllTheThings

Razor on the web, mobile and desktop! Blazor!
HTML
5
star
45

SkiaSharpBlazorComponents

Learning how to do Blazor for SkiaSharp on the job...
HTML
5
star
46

ComicVineApi

A beautiful .NET API that wraps the awesome Comic Vine rest API.
C#
5
star
47

TizenInstallersPlayground

PowerShell
4
star
48

SkiaSharpZoomTest

C#
4
star
49

MauiWinUIRatingControlDemo

Demo for showing the usage of a WinUI RatingControl in a MAUI app.
C#
4
star
50

AppShowcase

Xamarin.Android version of https://github.com/deano2390/MaterialShowcaseView and https://github.com/amlcurran/ShowcaseView
C#
4
star
51

lolcode-dot-net

Automatically exported from code.google.com/p/lolcode-dot-net
C#
4
star
52

XamarinFormsGitterApp

Fun with Xamarin.Forms and Gitter.im
C#
4
star
53

CustomMauiThings

C#
4
star
54

TwitterCover

TwitterCover is a parallax top view with real time blur effect to any scrollable view. Supports Xamarin.iOS and Xamarin.Android
C#
4
star
55

dotnetconf2022

.NET Conf 2022 - South Africa edition
C#
4
star
56

SkiaSharpSignatures

A small sample showing how to capture signatures using SkiaSharp.
C#
4
star
57

SkiaSharpFunctions

C#
4
star
58

SkiaSharpAndroidDemo

A simple SkiaSharp demonstration app using Xamarin.Android
C#
4
star
59

TicTacToe-Workshops

A short workshop that helps you get started creating your first real Xamarin app using Xamarin.Forms.
C#
4
star
60

ANGLE-Minimal

C#
3
star
61

MauiLibraryPacks

C#
3
star
62

Android.Extensions

C#
3
star
63

MauiMultiHeadProject

C#
3
star
64

PivotViewPlayground

C#
3
star
65

CrossPlatformBuild

A template repository for building cross-platform Xamarin apps on free hosted CI
C#
3
star
66

BingMaps

A Xamarin.iOS binding for Bing Maps Control for iOS
C#
3
star
67

Win2DSourceThing

C#
3
star
68

BugReporterApp

C#
2
star
69

SkiaSharpGtkSharp

A basic app that gets SkiaSharp to work with GTK#
C#
2
star
70

ANGLE-Example

C#
2
star
71

SkiaSharpExtensionsPlayground

C#
2
star
72

SkiaSharpTextures

C#
2
star
73

ProjectsWithDepsThatDoNotBuild

C#
2
star
74

AndroidAsync-binding

Xamarin.Android binding for AndroidAsync (https://github.com/koush/AndroidAsync)
C#
2
star
75

SkiaSharpPreviewerDemo

C#
2
star
76

XamarinGitHubActions

Xamarin + GitHub Actions
C#
2
star
77

MultiTargetingApp

C#
2
star
78

ResponsiveFormsDesign

C#
2
star
79

dotnet-devices

dotnet devices apple list --booted && dotnet devices /path/to/test.app
C#
2
star
80

shopify-bindings

Xamarin bindings for Shopify
C#
2
star
81

DotNetConf2018

2
star
82

MultiTargetWinUI

A semi-demo-proof-of-concept-thing showing WinUI as a multi-targeted project.
C#
2
star
83

SkiaSharpImageCropper

C#
2
star
84

RichTextBoxEx

C#
2
star
85

MauiUnpackaged

The repo to show off unpackaged .NET MAUI apps for Windows
C#
2
star
86

Spaceship

Spaceship with gravity in C# using SkiaSharp.
2
star
87

OpenGlobe

C#
2
star
88

Mono.ApiTools.MSBuildTasks

MSBuild tasks to help with adjusting .NET assemblies during a build.
C#
2
star
89

ICanHazDadJoke.NET

A .NET Client for icanhazdadjoke.com
C#
2
star
90

GitHubWikiEditor

HTML
2
star
91

NewInCSharp8AndNETCore3

Just some slides and code showing off what is new in C# 8 and .NET Core 3
C#
2
star
92

AsyncDataLoader

C#
2
star
93

WinUIMultiThreadResources

C#
2
star
94

XamarinLife

Conway's Game of Life made with Xamarin
C#
2
star
95

PivotViewer

C#
2
star
96

beginners-bible

The Beginner's Bible
C#
2
star
97

XamarinFormsTabsDemo

A simple demonstration app to show how one can improve the Xamarin.Forms TabbedPage
C#
2
star
98

SkiaSharpNetCoreGtkSharp

C#
1
star
99

SkiaSharpWebApi-Docker

A sample that shows a minimal WebAPI with SkiaSharp in a container.
C#
1
star
100

GoogleCardboard

C#
1
star