Você provavelmente já acessou algum site que enquanto carregava ficou assim:

exemplo de skeleton

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.

gerenciado de pacotes nuget

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

Modificado pela ultima vez: 26 de maio de 2020

Comentários

Escreva uma resposta ou comentário

Seu endereço de e-mail não será publicado.

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.