Você provavelmente já acessou algum site que enquanto carregava ficou assim:
Este tipo de loading é chamado de Skeleton Screen.
Skeleton Screen é mais amigável de serem exibido enquanto carregamos os dados da tela do que o tradicional spinner, ou não carregarmos nada e mostrarmos a tela em branco. Além de que os usuários já estão mais acostumados a vê-los enquanto os dados são carregados.
O termo Skeleton Screen foi citado a primeira vez neste post pelo Luke Worblewski. No post ele discute sobre loadings e aconselha designers a evitarem o uso de spinners (Activity indicator). Se você quiser ler um pouco mais sobre Sekeleton Screen, este post do Bill Chung é excelente.
O Skeleton Screen se tornou muito popular ao ser adotado pelo Facebook e passou a também ser conhecido como Shimmer. Você pode ver o repositório do Shimmer do Facebook clicando aqui. O Skeleton Screen também tem sido bastante utilizado por outros portais como Youtube, Linkedin, Submarino.
Sem mais delongas, vamos ver como implementar o Skeleton Screen com Xamarin.Forms!
StateSquid
Para implementar o Skeleton Screen no nosso projeto Xamarin Forms, vamos utilizar o pacote Xamarin.Forms.StateSquid desenvolvido pelo Steve Thewissen. Ele é open source, está no Github e disponível para ser instalado via NuGet .
Após criado o projeto Xamarin.Forms (se você é novo com Xamarin, veja mais aqui) Vamos instalar o StateSquid apenas no projeto compartilhado do Xamarin.Forms, ele não precisa ser instalado nos projetos das plataformas específicas.
Para o exemplo que vamos ver no post ser mais didático, vamos trabalhar com o padrão MVVM, se você não conhece MVVM, veja este material. Com isto, vou usar o pacote Refactored.MvvMHelpers do James Montemagno para facilitar o trabalho com Bindings.
O StateSquid possui um objeto chamado SkeletonView. É com ele que iremos representar o loading. A personalização dele para representar bem o está sendo carregando ficará a nosso cargo, definido o tamanho do objeto, largura, cor e se possui bordas arredondadas (você pode controlar o arredondamento da borda para representar círculos).
Para controlar o estado do SkeletenView vamos utilizar dois outros objetos do StateSquid: O StateLayout e o StateView.
O StateView é quem controlará o estado do SkeletonView. Ele faz isso através da propriedade StateKey que possui as seguintes opções:
- Loading
- Saving
- Success
- Error
- Empty
- Custom
- None
Para que o SkeletonView apareça na tela como carregando, vamos utilizar o estado Loading, e para desativa-lo, vamos utilizar o estado None.
O StateLayout é um agrupador de StateViews, ou seja, dentro dele você poderá ter vários StateViews que atendam a estados diferentes.
Legal! Agora vamos juntar o SkeletonView e o que queremos representar com ele enquanto o dado é carregado, para isto vamos utilizar um StackLayout.
O StackLayout irá conter o StateLayout, o StateView, o SkeletonView e um Label, que no nosso exemplo será o objeto que queremos mostrar somente após o carregamento. Para o StackLayout atualizar o StateLayout que está dentro dele, vamos adicionar a propriedade StateLayout.CurrentState do StateSquid com o valor SkeletonState. Ela será atualizada via binding pela nossa MainPageViewModel que iremos criar mais a frente.
Por fim, vamos adicionar um botão que irá atualizar a SkeletonState através do command SkeletonCommand.
Veja abaixo como ficou a MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage x:Class="SkeletonScreen.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
xmlns:state="clr-namespace:Xamarin.Forms.StateSquid;assembly=Xamarin.Forms.StateSquid"
ios:Page.UseSafeArea="true">
<StackLayout>
<StackLayout state:StateLayout.CurrentState="{Binding SkeletonState}">
<state:StateLayout.StateViews>
<state:StateView StateKey="Loading">
<state:SkeletonView BackgroundColor="#cccccc"
CornerRadius="6"
HeightRequest="20"
HorizontalOptions="Start"
WidthRequest="100" />
</state:StateView>
</state:StateLayout.StateViews>
<Label Text="Carregamento concluído!" />
</StackLayout>
<Button
BackgroundColor="Navy"
Command="{Binding SkeletonCommand}"
HeightRequest="40"
Text="Ativar Skeleton"
TextColor="White" />
</StackLayout>
</ContentPage>
Agora que já temos a MainPage criada com o SkeletonView, vamos criar a MainPageViewModel com as propriedade SkeletonState do tipo State e o command SkeletonCommand, que irão controlar a visibilidade do SkeletonView.
O SkeletonCommand irá atualizar o estado da SkeletonState para Loading, fazendo com que o SkeletonView seja exibido, aguardar 3 segundos para simular um carregamento e depois atualizar novamente o estado da SkeletonState para None, fazendo com que o SkeletonView seja ocultado e exibida o Label.
Veja abaixo a MainPageViewModel:
public class MainPageViewModel : BaseViewModel
{
public State SkeletonState { get; set; }
public ICommand SkeletonCommand { get; set; }
public MainPageViewModel()
{
SkeletonCommand = new Command(async (x) =>
{
SkeletonState = State.Loading;
await Task.Delay(3000);
SkeletonState = State.None;
});
}
}
Feito tudo isto, rode o app, clique no botão Ativar Skeleton e veja se funcionou!
Conclusão
Você pode trabalhar esta atualização de estado de várias maneiras, por exemplo quando receber o retorno da API ou quando terminar algum processamento. Trabalhe a mudança de estado do jeito que melhor atenda a sua regra de negócio.
—
Você pode conferir o código completo post no meu GitHub
#Ubuntu
Comentários