Aplicativos iOS possuem um comportamento específico de clicar na barra de status para retornar ao topo de uma listagem ou página, o scrollsToTop. Este comportamento é bastante utilizado pelos usuários e é importante manter este comportamento quando formos desenvolver nossos apps.

git app ios com scrollsToTop funcionando

O menu hambúrguer/master-detail é um componente nativo no sistema operacional Android e utiliza-lo normalmente não causa nenhum problema para o aplicativo.

Já no sistema operacional iOS, este tipo de menu não é implementando pelo sistema operacional, e utliza-lo pode ocasionar alguns efeitos colaterais, principalmente quando o aplicativo possui páginas que herdam de UIScrollView (normalmente listas, como no exemplo acima, e páginas com barra de rolagem).

Quando isto acontece, normalmente o aplicativo “perde” a funcionalidade de clicar na status bar para retornar ao topo.

git app ios com scrollstotop quebrado

Isto ocorre porque este gesto do iOS é capaz de observar apenas um objeto que herda de UIScrollView, o primeiro a ser montado na tela.

O problema neste caso é que, normalmente, quando estamos montando a página de menu (a master), implementamos um ScrollView, para nos certificarmos de que todo o menu será visualizado, independente do tamanho da tela do usuário. Fazendo isto, utilizamos o objeto ScrollView, que no caso do framework Xamarin.Forms herda de UIScrollView. Logo, teremos dois objetos que herdam de UIScrollView na tela: O menu (na master) e a lista de itens (na detail). Quando o aplicativo é carregado, o iOS irá escutar o evento de clique na barra de status para retornar ao topo na UIScrollView do menu (master) e não na página de detalhes que possui o lista de itens (detail).

Para escutar este evento o iOS utliza a propriedade scrollsToTop da UIScrollView. Esta é uma propriedade booleana que se setada verdadeiro, indica que o sistema operacional deve observar o evento de clique na status bar para voltar ao topo nesta página. Infelizmente o objeto ScrollView do Xamarin.Forms não possui uma Bindable Porperty para setar esta propriedade.

Para resolver o problema, você precisará criar um tipo customizado que herde de UIScrollView e aponte falso para a propriedade scrollsToTop para que o sistema operacional não escute o evento de clicar na status bar para retornar ao topo na página que implementar este objeto.

O exemplo da correção/customização mostrado abaixo no post está implementado em C# no framework Xamarin.Forms e possui uma página master (o menu) e uma página detail (com a listagem que está sendo escrolada) mas a ideia serve para qualquer linguagem de programação, dado que customiza um objeto nativo. Basta implementar na sintaxe que você estiver trabalhando.

Agora vamos criar um custom renderer que herde que ScrollViewRenderer, que é classe do Xamarin.iOS que implementa a UIScrollView e customiza-la.

[assembly: ExportRenderer(typeof(CustomScrollView), typeof(CustomScrollViewRenderer))]
namespace ScrollsToTop.CustomRenderers.iOS.CustomRenderers
{
    public class CustomScrollViewRenderer : ScrollViewRenderer
    {
        public CustomScrollViewRenderer() => ScrollsToTop = false;
    }
}

Depois de criar a CustomScrollView, troque a implementação da página de menu (master) para que implemente este objeto:

<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage x:Class="MenuHamburger.Views.MenuPage"
             xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:controles="clr-namespace:MenuHamburger.Controles"
             BackgroundColor="White">
    <StackLayout CompressedLayout.IsHeadless="true" Spacing="0">
        <Frame Padding="10"
               HeightRequest="120"
               BackgroundColor="Red"
               CornerRadius="0"
               HasShadow="false">
            <Label Text="Nome do Usuário" 
                   Margin="10"/>
        </Frame>
        <controles:CustomScrollView>
            <StackLayout CompressedLayout.IsHeadless="true" Spacing="10">
                <Label Text="Menu 1"
                       Command="{Binding NavegarCommand}" />
                <Label Text="Menu 2"
                       Command="{Binding NavegarCommand}" />
                <Label Text="Menu 3"
                       Command="{Binding NavegarCommand}" />     
            </StackLayout>
        </controles:CustomScrollView>
    </StackLayout>
</ContentPage>

Pronto! Desta forma o iOS não irá escutar mais o evento da página do menu (master) e sim a página de detalhes (detail). Assim quando você clicar na status bar a lista retornará para o topo.

git app ios com scrollstotop consertado

Deu certo? Comenta aqui o resultado!

Até o próximo post!

#Ubuntu

Você pode conferir o código completo deste post no meu GitHub!

Modificado pela ultima vez: 13 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.