.NET Maui - FlexLayout


  Neste artigo vou apresentar o layout FlexLayout do .NET MAUI.

Se você esta chegando agora e não sabe o que é o .NET MAUI nem como usá-lo acompanhe o meu artigo :  Criando seu primeiro projeto  onde eu mostro como verificar e configurar o ambiente para criar sua primeira aplicação .NET MAUI.

Apresentando o FlexLayout

As classes de Layout do .NET MAUI permitem organizar e agrupar controles de interface do usuário em seu aplicativo. Escolher uma classe de layout requer conhecimento de como o layout posiciona seus elementos filho e como o layout dimensiona seus elementos filho. Além disso, pode ser necessário aninhar layouts para criar o layout desejado.

Os principais layouts disponíveis no .NET MAUI são :

O FlexLayout é um layout que pode organizar seus filhos horizontal e verticalmente em uma pilha e também pode encapsular seus filhos se houver muitos para caber em uma única linha ou coluna, sendo uma opção ideal para criar interfaces de usuário responsivas para aplicativos .NET MAUI.

As principais propriedades deste layout são:

  1. FlexDirection: Especifica a direção em que os elementos filhos são dispostos.
  2. Wrap: Especifica se os elementos devem quebrar para a próxima linha quando não houver mais espaço na direção flex.
  3. JustifyContent: Especifica como os elementos devem ser alinhados ao longo do eixo principal.
  4. AlignItems: Especifica como os elementos devem ser alinhados ao longo do eixo transversal.
  5. AlignSelf: Especifica como um elemento filho específico deve ser alinhado ao longo do eixo transversal.
  6. Flex: Especifica a proporção do espaço disponível que um elemento filho deve ocupar.
  7. Margin: Especifica o espaço fora da borda do elemento.
  8. Padding: Especifica o espaço dentro da borda do elemento.
  9. Order: Especifica a ordem dos elementos filhos.
  10. Basis: Especifica o tamanho inicial de um elemento filho ao longo do eixo principal.

Quando os itens em um FlexLayout são organizados em uma coluna, o FlexLayout tem um eixo principal vertical e um eixo cruzado horizontal.

Quando os itens em um FlexLayout são organizados em uma linha, o FlexLayout tem um eixo principal horizontal e um eixo cruzado vertical.

As propriedades vinculáveis Direction, Wrap, Justify Content, Align Items, Align Content e Position podem ser definidas em um FlexLayout para controlar a orientação e o alinhamento de todos os filhos.

As propriedades vinculáveis anexadas AlignSelf, Order, Basis, Grow e Shrink podem ser definidas em filhos do FlexLayout para controlar a orientação, o alinhamento e o dimensionamento dos filhos.

Criando o projeto .NET MAUI

A seguir vou mostrar alguns exemplos usando FlexLayout. Para isso vamos criar um novo projeto no VS 2022 usando o template .NET MAUI App chamado AppFlexLayout :

A seguir vamos criar uma pasta Pages no projeto e nesta pasta vamos criar uma Content Page usando a opção .NET MAUI e selecionando .NET MAUI ContentPage (XAML) e informando o nome FlexLayoutDemo1.xaml :

A seguir vamos definir o código abaixo neste arquivo :

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="AppFlexLayout.Pages.FlexLayoutDemo1"
             Title="Flex Layout Demo1">
    <FlexLayout Direction="Column" 
                JustifyContent="SpaceEvenly" 
                AlignItems="Center">
        <Label Text="Exemplo de FlexLayout"
                 FontSize="Large" TextColor="Red"/>
        <Image Source="dotnet_bot.svg"/>
        <Button Text="Botão sem função" FontSize="Large"/>
        <Label Text="Macoratti.net - 2023" FontSize="Large"/>
    </FlexLayout>
</ContentPage>

Este código cria um layout flexível com diferentes elementos de interface, incluindo labels, imagens e botões.

A tag <FlexLayout> define o layout flexível e os atributos Direction="Column", JustifyContent="SpaceEvenly" e AlignItems="Center" especificam o layout dos elementos filhos. A direção é definida como coluna, o espaçamento entre os elementos é distribuído de forma uniforme e os itens são alinhados ao centro.

As tags <Label> e <Button> definem etiquetas e botões, respectivamente, com as propriedades especificadas, como texto, tamanho da fonte e cor do texto. A tag <Image> define uma imagem obtida da pasta Resources/Images do projeto.

A seguir vamos definir esta página como sendo a página principal da aplicação definindo o código a seguir no arquivo App.xaml.cs:

using AppFlexLayout.Pages;
namespace AppFlexLayout;
public partial class App : Application
{
	public App()
	{
	    InitializeComponent();
                 MainPage = new NavigationPage(new FlexLayoutDemo1());
	}
}

Para executar vou usar o Emulador Android a partir do Visual Studio:

O resultado obtido no emulador é visto a seguir:

A propriedade JustifyContent descreve como os elementos filho são justificados quando há espaço extra ao redor deles.

A valor definido no exemplo foi SpaceEvenly e aloca todo o espaço vertical que sobra à esquerda igualmente entre todos os itens e acima do primeiro item e abaixo do último item.

Se tivéssemos usado um StackLayout, teriamos que atribuir a propriedade VerticalOptions de cada item para o valor CenterAndExpand para conseguir um efeito semelhante. Ocorre que a opção CenterAndExpand iria alocar duas vezes mais espaço entre cada item que antes do primeiro item e depois do último item.

Para imitar a opção CenterAndExpand de VerticalOptions podemos definir a propriedade JustifyContent com a opção SpaceAround.

Os valores suportados para JustifyContent são:

Agora vamos alterar apenas o valor da propriedade JustifyContent e ver o resultado :

<FlexLayout JustifyContent="Start">
<
Label Text="FlexLayout" TextColor="White" Background="Red" />
<
Label Text="FlexLayout" TextColor="White" Background="Green" />
<
Label Text="FlexLayout" TextColor="White" Background="Blue" />
</
FlexLayout>

<FlexLayout JustifyContent="Center">
<
Label Text="FlexLayout" TextColor="White" Background="Red" />
<
Label Text="FlexLayout" TextColor="White" Background="Green" />
<
Label Text="FlexLayout" TextColor="White" Background="Blue" />
</
FlexLayout>
 


<
FlexLayout JustifyContent="End">
<
Label Text="FlexLayout" TextColor="White" Background="Red" />
<
Label Text="FlexLayout" TextColor="White" Background="Green" />
<
Label Text="FlexLayout" TextColor="White" Background="Blue" />
</
FlexLayout>
 

<FlexLayout JustifyContent="SpaceAround">
<
Label Text="FlexLayout" TextColor="White" Background="Red" />
<
Label Text="FlexLayout" TextColor="White" Background="Green" />
<
Label Text="FlexLayout" TextColor="White" Background="Blue" />
</
FlexLayout>

 

<FlexLayout JustifyContent="SpaceBetween">
<
Label Text="FlexLayout" TextColor="White" Background="Red" />
<
Label Text="FlexLayout" TextColor="White" Background="Green" />
<
Label Text="FlexLayout" TextColor="White" Background="Blue" />
</
FlexLayout>

 

<FlexLayout JustifyContent="SpaceEvenly">
<
Label Text="FlexLayout" TextColor="White" Background="Red" />
<
Label Text="FlexLayout" TextColor="White" Background="Green" />
<
Label Text="FlexLayout" TextColor="White" Background="Blue" />
</
FlexLayout>

A propriedade Direction é definida pelos valores da enumeração FlexDirection. O valor padrão é row.

O valor definido no exemplo é Column que faz com que as views filhas do FlexLayout sejam organizadas em uma única coluna de itens.

Quando os itens de um FlexLayout são organizados em uma coluna, o FlexLayout é considerado como tendo um eixo vertical principal e um eixo horizontal transversal.

Assim, Direction indica a direção dos elementos na tela e os valores possíveis são:

A propriedade Wrap organiza a localização dos componentes. Por padrão, os elementos do FlexLayout são colocados todos em apenas uma linha. Com essa propriedade, podemos mudar esse comportamento.

Temos os seguintes valores suportados:

<FlexLayout Wrap="Wrap">

<Label Text="Label 1" BackgroundColor="Red" FontSize="Large"/>
<
Label Text="Label 2" BackgroundColor="Blue" FontSize="Large"/>
<
Label Text="Label 3" BackgroundColor="Yellow" FontSize="Large"/>
<
Label Text="Label 4" BackgroundColor="Orange" FontSize="Large"/>
<
Label Text="Label 5" BackgroundColor="Salmon" FontSize="Large"/>
<
Label Text="Label 6" BackgroundColor="Violet" FontSize="Large"/>
</
FlexLayout>
 

A propriedade AlignItens é do tipo FlexAlignItens e define o comportamento do alinhamento dos elementos no contâiner, especificando como os itens são alinhados no eixo transversal.

No exemplo foi definido o valor Center que faz com que cada item seja centralizado horizontalmente.

Se tivessemos usado um StackLayout em vez de uma FlexLayout para essa tarefa, poderíamos ter centralizado todos os itens por meio do uso da propriedade HorizontalOptions com o valor Center.

A propriedade HorizontalOptions não funciona para os filhos de um FlexLayout, mas definindo uma única propriedade AlignItems obtemos o mesmo resultado. Se precisar você pode usar a propriedade bindable AlignSelf para substituir a propriedade AlignItems para itens individuais:

Exemplo:  <Label Text="FlexLayout em Ação"  FontSize="Large" FlexLayout.AlignSelf="Start" />

Com essa alteração, essa Label será posicionada na borda esquerda do FlexLayout quando a ordem de leitura for da esquerda para a direita.

Os valores suportados para AlignItems são:

Combinando FlexLayout com outros leiautes

Podemos também combinar o FlexLayout com outros Layouts. No exemplo a seguir temos um código onde estamos usando o FlexLayout com o leiaute GridLayout:

...
<FlexLayout Direction="Row" JustifyContent="SpaceBetween" AlignItems="Stretch">
        <StackLayout BackgroundColor="Yellow" WidthRequest="160" Margin="5">
            <Grid RowSpacing="10" ColumnSpacing="10" Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Label Text="Célula 1-1" Grid.Row="0" Grid.Column="0" />
                <Label Text="Célula 1-2" Grid.Row="0" Grid.Column="1" />
                <Label Text="Célula 2-1" Grid.Row="1" Grid.Column="0" />
                <Label Text="Célula 2-2" Grid.Row="1" Grid.Column="1" />
            </Grid>
        </StackLayout>
        <StackLayout BackgroundColor="Cyan" WidthRequest="160" Margin="5">
            <Grid RowSpacing="10" ColumnSpacing="10" Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Label Text="Célula 3-1" Grid.Row="0" Grid.Column="0" />
                <Label Text="Célula 3-2" Grid.Row="0" Grid.Column="1" />
                <Label Text="Célula 4-1" Grid.Row="1" Grid.Column="0" />
                <Label Text="Célula 4-2" Grid.Row="1" Grid.Column="1" />
            </Grid>
        </StackLayout>
    </FlexLayout>
...

Nesse exemplo, o FlexLayout é usado para distribuir duas StackLayouts na tela. Cada StackLayout contém um GridLayout que define duas linhas e duas colunas. As células do GridLayout são preenchidas com Labels e o FlexLayout é configurado para distribuir as StackLayouts uniformemente na tela, com uma margem de 10 pixels em todos os lados.

A grande contribuição do FlexLayout é permitir que seus elementos sejam "flexíveis" e para isso podemos também usar as propriedades : FlexLayout.Grow e FlexLayout.Basis.

A propriedade FlexLayout.Grow

Essa propriedade nos permite ter ainda mais controle a organização dos itens no contâiner. O valor da propriedade pode ser de zero a qualquer valor numérico positivo.

Por padrão, o valor da propriedade é 0. Esse valor faz com que o elemento não cresça para caber no espaço disponível. Se tivermos um elemento em um contêiner e definirmos o valor como 1, o elemento ocupará todo o espaço.

Basicamente, essa propriedade define a capacidade de um elemento crescer, se necessário. Aceita um valor sem unidades que serve como proporção. Indica quanto espaço disponível no contêiner flexível deve ocupar o elemento.

Se todos os elementos tiverem um crescimento flexível definido como 1, o espaço restante no contâiner será distribuído igualmente para todas as views filhas. Se uma das filhas tiver um valor de 2, o espaço restante ocuparia o dobro do espaço que as outras (ou pelo menos tentaria).

A propriedade FlexLayout.Basis

Essa propriedade define o tamanho padrão de um elemento antes que o espaço disponível restante seja distribuído. Pode ser uma proporção, por exemplo, uma porcentagem (5%, 25%, etc.). Você também pode usar algumas palavras invertidas, como Auto.

E estamos conversados...

"O Senhor é a minha força e o meu escudo; nele confiou o meu coração, e fui socorrido; assim o meu coração salta de prazer, e com o meu canto o louvarei."
Salmos 28:7

Referências:


José Carlos Macoratti