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…”.
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.
Selecione todos os projetos e clique no botão “Install”.
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; } | |
} | |
} |
Download
Crie o método Download que será responsável em pegar a primeira página da lista.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private async Task Download() | |
{ | |
var items = await _service.GetPessoasAsync(pageIndex: 0, pageSize: PageSize); | |
Items.AddRange(items); | |
} |
OnPropertyChanged
Crie o método OnPropertyChanged que será responsável por notificar a cada modificação de propriedade.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public event PropertyChangedEventHandler PropertyChanged; | |
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) | |
{ | |
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); | |
} |
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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> |
Resultado
Esse e todos os exemplos deste blog encontram-se disponíveis no GitHub.
Muito bom!
CurtirCurtir
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… 😦
CurtirCurtir
Olá Michel,
Acho que este post pode te ajudar: http://julianocustodio.com/GroupedListView
Abraço.
CurtirCurtir
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 ?
CurtirCurtir
Olá Michel,
Acho que este post pode te ajudar: http://julianocustodio.com/GroupedListView
Abraço
CurtirCurtir
muito bom esse artigo, …. simples. uma duvida, como controlar qdo subir/voltar na lista ? tenho 10.000 itens.
CurtirCurtir
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.
CurtirCurtir