Xamarin Forms - Apresentando Shapes - I
 Neste artigo vou apresentar o novo recurso Shapes do Xamarin Forms 4.7.

Para realizar desenhos em aplicações Xamarin Forms você tinha que usar uma biblioteca de terceiros como a SkiaSharp.

Tinha, pois a partir da versão 4.7 do Xamarin Forms, temos disponível o recurso Shapes.

Um Shape é um tipo de View que permite desenhar uma forma na tela. Os objetos Shape podem ser usados nas classes de layout e na maioria dos controles, visto que a classe Shape deriva da classe View.

O novo recurso Shapes está disponível no namespace Xamarin.Forms.Shapes no iOS, Android, macOS, na Plataforma Universal do Windows (UWP) e na Windows Presentation Foundation (WPF).

Atualmente, o Xamarin.Forms Shapes esta na fase dita experimental e pode ser usado definindo a configuração da flag Shapes_Experimental que deve ser adicionada conforme mostra o código abaixo nas classes AppDelegate no iOS, e, MainActivity no Android, antes da chamada de Forms.Init:


 global::Xamarin.Forms.Forms.SetFlags("Shapes_Experimental");

A classe Shape define as seguintes propriedades:

Todas elas suportam objetos BindableProperty podendo assim serem usadas no Data Binding.

A seguir temos os diferentes objetos que derivam da classe Shape:

Podemos ainda aplicar animações que conectam elementos comuns de uma página a outra. Para usar este recurso basta fazer o seguinte :

Configura a documentação em : https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/shapes/

Os objetos Shape têm uma propriedade Aspect, do tipo Stretch que determina como o conteúdo de um objeto Shape é esticado para preencher o espaço de layout do objeto Shape.

O espaço de layout de um objeto Shape é a quantidade de espaço que o Shape é alocado pelo sistema de layout do Xamarin.Forms, devido a uma configuração explícita WidthRequest e HeightRequest ou pelas configurações HorizontalOptions e VerticalOptions.

A enumeração Stretch define os seguintes membros:

Os objetos Color são usados para pintar o traçado e o preenchimento da forma. No exemplo o traçado (Stroke) esta sendo pintado de vermelho e o preenchimento (Fill) de azul escuro:


<Ellipse Fill="DarkBlue"
         Stroke="Red"
         StrokeThickness="4"
         WidthRequest="150"
         HeightRequest="50"
         HorizontalOptions="Start" />

'Bora' pra prática...

Recursos usados:

Criando o projeto Xamarin Forms

Vamos criar um novo projeto Xamarin Forms no VS 2019 Community com o nome XF_Shapes1.

Nota: Verifique se você precisa atualizar as versões do Xamarin Forms e do Xamarin.Essentials

Você pode ver como criar um projeto no Xamarin Forms neste link: Criar Projeto Xamarin Forms

Crie uma pasta Views no projeto e nesta pasta inclua seis Content Pages : RectanglePage.xaml, EllipsePage.xaml, LinePage.xaml, PolylinePage.xaml, PolygonPage.xaml e PathPage.xaml

Abra o arquivo App.xaml.cs e altere o código do construtor da classe App:

...
      public App()
        {
            InitializeComponent();
            MainPage = new NavigationPage(new MainPage());
        }
...

A seguir abra o arquivo MainPage.xaml e inclua o código abaixo:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="XF_Shapes1.MainPage">
    
    <StackLayout>
        <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
            <Button x:Name="btnShape1" Text="Rectangle" Clicked="btnShape1_Clicked"/>
            <Button x:Name="btnShape2" Text="Ellipse" Clicked="btnShape2_Clicked"/>
            <Button x:Name="btnShape3" Text="Line" Clicked="btnShape3_Clicked"/>
            <Button x:Name="btnShape4" Text="PolyLine" Clicked="btnShape4_Clicked"/>
            <Button x:Name="btnShape5" Text="Polygon" Clicked="btnShape5_Clicked"/>
            <Button x:Name="btnShape6" Text="Path" Clicked="btnShape6_Clicked"/>
        </StackLayout>
    </StackLayout>
</ContentPage>

Aqui apenas criamos os botões na página principal para acionar os tipos figuras que iremos tratar.

E no arquivo MainPage.xaml.cs o código para os eventos Click de cada Button:

using System;
using System.ComponentModel;
using Xamarin.Forms;
using XF_Shapes1.Views;
namespace XF_Shapes1
{
    [DesignTimeVisible(false)]
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
        private void btnShape1_Clicked(object sender, EventArgs e)
        {
            App.Current.MainPage.Navigation.PushAsync(new RectanglePage());
        }
        private void btnShape2_Clicked(object sender, EventArgs e)
        {
            App.Current.MainPage.Navigation.PushAsync(new EllipsePage());
        }
        private void btnShape3_Clicked(object sender, EventArgs e)
        {
            App.Current.MainPage.Navigation.PushAsync(new LinePage());
        }
        private void btnShape4_Clicked(object sender, EventArgs e)
        {
            App.Current.MainPage.Navigation.PushAsync(new PolylinePage());
        }
        private void btnShape5_Clicked(object sender, EventArgs e)
        {
            App.Current.MainPage.Navigation.PushAsync(new PolygonPage());
        }
        private void btnShape6_Clicked(object sender, EventArgs e)
        {
            App.Current.MainPage.Navigation.PushAsync(new PathPage());
        }
    }
}

Vejamos agora o tratamento básico para cada uma das formas que derivam de Shapes.

Nota: Para simplificar estou mostrando apenas o código que efetivamente desenha a figura.

1- RectanglePage.xaml

É uma forma com quatro lados cujos lados opostos são os mesmos. Para criar um retângulo básico, as propriedades WidthRequest, HeightRequest e Fill devem ser especificadas.

A classe Rectangle possui as propriedades:

Para dar um contorno ao retângulo, defina sua propriedade Stroke como Color.
A propriedade StrokeThickness especifica a espessura do contorno do retângulo.
Para fornecer cantos arredondados ao retângulo, defina suas propriedades RadiusX e RadiusY.

...
  <StackLayout Padding="10">
            <Rectangle 
                Fill="Red"
                WidthRequest="150"
                HeightRequest="100"
                HorizontalOptions="Center" />
            <Rectangle 
                Fill="White"
                Stroke ="Black"
                WidthRequest="150"
                HeightRequest="150"
                HorizontalOptions="Center" />
            <Rectangle Fill="DarkBlue"
                Stroke="Red"
                StrokeThickness="4"
                StrokeDashArray="1,1"
                StrokeDashOffset="6"
                WidthRequest="150"
                HeightRequest="50"
                HorizontalOptions="Center" />
            <Rectangle Fill="Yellow"
                Stroke="Black"
                StrokeThickness="3"
                RadiusX="50"
                RadiusY="10"
                WidthRequest="150"
                HeightRequest="100"
                HorizontalOptions="Center" />
        </StackLayout>
...

 

2- EllipsePage.xaml

Uma Elipse é um tipo de seção cônica.

Para desenhar uma elipse, crie um objeto Ellipse e defina suas propriedades WidthRequest e HeightRequest.
Para pintar o interior da elipse, defina sua propriedade Fill como Color.
Para dar um contorno à elipse, defina sua propriedade Stroke como uma Cor.
A propriedade StrokeThickness especifica a espessura do contorno da elipse.

 ...
 <StackLayout Margin="20">
            <Label Text="Elipse preenchida" />
            <Ellipse Fill="Red"
                     WidthRequest="100"
                     HeightRequest="50"
                     HorizontalOptions="Center" />
            <Label Text="Circulo" />
            <Ellipse Stroke="Red"
                     StrokeThickness="4"
                     WidthRequest="100"
                     HeightRequest="100"
                     HorizontalOptions="Center" />
            <Label Text="Ellipse com stroke" />
            <Ellipse Stroke="Black"
                     StrokeThickness="4"
                     WidthRequest="100"
                     HeightRequest="50"
                     HorizontalOptions="Center" />
            <Label Text="Filled ellipse com stroke" />
            <Ellipse Fill="Yellow"
                     Stroke="Red"
                     StrokeThickness="4"
                     WidthRequest="100"
                     HeightRequest="50"
                     HorizontalOptions="Center" />
            <Label Text="ellipse com dashed stroke" />
            <Ellipse Fill="Blue"
                     Stroke="Red"
                     StrokeThickness="4"
                     StrokeDashArray="1,1"
                     StrokeDashOffset="6"
                     WidthRequest="150"
                     HeightRequest="50"
                     HorizontalOptions="Center" />
        </StackLayout>
...

 

3- LinePage.xaml

A classe Line pode ser usada para desenhar linhas e define as seguintes propriedades:

Para desenhar uma linha, crie um objeto Line e defina suas propriedades X1 e Y1 como ponto inicial e suas propriedades X2 e Y como ponto final. Além disso, defina sua propriedade Stroke como Color, porque uma linha sem traço é invisível.

...
 <ScrollView>
    <StackLayout Margin="20" Padding="10">
        <Label Text="Line" />
        <Line X1="40"
                  Y1="0"
                  X2="0"
                  Y2="120"
                  Stroke="Red" />
        <Label Text="Line with stroke" />
        <Line X1="40"
                  Y1="0"
                  X2="0"
                  Y2="120"
                  Stroke="DarkBlue"
                  StrokeThickness="4" />
        <Label Text="Dashed line" />
        <Line X1="40"
                  Y1="0"
                  X2="0"
                  Y2="120"
                  Stroke="DarkBlue"
                  StrokeDashArray="1,1"
                  StrokeDashOffset="6" />
        <Label Text="LineCap: Flat" />
        <Line X1="0"
                  Y1="20"
                  X2="300"
                  Y2="20"
                  StrokeLineCap="Flat"
                  Stroke="Red"
                  StrokeThickness="12" />
        <Label Text="LineCap: Square" />
        <Line X1="0"
                  Y1="20"
                  X2="300"
                  Y2="20"
                  StrokeLineCap="Square"
                  Stroke="Green"
                  StrokeThickness="12" />
        <Label Text="LineCap: Round" />
        <Line X1="0"
                  Y1="20"
                  X2="300"
                  Y2="20"
                  StrokeLineCap="Round"
                  Stroke="Black"
                  StrokeThickness="12" />
    </StackLayout>
    </ScrollView>
...

 

4- PolylinePage.xaml

A classe Polyline deriva da classe Shape e pode ser usada para desenhar uma série de linhas retas conectadas. Uma polilinha é semelhante a um polígono, exceto que o último ponto de uma polilinha não está conectado ao primeiro ponto.  Esta classe define as seguintes propriedades:

O tipo PointsCollection é um objeto ObservableCollection de Point.

A estrutura Point define propriedades X e Y, do tipo double, que representam um par de coordenadas x e y no espaço 2D. Portanto, a propriedade Points deve ser definida como uma lista de pares de coordenadas e coordenadas y que descrevem os pontos de vértice da polilinha, delimitados por uma única vírgula e/ou um ou mais espaços. Por exemplo, "40,10 70,80" e "40 10, 70 80" são válidos.

...
  <ScrollView>
        <StackLayout Margin="20" Padding="10">
            <Label Text="Polyline" />
            <Polyline Points="0,0 10,30, 15,0 18,60 23,30 35,30 40,0 43,60 48,30 100,30"
                      Stroke="Red" />
            <Label Text="Polyline with dashed stroke" />
            <Polyline Points="0,0 10,30, 15,0 18,60 23,30 35,30 40,0 43,60 48,30 100,30"
                      Stroke="Red"
                      StrokeThickness="2"
                      StrokeDashArray="1,1"
                      StrokeDashOffset="6" />
            <Label Text="EvenOdd polyline" />
            <!-- FillRule não precisa ser definido pois EvenOdd é o padrão default. -->
            <Polyline Points="0 48, 0 144, 96 150, 100 0, 192 0, 192 96, 50 96, 48 192, 150 200 144 48"
                     Fill="Blue"
                     Stroke="Red"
                     StrokeThickness="3" />
            <Label Text="NonZero polyline" />
            <Polyline Points="0 48, 0 144, 96 150, 100 0, 192 0, 192 96, 50 96, 48 192, 150 200 144 48"
                     Fill="Black"
                     FillRule="Nonzero"
                     Stroke="Yellow"
                     StrokeThickness="3" />
            <Label Text="LineJoin: Miter" />
            <!-- StrokeLineJoin não precisa ser definida pois Miter é o padrão. -->
            <Polyline Points="20 20,250 50,20 120"
                      Stroke="Black"
                      StrokeThickness="20" />
            <Label Text="LineJoin: Bevel" />
            <Polyline Points="20 20,250 50,20 120"
                      Stroke="DarkBlue"
                      StrokeThickness="20"
                      StrokeLineJoin="Bevel" />
            <Label Text="LineJoin: Round" />
            <Polyline Points="20 20,250 50,20 120"
                      Stroke="Red"
                      StrokeThickness="20"
                      StrokeLineJoin="Round" />
        </StackLayout>
    </ScrollView>
...

Abaixo temos o resultado:

Na próxima parte do artigo vamos continuar a apresentar as demais formas derivadas de Shape.

Pegue o código do projeto compartilhado aqui :  XF_Shapes1.zip   

(Porque a vida foi manifestada, e nós a vimos, e testificamos dela, e vos anunciamos a vida eterna, que estava com o Pai, e nos foi manifestada);
1 João 1:2

Referências:


José Carlos Macoratti