Partilhar via


DrawingView

O DrawingView fornece uma superfície que permite o desenho de linhas através do uso de toque ou interação do mouse. O resultado do desenho do usuário pode ser salvo como uma imagem. Um caso de uso comum para isso é fornecer uma caixa de assinatura em um aplicativo.

Uso básico

DrawingView permite definir a cor e a largura da linha e vincular à coleção de linhas.

XAML

Incluir o namespace XAML

Para usar o kit de ferramentas no XAML, o xmlns a seguir precisa ser adicionado à sua página ou exibição:

xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"

Portanto, o seguinte:

<ContentPage
    x:Class="CommunityToolkit.Maui.Sample.Pages.MyPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

</ContentPage>

Seria modificado para incluir o xmlns conforme o seguinte:

<ContentPage
    x:Class="CommunityToolkit.Maui.Sample.Pages.MyPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit">

</ContentPage>

Usando o DrawingView

<toolkit:DrawingView
            Lines="{Binding MyLines}"
            LineColor="Red"
            LineWidth="5" />

C#

using CommunityToolkit.Maui.Views;

var drawingView = new DrawingView
{
    Lines = new ObservableCollection<IDrawingLine>(),
    LineColor = Colors.Red,
    LineWidth = 5
};

A captura de tela a seguir mostra o DrawingView resultante no Android:

Captura de tela de uma DrawingView no Android

Uso de MultiLine

Por padrão, DrawingView suporta apenas 1 linha. Para habilitar MultiLine defina IsMultiLineModeEnabled como verdadeiro. Certifique-se de que ShouldClearOnFinish seja falso.

XAML

<views:DrawingView
            Lines="{Binding MyLines}"
            IsMultiLineModeEnabled="true"
            ShouldClearOnFinish="false" />

C#

using CommunityToolkit.Maui.Views;

var gestureImage = new Image();
var drawingView = new DrawingView
{
    Lines = new ObservableCollection<IDrawingLine>(),
    IsMultiLineModeEnabled = true,
    ShouldClearOnFinish = false,
};

A captura de tela a seguir mostra o DrawingView resultante no Android:

Captura de tela de uma DrawingView com várias linhas no Android

Manipular evento quando a linha de desenho for concluída

DrawingView permite assinar eventos como OnDrawingLineCompleted. O comando correspondente DrawingLineCompletedCommand também está disponível.

XAML

<views:DrawingView
            Lines="{Binding MyLines}"
            DrawingLineCompletedCommand="{Binding DrawingLineCompletedCommand}"
            OnDrawingLineCompleted="OnDrawingLineCompletedEvent" />

C#

using CommunityToolkit.Maui.Views;

var gestureImage = new Image();
var drawingView = new DrawingView
{
    Lines = new ObservableCollection<IDrawingLine>(),
    DrawingLineCompletedCommand = new Command<IDrawingLine>(async (line) =>
    {
        var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

        var stream = await line.GetImageStream(gestureImage.Width, gestureImage.Height, Colors.Gray.AsPaint(), cts.Token);
        gestureImage.Source = ImageSource.FromStream(() => stream);
    })
};
drawingView.OnDrawingLineCompleted += async (s, e) =>
{
    var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

    var stream = await e.LastDrawingLine.GetImageStream(gestureImage.Width, gestureImage.Height, Colors.Gray.AsPaint(), cts.Token);
    gestureImage.Source = ImageSource.FromStream(() => stream);
};

Uso em uma ScrollView

Quando a DrawingView é usada dentro de uma ScrollView, às vezes, a interação de toque com a ScrollView pode ser interceptada no iOS. Evite que isso ocorra definindo a propriedade ShouldDelayContentTouches como false no iOS, de acordo com o seguinte exemplo:

Resolvi esse problema adicionando ios:ScrollView.ShouldDelayContentTouches="false" à ScrollView que contém a DrawingView:

<ContentPage
    xmlns:ios="clr-namespace:Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;assembly=Microsoft.Maui.Controls">

    <ScrollView ios:ScrollView.ShouldDelayContentTouches="false">

        <DrawingView />

    </ScrollView>

</ContentPage>

Para obter mais informações, confira Toques de conteúdo da ScrollView.

Uso avançado

Para obter todos os benefícios, DrawingView fornece os métodos para obter o fluxo de imagem das linhas de desenho.

XAML

<toolkit:DrawingView
            x:Name="DrawingViewControl"
            Lines="{Binding MyLines}"
            IsMultiLineModeEnabled="true"
            ShouldClearOnFinish="true"
            DrawingLineCompletedCommand="{Binding DrawingLineCompletedCommand}"
            OnDrawingLineCompleted="OnDrawingLineCompletedEvent"
            LineColor="Red"
            LineWidth="5"
            HorizontalOptions="Fill"
            VerticalOptions="Fill">
            <toolkit:DrawingView.Background>
                    <LinearGradientBrush StartPoint="0,0"
                                         EndPoint="0,1">
                        <GradientStop Color="Blue"
                                      Offset="0"/>
                        <GradientStop Color="Yellow"
                                      Offset="1"/>
                    </LinearGradientBrush>
            </toolkit:DrawingView.Background>
</toolkit:DrawingView>

C#

using CommunityToolkit.Maui.Views;

var gestureImage = new Image();
var drawingView = new DrawingView
{
    Lines = new ObservableCollection<IDrawingLine>(),
    IsMultiLineModeEnabled = true,
    ShouldClearOnFinish = false,
    DrawingLineCompletedCommand = new Command<IDrawingLine>(async (line) =>
    {
        var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

        var stream = await line.GetImageStream(gestureImage.Width, gestureImage.Height, Colors.Gray.AsPaint(), cts.Token);
        gestureImage.Source = ImageSource.FromStream(() => stream);
    }),
    LineColor = Colors.Red,
    LineWidth = 5,
    Background = Brush.Red
};
drawingView.OnDrawingLineCompleted += async (s, e) =>
{
    var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

    var stream = await e.LastDrawingLine.GetImageStream(gestureImage.Width, gestureImage.Height, Colors.Gray.AsPaint(), cts.Token);
    gestureImage.Source = ImageSource.FromStream(() => stream);
};

// get stream from lines collection
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var lines = new List<IDrawingLine>();
var stream1 = await DrawingView.GetImageStream(
                lines,
                new Size(gestureImage.Width, gestureImage.Height),
                Colors.Black.
                cts.Token);

// get steam from the current DrawingView
var stream2 = await drawingView.GetImageStream(gestureImage.Width, gestureImage.Height, cts.Token);

Propriedades

Propriedade Type Descrição
Linhas ObservableCollection<IDrawingLine> Coleção de IDrawingLine que estão atualmente no DrawingView
IsMultiLineModeEnabled bool Alterna o modo multilinha. Quando verdadeiro, várias linhas podem ser desenhadas no DrawingView enquanto o toque/clique é liberado entre as linhas. Observação: quando ClearOnFinish também está habilitado, as linhas são limpas após o toque/clique ser liberado. Além disso, DrawingLineCompletedCommand será disparado após cada linha desenhada.
ShouldClearOnFinish bool Indica se DrawingView é apagado após soltar o toque/clique e uma linha é desenhada. Observação: quando IsMultiLineModeEnabled também está habilitado, isso pode causar um comportamento inesperado.
DrawingLineStartedCommand ICommand Esse comando é invocado sempre que o desenho de uma linha no DrawingView é iniciado.
DrawingLineCancelledCommand ICommand Este comando é invocado sempre que o desenho de uma linha no DrawingView for cancelado.
DrawingLineCompletedCommand ICommand Esse comando é invocado sempre que o desenho de uma linha no DrawingView for concluído. . Observe que isso é acionado após o toque ou clique ser suspenso. Quando MultiLineMode está habilitado, esse comando é disparado várias vezes.
PointDrawnCommand ICommand Esse comando é invocado sempre que o desenho de um ponto no DrawingView for concluído.
OnDrawingLineStarted EventHandler<DrawingLineStartedEventArgs> DrawingView eO evento ocorre quando o desenho da linha é iniciado.
OnDrawingLineCancelled EventHandler<EventArgs> DrawingView O evento ocorre quando o desenho da linha é cancelado.
OnDrawingLineCompleted EventHandler<DrawingLineCompletedEventArgs> DrawingView O evento ocorre quando o desenho da linha é concluído.
OnPointDrawn EventHandler<PointDrawnEventArgs> DrawingView evento ocorre quando o ponto é desenhado.
LineColor Color A cor usada por padrão para desenhar uma linha no DrawingView.
LineWidth float A largura usada por padrão para desenhar uma linha no DrawingView.

DrawingLine

O DrawingLine contém a lista de pontos e permite configurar cada estilo de linha individualmente.

Propriedades

Propriedade Type Descrição Valor padrão
LineColor Color A cor usada para desenhar a linha no DrawingView. Colors.Black
LineWidth float A largura usada para desenhar a linha no DrawingView. 5
Pontos ObservableCollection<PointF> A coleção de PointF que forma a linha. new()
Granularidade int A granularidade dessa linha. O valor mínimo é 5. Quanto maior o valor, mais suave será a linha e mais lento será o programa. 5
ShouldSmoothPathWhenDrawn bool Habilita ou desabilita se essa linha for suavizada (suavização) quando desenhada. false

IDrawingLine personalizado

Existem 2 etapas para substituir o padrão DrawingLine pela implementação personalizada:

  1. Crie uma classe personalizada que implemente IDrawingLine:
    public class MyDrawingLine : IDrawingLine
    {
        public ObservableCollection<PointF> Points { get; } = new();
        ...
    }
    
  2. Crie uma classe personalizada que implemente IDrawingLineAdapter.
    public class MyDrawingLineAdapter : IDrawingLineAdapter
    {
        public IDrawingLine(MauiDrawingLine mauiDrawingLine)
        {
            return new MyDrawingLine
            {
                Points = mauiDrawingLine.Points,
                ...
            }
        }
    }
    
  3. Definir personalizado IDrawingLineAdapter em IDrawingViewHandler:
    var myDrawingLineAdapter = new MyDrawingLineAdapter();
    drawingViewHandler.SetDrawingLineAdapter(myDrawingLineAdapter);
    

DrawingLineStartedEventArgs

Argumento de evento que contém o último ponto de desenho.

Propriedades

Propriedade Type Descrição
Point PointF Último ponto de desenho.

DrawingLineCompletedEventArgs

Argumento de evento que contém a última linha do desenho.

Propriedades

Propriedade Type Descrição
LastDrawingLine IDrawingLine Última linha de desenho.

PointDrawnEventArgs

Argumento de evento que contém o último ponto de desenho.

Propriedades

Propriedade Type Descrição
Point PointF Último ponto de desenho.

Métodos

Método Descrição
GetImageStream Recupera um Stream contendo uma imagem do Lines que está atualmente desenhado no DrawingView.
GetImageStream (estático) Recupera um Stream contendo uma imagem da coleção de IDrawingLine que é fornecida como parâmetro.

Exemplos

Você pode encontrar um exemplo desse recurso na prática em Aplicativo de exemplo do Kit de Ferramentas da Comunidade do .NET MAUI.

API

O código-fonte do DrawingView pode ser encontrado no repositório GitHub do .NET MAUI Community Toolkit.