ListView com Infinite Scroll – Xamarin.Forms

Neste artigo irei demonstrar como você pode implementar uma lista com Infinite Scroll, dessa forma a sua lista será carregada “em partes”, com paginação e a quantidade de itens que você deseja por página. Esse tipo de carregamento é muito utilizado quando é necessário carregar uma lista com muitos elementos, evitando que o usuário espere toda a lista carregar para que possa selecionar o elemento desejado.

 

ADICIONANDO O NUGET PACKAGE

Clique com o botão direito em cima de sua Solution e selecione “Manage NuGet Packages for Solution…”.

1

 

No momento em que escrevo este artigo, o plugin utilizado encontra-se em prerelease, então para que possa encontra-lo, selecione a opção “Include prerelease”.

Digite “Xamarin.Forms.Extended.InfiniteScrolling” e selecione o plugin como demonstrado na imagem a seguir.

2

 

Selecione todos os projetos e clique no botão “Install”.

2

Service.cs

Está classe será necessária para simular uma requisição, observe que no método GetPessoasAsync está sendo utilizado um Delay de 3000 milissegundos.

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace InfiniteScrollDemo
{
public class Service
{
private readonly List<string> _pessoas = new List<string>
{
"Adriano", "José", "Maria","Oscar", "João", "Eduarda", "Daniel",
"Suzana", "Paulo", "Pedro","Davi", "Felipe", "Fernanda", "Regina", "Nicole",
"Jesus", "Samira", "Samuel", "Elis", "Mayara", "Leticia", "Luiz", "Luciano",
"Neto", "Rodrigo", "Silvia", "Joel", "Vitória", "Fernando", "Samanta", "Karen",
"Marcio", "Cleusa", "Clara", "Luciana", "Cleber", "Jairo", "Jair", "Douglas", "Hamilton",
};
public async Task<List<string>> GetPessoasAsync(int pageIndex, int pageSize)
{
//Delay para simular o tempo de uma requisição
await Task.Delay(3000);
return _pessoas.Skip(pageIndex * pageSize).Take(pageSize).ToList();
}
}
}

view raw
Service.cs
hosted with ❤ by GitHub

MainViewModel.cs

Crie a classe MainViewModel, elá irá herdar de INotifyPropertyChanged e terá as seguintes propriedades:

  • PageSize – Tamanho da página
  • _isBusy – Indica quando começa(true) e quando termina(false) a requisição.
  • Service – Objeto do tipo da classe Service criada anteriormente.
  • Items – A lista com os elementos que serão apresentados.
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Xamarin.Forms.Extended;
namespace InfiniteScrollDemo
{
public class MainViewModel : INotifyPropertyChanged
{
private const int PageSize = 8;
private bool _isBusy;
readonly Service _service = new Service();
public InfiniteScrollCollection<string> Items { get; }
}
}

view raw
MainViewModel.cs
hosted with ❤ by GitHub

 

Download

Crie o método Download que será responsável em pegar a primeira página da lista.

private async Task Download()
{
var items = await _service.GetPessoasAsync(pageIndex: 0, pageSize: PageSize);
Items.AddRange(items);
}

view raw
MainViewModel.cs
hosted with ❤ by GitHub

 

OnPropertyChanged

Crie o método OnPropertyChanged que será responsável  por notificar a cada modificação de propriedade.

public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

view raw
MainViewModel.cs
hosted with ❤ by GitHub

 

Construtor

No construtor da classe instancie a lista, observe que OnLoadMore também busca os itens e adiciona na lista,  pois ele será chamado a cada página carregada. No construtor adicione uma chamada para o método Download, ele será chamado para carregar apenas a primeira página.

public MainViewModel()
{
Items = new InfiniteScrollCollection<string>
{
OnLoadMore = async () =>
{
IsBusy = true;
// Ler a proxima pagina
var page = Items.Count / PageSize;
//Busca os itens
var items = await _service.GetPessoasAsync(page, PageSize);
IsBusy = false;
// Itens que serão adicionados
return items;
}
};
Download();
}
public bool IsBusy
{
get => _isBusy;
set
{
_isBusy = value;
OnPropertyChanged();
}
}

view raw
MainViewModel.cs
hosted with ❤ by GitHub

MainPage.xaml

Comece setando a MainViewModel no BindingContext, depois crie uma lista como você já deve estar acostumado.

Referencie o plugin Xamarin.Forms.Extended e sete o InfiniteScrollBehavior no ListView.Behaviors.

No footer da lista, adicione um ActivityIndicator que será apresentado enquanto a próxima página é carregada.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:InfiniteScrollDemo"
xmlns:extended="clr-namespace:Xamarin.Forms.Extended;assembly=Xamarin.Forms.Extended.InfiniteScrolling"
x:Class="InfiniteScrollDemo.MainPage">
<ContentPage.BindingContext>
<local:MainViewModel />
</ContentPage.BindingContext>
<StackLayout>
<Label Text="Infinite Scroll" FontSize="40" HorizontalTextAlignment="Center"
TextColor="Black" Margin="0,30" />
<ListView ItemsSource="{Binding Items}"
CachingStrategy="RecycleElement"
HasUnevenRows="True">
<ListView.Behaviors>
<extended:InfiniteScrollBehavior IsLoadingMore="{Binding IsBusy}" />
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="12">
<Label Text="{Binding .}" FontSize="30" TextColor="Black" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Footer>
<Grid Padding="6" IsVisible="{Binding IsBusy}">
<Grid.Triggers>
<Trigger TargetType="Grid" Property="IsVisible" Value="False">
<Setter Property="HeightRequest" Value="0" />
</Trigger>
</Grid.Triggers>
<ActivityIndicator IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}"
Color="#2196F3" VerticalOptions="Center"
HorizontalOptions="Center"/>
</Grid>
</ListView.Footer>
</ListView>
</StackLayout>
</ContentPage>

view raw
MainPage.xaml
hosted with ❤ by GitHub

Resultado

ezgif.com-gif-maker

ezgif.com-video-to-gif.gif

 

Esse e todos os exemplos deste blog encontram-se disponíveis no GitHub.

icongithub

7 comentários em “ListView com Infinite Scroll – Xamarin.Forms

  1. Muito bom Juliano ! Agora você poderia nos ensinar a fazer utilizando GroupCollection, tenho uma lista enorme dentro de outra lista, e estou apanhando para fazer… 😦

    Curtir

  2. Fala juliano beleza… Então tenho uma lista dentro de outra lista, aí pelo que pesquisei deve-se montar um group collection, tentei mas não consegui carregar por demanda de forma correta, podia criar um artigo assim ?

    Curtir

    1. Olá…

      Você pode substituir o uso da TableView e utilizar uma ListView, acredito que terá mais controle e muito mais opções de layout.

      Espero ter ajudado.

      Curtir

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s