Home / Aplicativo móvel / Introdução ao componente BottomSheet para .NET MAUI

Introdução ao componente BottomSheet para .NET MAUI

Introdução ao componente BottomSheet para .NET MAUI

Se o seu aplicativo móvel precisar que uma seção deslizante apareça na parte inferior da tela, verifique o componente .NET MAUI BottomSheet.

Em alguns aplicativos móveis modernos, podemos ver um componente chamado Bottom Sheet em ação, que permite ao usuário deslizar uma seção da parte inferior do aplicativo para exibir ações ou informações sem alterar a tela.

Esse tipo de componente não existe como parte dos controles MAUI nativos do .NET. Felizmente, o conjunto de controles Progress Telerik para .NET MAUI oferece o Folha inferior do .NET MAUI componente, que analisaremos durante este post. Vamos começar!

Descobrindo o componente Telerik .NET MAUI BottomSheet para .NET MAUI

Exploraremos diferentes recursos do componente Bottom Sheet, para o qual mostrarei uma janela criada com código XAML que pode muito bem representar uma seção de um aplicativo real. A seguir, mostrarei como implementar o controle Bottom Sheet para exibir opções de seleção aos usuários na mesma janela.

Criando um projeto de exemplo

Suponha que temos um projeto que permite aos usuários pedir comida em restaurantes por meio de um aplicativo. Para a criação da página XAML, usei diferentes controles do conjunto Telerik UI for .NET MAUI, que permitem a criação rápida de interfaces gráficas personalizadas:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height=".2*" />
        <RowDefinition Height=".8*" />
    Grid.RowDefinitions>

    
    <VerticalStackLayout Padding="25,25,25,0" Spacing="10">
        <Label
            FontAttributes="Bold"
            FontSize="12"
            Text="DELIVERY ADDRESS"
            TextColor="White" />

        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
            Grid.ColumnDefinitions>
            <Grid.GestureRecognizers>
                <TapGestureRecognizer Tapped="OnAddressTapped" />
            Grid.GestureRecognizers>

            <Label
                x:Name="CurrentAddressLabel"
                FontSize="16"
                Text="123 Main Street, City"
                TextColor="White"
                VerticalOptions="Center" />

            <Label
                Grid.Column="1"
                Margin="10,0,0,0"
                FontSize="14"
                Text=""
                TextColor="White"
                VerticalOptions="Center" />
        Grid>

        
        <telerik:RadBorder
            Padding="10"
            BackgroundColor="#6B5BAF"
            CornerRadius="10">
            <Grid ColumnDefinitions="Auto,*">
                <Label
                    Margin="0,0,10,0"
                    FontSize="16"
                    Text="🔍"
                    VerticalOptions="Center" />
                <telerik:RadEntry
                    x:Name="StoreSearchEntry"
                    Grid.Column="1"
                    BackgroundColor="Transparent"
                    BorderThickness="0"
                    ClearButtonVisibility="WhileEditing"
                    Placeholder="Search a restaurant or dish"
                    PlaceholderColor="#B8B0D0"
                    TextColor="White" />
            Grid>
        telerik:RadBorder>
    VerticalStackLayout>

    
    <telerik:RadBorder
        Grid.Row="1"
        Margin="0,10,0,0"
        BackgroundColor="#F2F1F6"
        CornerRadius="25,25,0,0">
        <telerik:RadCollectionView
            x:Name="StoresCollection"
            Margin="15"
            SelectionChanged="OnStoreSelected"
            SelectionMode="Single">
            <telerik:RadCollectionView.ItemsLayout>
                <telerik:CollectionViewLinearLayout ItemSpacing="15" />
            telerik:RadCollectionView.ItemsLayout>
            <telerik:RadCollectionView.ItemTemplate>
                <DataTemplate>
                    <Border
                        Padding="0"
                        BackgroundColor="White"
                        StrokeShape="RoundRectangle 15"
                        StrokeThickness="0">
                        <Border.Shadow>
                            <Shadow
                                Brush="#CFD0D4"
                                Opacity="0.5"
                                Radius="10"
                                Offset="5,5" />
                        Border.Shadow>
                        <Grid Padding="0" RowDefinitions="150,Auto">
                            
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height=".6*" />
                                    <RowDefinition Height=".4*" />
                                Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width=".4*" />
                                    <ColumnDefinition Width=".2*" />
                                    <ColumnDefinition Width=".4*" />
                                Grid.ColumnDefinitions>

                                
                                <Image
                                    Grid.RowSpan="2"
                                    Grid.ColumnSpan="3"
                                    Aspect="AspectFill"
                                    Source="{Binding Header}" />

                                
                                <Grid
                                    Grid.Row="1"
                                    Grid.Column="0"
                                    Margin="10,0,0,0"
                                    HeightRequest="70"
                                    HorizontalOptions="Start"
                                    VerticalOptions="End"
                                    WidthRequest="70">
                                    <Border
                                        HeightRequest="65"
                                        HorizontalOptions="Center"
                                        StrokeShape="Ellipse"
                                        StrokeThickness="3"
                                        WidthRequest="65">
                                        <Border.Stroke>
                                            <LinearGradientBrush EndPoint="0,1">
                                                <GradientStop Offset="0.0" Color="#FEFEEF" />
                                                <GradientStop Offset="0.25" Color="#EBD570" />
                                                <GradientStop Offset="0.5" Color="#FF94C3" />
                                                <GradientStop Offset="0.75" Color="#A573E4" />
                                                <GradientStop Offset="1.0" Color="#A9E2EE" />
                                            LinearGradientBrush>
                                        Border.Stroke>
                                        <Image
                                            Aspect="AspectFill"
                                            HorizontalOptions="Center"
                                            Source="{Binding Logo}" />
                                    Border>
                                Grid>

                                
                                <Border
                                    Grid.Row="1"
                                    Grid.Column="2"
                                    Margin="0,0,10,10"
                                    Padding="10,5"
                                    BackgroundColor="#F8F8F7"
                                    HeightRequest="35"
                                    HorizontalOptions="Center"
                                    StrokeShape="RoundRectangle 10"
                                    StrokeThickness="0"
                                    VerticalOptions="End"
                                    WidthRequest="70">
                                    <HorizontalStackLayout
                                        HorizontalOptions="Center"
                                        Spacing="8"
                                        VerticalOptions="Center">
                                        <Label
                                            FontSize="14"
                                            Text=""
                                            VerticalOptions="Center" />
                                        <Label
                                            FontAttributes="Bold"
                                            FontSize="14"
                                            Text="{Binding Rating}"
                                            TextColor="Black"
                                            VerticalOptions="Center" />
                                    HorizontalStackLayout>
                                Border>
                            Grid>

                            
                            <VerticalStackLayout
                                Grid.Row="1"
                                Padding="15"
                                Spacing="8">
                                <Label
                                    FontAttributes="Bold"
                                    FontSize="18"
                                    Text="{Binding Name}"
                                    TextColor="Black" />

                                <Grid ColumnDefinitions="*,*,*">
                                    <Label
                                        FontSize="13"
                                        Text="{Binding Minimum, StringFormat='${0} min'}"
                                        TextColor="#666666" />
                                    <Label
                                        Grid.Column="1"
                                        FontSize="13"
                                        HorizontalOptions="Center"
                                        Text="{Binding ServiceFee, StringFormat='Fee: ${0}'}"
                                        TextColor="#666666" />
                                    <Label
                                        Grid.Column="2"
                                        FontSize="13"
                                        HorizontalOptions="End"
                                        Text="{Binding DeliveryTime}"
                                        TextColor="#666666" />
                                Grid>
                            VerticalStackLayout>
                        Grid>
                    Border>
                DataTemplate>
            telerik:RadCollectionView.ItemTemplate>
        telerik:RadCollectionView>
    telerik:RadBorder>
Grid>

O resultado é uma bela interface gráfica que mostra alguns restaurantes fictícios, junto com controles adicionais como uma barra de pesquisa e um seletor de endereço físico:

Captura de tela de uma página de lojas de pedidos de alimentos criada usando componentes de UI da Telerik para .NET MAUI

Na captura de tela acima, você pode ver alguns componentes do Telerik usados, como os seguintes:

  • RadEntry: Para a barra de pesquisa da loja
  • RadBorder: para melhorar a aparência da barra de pesquisa e dos itens da lista
  • RadCollection: Para exibir a lista de lojas

Na parte superior do aplicativo, coloquei um endereço fictício abaixo do texto Endereço de entrega. Idealmente, os usuários deveriam poder selecionar um endereço de entrega diferente, se necessário, sem sair da tela atual. Este é um excelente caso de uso para uma Folha Inferior.

Conhecendo o componente Telerik BottomSheet

Para implementar o componente Bottom Sheet, é essencial entender que ele consiste em três partes que podemos configurar:

  • Conteúdo principal da folha inferior: Container para o conteúdo gráfico que ficará visível antes da exibição da Folha Inferior.
  • Conteúdo da folha inferior: Conteúdo que preenche a Folha Inferior e que mostraremos como opções ou informações adicionais ao usuário.
  • Alça da Folha Inferior: uma dica visual que indica ao usuário que ele pode arrastar a planilha inferior.

Você pode ver a localização de cada uma dessas partes graficamente abaixo:

Estrutura visual de um controle Telerik BottomSheet para .NET MAUI

Agora que temos essas informações, vamos adicionar uma Folha Inferior ao projeto.

Adicionando o componente BottomSheet a um projeto .NET MAUI

Quando estivermos familiarizados com as partes principais do controle Folha Inferior, a próxima etapa é migrar o conteúdo da UI existente para o controle Folha Inferior. Conteúdo principal da folha inferior seção, usando o Content propriedade da seguinte forma:

<telerik:RadBottomSheet x:Name="AddressBottomSheet">
    <telerik:RadBottomSheet.Content>
        <Grid>
            ...
        Grid>
     telerik:RadBottomSheet.Content>
telerik:RadBottomSheet>


O acima determinará o conteúdo sobre o qual a Folha Inferior aparecerá. A seguir, precisamos especificar o BottomSheetContent tag, onde definiremos o conteúdo que será mostrado ao usuário quando a Folha Inferior aparecer:

    <telerik:RadBottomSheet x:Name="AddressBottomSheet">
        ...
        <telerik:RadBottomSheet.BottomSheetContent>
            <Grid
                Padding="20,20,20,60"
                RowDefinitions="Auto,Auto,*,Auto"
                RowSpacing="15">

                
                <Grid ColumnDefinitions="*,Auto">
                    <VerticalStackLayout>
                        <Label
                            FontAttributes="Bold"
                            FontSize="22"
                            Text="📍 Delivery Address"
                            TextColor="#333333" />
                        <Label
                            Margin="0,5,0,0"
                            FontSize="13"
                            Text="Select or add a new delivery address"
                            TextColor="#888888" />
                    VerticalStackLayout>
                    <telerik:RadTemplatedButton
                        Grid.Column="1"
                        BackgroundColor="Transparent"
                        Clicked="OnCloseBottomSheet"
                        Content=""
                        CornerRadius="20"
                        FontSize="20"
                        HeightRequest="40"
                        TextColor="#666666"
                        WidthRequest="40" />
                Grid>

                
                <telerik:RadBorder
                    Grid.Row="1"
                    Padding="12"
                    BackgroundColor="#EAEAEA"
                    CornerRadius="12">
                    <Grid ColumnDefinitions="Auto,*">
                        <Label
                            Margin="0,0,10,0"
                            FontSize="16"
                            Text="🔍"
                            VerticalOptions="Center" />
                        <telerik:RadEntry
                            x:Name="AddressSearchEntry"
                            Grid.Column="1"
                            BackgroundColor="Transparent"
                            Placeholder="Search your addresses..."
                            PlaceholderColor="#999999"
                            BorderThickness="0"
                            ClearButtonVisibility="WhileEditing"
                            TextChanged="OnAddressSearchTextChanged" />
                    Grid>
                telerik:RadBorder>

                
                <telerik:RadCollectionView
                    x:Name="AddressesCollectionView"
                    Grid.Row="2"
                    SelectionChanged="OnAddressSelectionChanged"
                    SelectionMode="Single">
                    <telerik:RadCollectionView.ItemsLayout>
                        <telerik:CollectionViewLinearLayout ItemSpacing="10" />
                    telerik:RadCollectionView.ItemsLayout>
                    <telerik:RadCollectionView.ItemTemplate>
                        <DataTemplate>
                            <Border Style="{StaticResource AddressItemStyle}">
                                <Grid ColumnDefinitions="*,Auto" ColumnSpacing="12">
                                    
                                    <VerticalStackLayout Spacing="2" VerticalOptions="Center">
                                        <Label
                                            FontAttributes="Bold"
                                            FontSize="15"
                                            Text="{Binding Label}"
                                            TextColor="#333333" />
                                        <Label
                                            FontSize="13"
                                            LineBreakMode="TailTruncation"
                                            Text="{Binding FullAddress}"
                                            TextColor="#888888" />
                                    VerticalStackLayout>

                                    
                                    <Border
                                        Grid.Column="1"
                                        BackgroundColor="{Binding SelectionColor}"
                                        HeightRequest="24"
                                        Stroke="{Binding SelectionBorderColor}"
                                        StrokeShape="RoundRectangle 12"
                                        StrokeThickness="2"
                                        VerticalOptions="Center"
                                        WidthRequest="24">
                                        <Label
                                            FontSize="14"
                                            HorizontalOptions="Center"
                                            Text="{Binding CheckMark}"
                                            TextColor="White"
                                            VerticalOptions="Center" />
                                    Border>
                                Grid>
                            Border>
                        DataTemplate>
                    telerik:RadCollectionView.ItemTemplate>
                telerik:RadCollectionView>

                
                <VerticalStackLayout Grid.Row="3" Spacing="12">
                    <telerik:RadButton
                        x:Name="SelectAddressButton"
                        BackgroundColor="#FB7647"
                        Clicked="OnSelectAddressClicked"
                        CornerRadius="12"
                        FontAttributes="Bold"
                        HeightRequest="54"
                        IsEnabled="False"
                        Text="Select Address"
                        TextColor="White" />
                    <telerik:RadButton
                        BackgroundColor="#4F3F9B"
                        Clicked="OnAddNewAddressClicked"
                        CornerRadius="12"
                        FontAttributes="Bold"
                        HeightRequest="54"
                        Text="Add new address"
                        TextColor="White" />
                VerticalStackLayout>
            Grid>            
        telerik:RadBottomSheet.BottomSheetContent>
    telerik:RadBottomSheet>        

Com o código acima, preparamos o conteúdo da Folha Inferior para ser exibido ao usuário quando o indicarmos.

Mostrando o BottomSheet ao usuário

Assim que tivermos o conteúdo da Folha Inferior pronto, o próximo passo é exibi-lo.

Existem várias maneiras de conseguir isso; usaremos o método GoToBottomSheetStateque permite a transição para um estado específico. Um estado refere-se a quanto espaço de tela a Folha Inferior ocupará, com valores possíveis sendo Hidden (padrão), Minimal (25%), Partial (50%) e Full (90%). Também é possível criar estados personalizados.

Sabendo o que foi dito acima, no meu exemplo usarei o TapGestureRecognizerque faz parte do contêiner que exibe o endereço atual, para mostrar a Folha Inferior a partir daí:

private void OnAddressTapped(object sender, EventArgs e)
{
   AddressBottomSheet.GoToBottomSheetState(BottomSheetState.FullState);
}

Da mesma forma que a Folha Inferior pode ser mostrada à vontade, ela também pode ser ocultada usando o mesmo método, GoToBottomSheetState:

private void OnCloseBottomSheet(object sender, EventArgs e)
{
   AddressBottomSheet.GoToBottomSheetState(BottomSheetState.HiddenState);
}

A execução das alterações acima resulta no seguinte:

Controle BottomSheet em ação, permitindo que os usuários selecionem um endereço de entrega diferente para um pedido

Na imagem acima você pode ver como é possível selecionar um endereço diferente graças ao uso da Folha Inferior, com um visual espetacular, tudo sem sair da janela atual.

Personalizando a folha inferior

O controle Telerik BottomSheet para .NET MAUI oferece diversas propriedades que permitem a personalização do controle. Por exemplo, a propriedade Width permite especificar o espaço horizontal que a Folha Inferior irá ocupar, seja através de um valor absoluto ou de uma porcentagem:

Demonstração de ajuste de tamanho horizontal da Folha Inferior usando a propriedade Largura

Da mesma forma, se quiser evitar que o usuário arraste para cima ou para baixo no identificador BottomSheet, você pode configurar a propriedade IsSwipeEnabled com um valor false.

Além disso, também é possível modificar a animação da Folha Inferior, habilitando-a ou desabilitando-a com a propriedade IsAnimationEnablede ajustando a duração da animação e a função de atenuação usada por meio das propriedades AnimationDuration e AnimationEasing.

Você também pode alterar recursos como borda, raio do canto e cor de fundo da Folha Inferior através da propriedade BottomSheetContentStyle. Além disso, você pode modificar as propriedades do BottomSheet Handle usando a propriedade HandleStyle.

Abaixo, mostro um exemplo das propriedades mencionadas acima aplicadas à Folha Inferior:


<ContentPage...>

    <ContentPage.Resources>
        
        <Style x:Key="BottomSheetContentStyle" TargetType="telerik:BottomSheetContentView">
            "BackgroundColor" Value="#F7F7F7" />
            "CornerRadius" Value="25,25,0,0" />
            "BorderColor" Value="#4F3F9B" />
            "BorderThickness" Value="5" />
        Style>

        
        <Style x:Key="HandleStyle" TargetType="telerik:BottomSheetHandle">
            "BackgroundColor" Value="#4F3F9B" />
            "HeightRequest" Value="5" />
            "WidthRequest" Value="60" />
            "CornerRadius" Value="3" />
        Style>
        ...
    ContentPage.Resources>

    <telerik:RadBottomSheet
        x:Name="AddressBottomSheet"
        AnimationDuration="300"
        AnimationEasing="{x:Static Easing.CubicOut}"
        BottomSheetContentStyle="{StaticResource BottomSheetContentStyle}"
        BottomSheetContentWidth="100%"
        HandleStyle="{StaticResource HandleStyle}"
        IsAnimationEnabled="True"
        IsSwipeEnabled="True"
        State="Hidden"
        StateChanging="OnBottomSheetStateChanging">
        ...
    telerik:RadBottomSheet>
ContentPage>    

O resultado da execução com as alterações anteriores aplicadas proporciona maior customização da Folha Inferior:

Personalização da folha inferior e da alça da folha inferior

Com isso, conseguimos uma melhoria visual que centraliza melhor o usuário no conteúdo da Folha Inferior.

Conclusão

Ao longo deste artigo, você aprendeu sobre o componente BottomSheet do conjunto de controle Telerik UI for .NET MAUI, entendendo sua finalidade e como personalizá-lo para mostrar aos usuários opções adicionais sem sair da tela atual.

Sem dúvida, adicionar este tipo de componente às suas aplicações pode melhorar a experiência do usuário, permitindo-lhe realizar ações rápidas ou obter informações com facilidade.

Quer experimentar você mesmo? Telerik UI para Blazor vem com uma avaliação gratuita de 30 dias.

Baixe agora

Deixe um Comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *