DrawingView

DrawingView 提供了一个图面,允许使用触摸或鼠标交互绘制线条。 用户绘图的结果可以保存为图像。 一个常见的用例是在应用程序中提供签名框。

基本用法

DrawingView 允许设置线条颜色、线条宽度并绑定到线条集合。

XAML

包括 XAML 命名空间

若要在 XAML 中使用工具包,需要将以下 xmlns 添加到页面或视图中:

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

因此,请执行以下步骤:

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

将被修改为包含 xmlns,具体如下:

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

使用绘图视图功能

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

以下屏幕截图显示了 Android 上生成的 DrawingView:

Android 上 DrawingView 的屏幕截图

多行用法

默认情况下,DrawingView 仅支持 1 行。 若要启用 MultiLine,请将 IsMultiLineModeEnabled 设置为 true。 请确保 ShouldClearOnFinish 为假。

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

以下屏幕截图显示了 Android 上生成的 DrawingView:

在 Android 上支持多行的 DrawingView 屏幕截图

将结果保存为图像文件

.NET MAUI 社区工具包提供了几种用于将生成的绘图保存到图像的选项,这些选项如下所示:

DrawingView 保存

DrawingView 提供了 GetImageStream 方法,该方法将生成图像并返回 Stream中的内容。

以下示例将绘图导出到所需宽度为 400 的图像,所需高度为 300。 将调整期望的尺寸,以确保保留绘图的纵横比。

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

注意

默认情况下,GetImageStream 方法将返回包含绘制线条的图像,这与用户看到的完整图面不匹配。 若要生成与应用程序中显示的图面直接匹配的图像,必须使用具有 DrawingViewOutputOption 参数的 GetImageStream 方法。

以下示例演示如何生成与应用程序中显示的 DrawingView 图面直接匹配的图像:

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

DrawingViewService 保存

使用 DrawingView 方法可能会使使用 MVVM 模式生成应用程序变得困难,以帮助处理此 .NET MAUI 社区工具包还提供 DrawingViewService 类,该类还允许生成图像流。

ImageLineOptions.JustLines

下面的示例演示如何生成所需宽度为 1920 的图像流,高度为 1080 和蓝色背景。 开发人员可以使用 ImageLineOptions.JustLines 方法提供适当的选项来仅导出绘制的线条。 若要导出整个画布,请参阅 ImageLineOptions.FullCanvas

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

ImageLineOptions.FullCanvas

为了生成与 DrawingView 图面直接匹配的图像,可以使用 ImageLineOptions.FullCanvas 方法,如下所示。

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

在此示例中,CanvasWidthCanvasHeight 属性已分别绑定到 DrawingViewWidthHeight 属性。 有关完整解决方案,请参阅 .NET MAUI 社区工具包示例应用程序

绘制线条完成时处理事件

DrawingView 允许订阅 OnDrawingLineCompleted等事件。 还可以使用相应的命令 DrawingLineCompletedCommand

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

在 ScrollView 中使用

ScrollView 内使用 DrawingView 时,有时可以在 iOS 上截获与 ScrollView 的触摸交互。 可以通过将 ShouldDelayContentTouches 属性设置为在 iOS 上 false 来防止这种情况,如以下示例所示:

我解决了此问题,方法是将 ios:ScrollView.ShouldDelayContentTouches=“false”添加到包含 DrawingView 的 ScrollView:

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

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

        <DrawingView />

    </ScrollView>

</ContentPage>

有关详细信息,请参阅 ScrollView 内容涉及

高级用法

为了获得全部优势,DrawingView 提供了获取绘图线图像流的方法。

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

性能

财产 类型 描述
线 ObservableCollection<IDrawingLine> 当前位于 DrawingView 上的 IDrawingLine 集合
是否启用多行模式 bool 切换多行模式。 如果为 true,则在两行之间释放点击/单击时,可以在 DrawingView 上绘制多个线条。 注意:当同时启用 ClearOnFinish 时,点击/单击释放后将清除这些行。 此外,绘制完每一行后,都会触发 DrawingLineCompletedCommand
应在完成时清除 bool 指示在释放点击/单击后是否清除 DrawingView 并绘制线条。 注意:启用 IsMultiLineModeEnabled 时,这可能会导致意外行为。
绘制线条开始命令 ICommand 每当开始在 DrawingView 上绘制线条时,就会调用此命令。
取消绘制线命令 ICommand 每当 DrawingView 上的线条绘图被取消时,就会调用此命令。
绘制线段完成命令 ICommand 每当 DrawingView 上的线条绘图完成时,就会调用此命令。 . 请注意,在解除点击或单击后,会触发此作。 启用 MultiLineMode 时,此命令将多次触发。
PointDrawnCommand ICommand 每当 DrawingView 上的点绘图完成时,就会调用此命令。
OnDrawingLineStarted EventHandler<DrawingLineStartedEventArgs> DrawingView 事件在开始绘制线时发生。
绘制线取消时 EventHandler<EventArgs> DrawingView 事件发生于绘制线条取消时。
完成绘制线 EventHandler<DrawingLineCompletedEventArgs> 绘制线条完成时发生 DrawingView 事件。
OnPointDrawn EventHandler<PointDrawnEventArgs> 绘制点时发生 DrawingView 事件。
线条颜色 Color 默认情况下用于在 DrawingView上绘制线条的颜色。
线宽 float 默认情况下用于在 DrawingView上绘制线条的宽度。

DrawingLine

DrawingLine 包含点列表,并允许单独配置每个线条样式。

性能

财产 类型 描述 默认值
线条颜色 Color 用于在 DrawingView上绘制线条的颜色。 Colors.Black
线宽 float 用于在 DrawingView上绘制线条的宽度。 5
分数 ObservableCollection<PointF> 构成线条的 PointF 的集合。 new()
粒度 int 此行的粒度。 最小值为 5。 值越高,线条越平滑,程序执行越慢。 5
绘制时应平滑路径 bool 启用或禁用绘制此线条时的平滑(抗锯齿)功能。 false

自定义 IDrawingLine

有 2 个步骤可将默认 DrawingLine 替换为自定义实现:

  1. 创建实现 IDrawingLine的自定义类:
    public class MyDrawingLine : IDrawingLine
    {
        public ObservableCollection<PointF> Points { get; } = new();
        ...
    }
    
  2. 创建实现 IDrawingLineAdapter的自定义类。
    public class MyDrawingLineAdapter : IDrawingLineAdapter
    {
        public IDrawingLine(MauiDrawingLine mauiDrawingLine)
        {
            return new MyDrawingLine
            {
                Points = mauiDrawingLine.Points,
                ...
            }
        }
    }
    
  3. IDrawingViewHandler中设置自定义 IDrawingLineAdapter
    var myDrawingLineAdapter = new MyDrawingLineAdapter();
    drawingViewHandler.SetDrawingLineAdapter(myDrawingLineAdapter);
    

绘图线开始事件参数

包含最后一个绘图点的事件参数。

性能

财产 类型 描述
PointF 最后一个绘图点。

DrawingLineCompletedEventArgs

包含最后一个绘图线的事件参数。

性能

财产 类型 描述
最后绘图线 IDrawingLine 最后一条绘图线条。

PointDrawnEventArgs

包含最后一个绘图点的事件参数。

性能

财产 类型 描述
PointF 最后一个绘图点。

方法

方法 描述
GetImageStream 检索一个 Stream,其中包含当前在 DrawingView上绘制的 Lines 的图像。
GetImageStream (静态) 检索一个 Stream,其中包含作为参数提供的 IDrawingLine 集合的图像。

例子

可以在 .NET MAUI 社区工具包示例应用程序中找到此功能的示例。

应用程序接口

可以在 .NET MAUI 社区工具包 GitHub 存储库中找到 DrawingView 的源代码。