Widok rysunku

DrawingView zapewnia powierzchnię umożliwiającą rysowanie linii przy użyciu dotyku lub myszy. Wynik rysunku użytkownika można zapisać jako plik obrazu. Typowym przypadkiem użycia jest podanie pola podpisu w aplikacji.

Podstawowy sposób użycia

DrawingView umożliwia ustawienie koloru linii, szerokości linii i powiązania z kolekcją linii.

XAML

Dołączanie przestrzeni nazw XAML

Aby można było używać zestawu narzędzi w języku XAML, należy dodać następujące xmlns elementy do strony lub widoku:

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

Zatem następujące:

<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>

Zostanie zmodyfikowana w celu uwzględnienia xmlns w następujący sposób:

<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>

Korzystanie z obiektu 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
};

Poniższy zrzut ekranu przedstawia uzyskany widok DrawingView w systemie Android:

Zrzut ekranu przedstawiający obiekt DrawingView w aplikacji Android

Użycie wielowierszowe

Domyślnie DrawingView obsługuje tylko 1 wiersz. Aby włączyć MultiLine, ustaw IsMultiLineModeEnabled na wartość true. Upewnij się, że ShouldClearOnFinish ma wartość false.

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,
};

Poniższy zrzut ekranu przedstawia uzyskany widok DrawingView na Androidzie:

Zrzut ekranu przedstawiający obiekt DrawingView z wieloma wierszami w systemie Android

Zapisywanie wyniku na obrazie

Zestaw narzędzi .NET MAUI Community Toolkit oferuje kilka opcji zapisywania wynikowego rysunku na obrazie. Te opcje są następujące:

Zapisywanie z DrawingView

DrawingView udostępnia metodę GetImageStream, która wygeneruje obraz i zwróci jego zawartość jako obiekt Stream.

Poniższy przykład spowoduje wyeksportowanie rysunku do obrazu o żądanej szerokości 400 i żądanej wysokości 300. Żądane wymiary zostaną dostosowane, aby upewnić się, że współczynnik proporcji rysunku został zachowany.

await drawingView.GetImageStream(desiredWidth: 400, desiredHeight: 300);

Note

Domyślnie metoda GetImageStream zwraca obraz zawierający narysowane linie, który nie będzie odpowiadał całej powierzchni widocznej dla użytkownika. Aby wygenerować obraz, który dokładnie odpowiada powierzchni wyświetlanej w aplikacji, należy użyć metody GetImageStream z parametrem DrawingViewOutputOption.

W poniższym przykładzie pokazano, jak wygenerować obraz, który jest bezpośrednio zgodny z powierzchnią DrawingView wyświetlaną w aplikacji:

await drawingView.GetImageStream(desiredWidth: 400, desiredHeight: 300, imageOutputOption: DrawingViewOutputOption.FullCanvas);

Zapisywanie z DrawingViewService

Użycie metod DrawingView może utrudnić utworzenie aplikacji przy użyciu wzorca MVVM, aby pomóc w radzeniu sobie z tym zestawem narzędzi .NET MAUI Community Toolkit również udostępnia klasę DrawingViewService, która umożliwi również generowanie strumienia obrazów.

ImageLineOptions.JustLines

W poniższym przykładzie pokazano, jak wygenerować strumień obrazu o żądanej szerokości 1920 i wysokości 1080 oraz niebieskie tło. Deweloperzy mogą użyć metody ImageLineOptions.JustLines, aby udostępnić odpowiednie opcje do wyeksportowania wyłącznie narysowanych linii. Aby wyeksportować całą kanwę, zobacz ImageLineOptions.FullCanvas

await using var stream = await DrawingViewService.GetImageStream(
    ImageLineOptions.JustLines(Lines, new Size(1920, 1080), Brush.Blue));

ImageLineOptions.FullCanvas

Aby wygenerować obraz, który jest bezpośrednio zgodny z powierzchnią DrawingView, ImageLineOptions.FullCanvas można użyć metody w następujący sposób.

await using var stream = await DrawingViewService.GetImageStream(
    ImageLineOptions.FullCanvas(Lines, new Size(1920, 1080), Brush.Blue, new Size(CanvasWidth, CanvasHeight)));

Na potrzeby tego przykładu właściwości CanvasWidth i CanvasHeight zostały odpowiednio powiązane z danymi z właściwościami Width i Height obiektu DrawingView. Pełne rozwiązanie można znaleźć w przykładowej aplikacji .NET MAUI Community Toolkit.

Obsługa zdarzenia po zakończeniu rysowania linii

DrawingView umożliwia subskrybowanie zdarzeń, takich jak OnDrawingLineCompleted. Odpowiednie polecenie DrawingLineCompletedCommand jest również dostępne.

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);
};

Użycie wewnątrz ScrollView

Podczas używania DrawingView wewnątrz ScrollView interakcja dotykowa z ScrollView może być czasami przechwytywana w iOS. Można temu zapobiec, ustawiając ShouldDelayContentTouches właściwość na false w systemie iOS zgodnie z poniższym przykładem:

Rozwiązano ten problem, dodając element ios:ScrollView.ShouldDelayContentTouches="false" do widoku ScrollView, który zawiera element DrawingView:

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

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

        <DrawingView />

    </ScrollView>

</ContentPage>

Więcej informacji można znaleźć w sekcji Dotknięcia zawartości ScrollView.

Użycie zaawansowane

Aby w pełni skorzystać z tych możliwości, element DrawingView udostępnia metody umożliwiające uzyskanie strumienia obrazu linii rysowanych.

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);

Właściwości

Majątek Typ Description
Wiersze ObservableCollection<IDrawingLine> Zbiór elementów IDrawingLine, które obecnie znajdują się w DrawingView
IsMultiLineModeEnabled bool Przełącza tryb wielowierszowy. Jeśli ustawiono wartość true, na DrawingView można rysować wiele linii, jeśli między liniami zwolni się dotknięcie/kliknięcie. Uwaga: gdy opcja ClearOnFinish jest również włączona, linie są czyszczone po zwolnieniu stuknięcia/kliknięcia. Ponadto DrawingLineCompletedCommand zostanie uruchomiony po narysowaniu każdej linii.
ShouldClearOnFinish bool Wskazuje, czy pole DrawingView zostaje wyczyszczone po zakończeniu stuknięcia/kliknięcia i czy zostaje narysowana linia. Uwaga: jeśli IsMultiLineModeEnabled jest również włączona, może to spowodować nieoczekiwane zachowanie.
DrawingLineStartedCommand ICommand To polecenie jest wywoływane za każdym razem, gdy rozpoczyna się rysowanie linii na DrawingView.
PolecenieAnulowaniaRysowaniaLinii ICommand To polecenie jest wywoływane za każdym razem, gdy rysowanie linii na obiekcie DrawingView zostanie anulowane.
DrawingLineCompletedCommand ICommand To polecenie jest wywoływane za każdym razem, gdy narysowanie linii na DrawingView zostanie zakończone. . Należy pamiętać, że zdarzenie to jest wyzwalane po zwolnieniu dotknięcia lub kliknięcia. Gdy MultiLineMode jest włączone, to polecenie jest wykonywane wielokrotnie.
PointDrawnCommand ICommand To polecenie jest wywoływane za każdym razem, gdy zakończy się rysowanie punktu na DrawingView.
OnDrawingLineStarted EventHandler<DrawingLineStartedEventArgs> DrawingView zdarzenie występuje po rozpoczęciu rysowania linii.
OnDrawingLineCancelled EventHandler<EventArgs> DrawingView zdarzenie występuje po anulowaniu rysowania linii.
OnDrawingLineCompleted EventHandler<DrawingLineCompletedEventArgs> DrawingView zdarzenie występuje po zakończeniu rysowania linii.
OnPointDrawn EventHandler<PointDrawnEventArgs> DrawingView zdarzenie występuje po narysowaniu punktu.
Kolor linii Color Kolor używany domyślnie do rysowania linii na DrawingView.
Szerokość linii float Szerokość, która jest domyślnie używana do rysowania linii na DrawingView.

Linia rysowania

Element DrawingLine zawiera listę punktów i umożliwia indywidualne konfigurowanie każdego stylu wiersza.

Właściwości

Majątek Typ Description Domyślna wartość
Kolor linii Color Kolor używany do rysowania linii na DrawingView. Colors.Black
Szerokość linii float Szerokość, która jest używana do rysowania linii na DrawingView. 5
Punkty ObservableCollection<PointF> Zbiór elementów PointF, które tworzą linię. new()
Granularność int Stopień szczegółowości tej linii. Minimalna wartość to 5. Im większa wartość, tym bardziej gładka linia, tym wolniej program. 5
PowinnaWygładzaćŚcieżkęPodczasRysowania bool Określa, czy ta linia jest wygładzana (z antyaliasingiem) podczas rysowania. false

Niestandardowa linia IDrawingLine

Aby zastąpić wartość domyślną DrawingLine implementacją niestandardową, należy wykonać 2 kroki:

  1. Utwórz klasę niestandardową, która implementuje IDrawingLine:
    public class MyDrawingLine : IDrawingLine
    {
        public ObservableCollection<PointF> Points { get; } = new();
        ...
    }
    
  2. Utwórz niestandardową klasę, która implementuje interfejs IDrawingLineAdapter.
    public class MyDrawingLineAdapter : IDrawingLineAdapter
    {
        public IDrawingLine(MauiDrawingLine mauiDrawingLine)
        {
            return new MyDrawingLine
            {
                Points = mauiDrawingLine.Points,
                ...
            }
        }
    }
    
  3. Ustaw wartość niestandardową IDrawingLineAdapter w pliku IDrawingViewHandler:
    var myDrawingLineAdapter = new MyDrawingLineAdapter();
    drawingViewHandler.SetDrawingLineAdapter(myDrawingLineAdapter);
    

DrawingLineStartedEventArgs

Argument zdarzenia, który zawiera ostatni punkt rysunku.

Właściwości

Majątek Typ Description
Point PointF Ostatni punkt rysunku.

DrawingLineCompletedEventArgs

Argument zdarzenia, który zawiera ostatni wiersz rysunku.

Właściwości

Majątek Typ Description
LastDrawingLine IDrawingLine Ostatnia linia rysunku.

PointDrawnEventArgs

Argument zdarzenia, który zawiera ostatni punkt rysunku.

Właściwości

Majątek Typ Description
Point PointF Ostatni punkt rysunku.

Methods

Metoda Description
GetImageStream Pobiera obiekt Stream zawierający obraz elementu Lines, aktualnie narysowanego na elemencie DrawingView.
GetImageStream (statyczny) Pobiera element Stream zawierający obraz kolekcji IDrawingLine przekazanej jako parametr.

Examples

Przykład tej funkcji można znaleźć w przykładzie przykładowej aplikacji .NET MAUI Community Toolkit Sample Application.

API

Kod źródłowy DrawingView można znaleźć w repozytorium .NET MAUI Community Toolkit GitHub.