MAUI中如何将DrawingView置于ScrollView上方且位置不变以解决绘图延迟问题
MAUI中如何将DrawingView置于ScrollView上方且位置不变以解决绘图延迟问题
我来帮你搞定这个绘图延迟的问题!你遇到的核心问题其实是ScrollView的触摸事件优先级更高——它需要花一小段时间判断你是要滚动页面还是操作子视图,这就导致DrawingView的响应慢了半拍。要解决这个问题,我们需要让DrawingView直接接收触摸事件,同时保持它和原来完全一致的位置(包括ScrollView滚动时也能同步位置)。
下面是具体的解决方案:
方案步骤
- 调整布局层级:把DrawingView从ScrollView内部的Grid中移出来,放到和ScrollView同级的外层Grid里,让它覆盖在ScrollView上方。
- 同步滚动位置:通过绑定ScrollView的滚动偏移量,让DrawingView在ScrollView滚动时自动跟随,保持相对位置不变。
- 禁用ScrollView的滚动干扰:在绘图开始时暂时禁用ScrollView的滚动,结束后恢复,避免触摸冲突。
修改后的完整XAML代码
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="EaaDigitalSigningApp.Views.YeMinorWaiverPage" xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit" xmlns:local="clr-namespace:EaaDigitalSigningApp.Views" Shell.BackgroundColor="{StaticResource EaaBlue}" Title="Waiver Page"> <ContentPage.Resources> <!-- 自定义转换器:用于计算DrawingView的顶部位置 --> <local:AddValueConverter x:Key="AddValueConverter" /> </ContentPage.Resources> <Shell.BackButtonBehavior> <BackButtonBehavior Command="{Binding BackCommand}"/> </Shell.BackButtonBehavior> <!-- 外层Grid,让ScrollView和DrawingView重叠 --> <Grid> <!-- 原有的ScrollView,移除内部的DrawingView --> <ScrollView x:Name="SigningScrollView" HorizontalOptions="CenterAndExpand" WidthRequest="800" IsEnabled="True" > <Grid Padding="20,0,0,0" Margin="0,0,0,0" > <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <!-- 合同内容WebView --> <WebView x:Name="Webview" InputTransparent="True" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" HeightRequest="1825" VerticalOptions="End" HorizontalOptions="FillAndExpand"/> <!-- 移除原来的DrawingView,移到外层Grid --> <Label Grid.Row="2" Grid.Column="0" HorizontalOptions="Start" Text="{Binding parentSignatureText}" x:Name="ParentSignatureText" FontSize="Micro" /> <StackLayout Grid.Row="3" Grid.Column="0" HorizontalOptions="Start"> <Label x:Name="ParentOrGuardiansPrintedName" VerticalTextAlignment="End" Text="{Binding YeWaiver.Signee.FullNameFirstLast}" /> <Label Text="{Binding PrintParentSignatureText}" x:Name="PrintParentSignatureText" FontSize="Micro" /> </StackLayout> <StackLayout Grid.Row="3" Grid.Column="1" HorizontalOptions="Center"> <Label x:Name="MinorParticipantsPrintedName" Text="{Binding YeWaiver.Signee.AssociatedMinorFullNameFirstLast}" /> <Label Text="Minor Participant's Name" IsVisible="{Binding MinorSignatureTextVisible}" x:Name="MinorSignatureText" FontSize="Micro"/> </StackLayout> <StackLayout Grid.Row="3" Grid.Column="2" HorizontalOptions="Center"> <Label x:Name="DateOfSignature" Text="{Binding ContractDate}"/> <Label Text="Date" FontSize="Micro" VerticalOptions="Start" /> </StackLayout> <Button Grid.Row="4" Margin="5" Grid.Column="0" Grid.ColumnSpan="3" FontSize="Large" x:Name="ReviewAndSignDocument" Text="Complete Signing And Next Document" Command="{Binding ReviewAndSignCommand}" BackgroundColor="{StaticResource EaaBlue}" TextColor="White" /> <Button Grid.Row="5" Margin="5" Grid.Column="0" Grid.ColumnSpan="3" FontSize="Large" x:Name="SkipDocument" Text="Skip this Youth >>" IsVisible="{Binding SkipDocumentVisible}" IsEnabled="{Binding SkipDocumentEnabled}" Command="{Binding SkipDocumentCommand}" BackgroundColor="{StaticResource EaaBlue}" TextColor="White" /> </Grid> </ScrollView> <!-- 移到外层的DrawingView,绑定位置同步滚动 --> <toolkit:DrawingView x:Name="drawingView" Margin="20, {Binding Source={x:Reference SigningScrollView}, Path=ScrollY, Converter={StaticResource AddValueConverter}, ConverterParameter=1825}, 0, 0" WidthRequest="780" <!-- 800 - 左边Padding20 --> HeightRequest="200" BackgroundColor="BlanchedAlmond" DrawingLineCompleted="DrawingView_DrawingLineCompleted" DrawingStarted="DrawingView_DrawingStarted" Lines="{Binding Signature}" IsMultiLineModeEnabled="True" ShouldClearOnFinish="False" /> </Grid> </ContentPage>
补充代码实现
- 添加值转换器:创建一个
AddValueConverter类,用于计算DrawingView的顶部位置(ScrollView的滚动偏移量 + WebView的高度):
namespace EaaDigitalSigningApp.Views { public class AddValueConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value is double scrollY && double.TryParse(parameter?.ToString() ?? "0", out double addValue)) { return scrollY + addValue; } return 0; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } }
- 处理绘图事件:在后台代码中添加绘图开始和结束的事件,控制ScrollView的启用状态:
private void DrawingView_DrawingStarted(object sender, EventArgs e) { // 绘图开始时禁用ScrollView,防止滚动干扰 SigningScrollView.IsEnabled = false; } private void DrawingView_DrawingLineCompleted(object sender, CommunityToolkit.Maui.Core.DrawingLineCompletedEventArgs e) { // 绘图结束后恢复ScrollView的滚动功能 SigningScrollView.IsEnabled = true; }
为什么这个方案有效?
- 层级调整:DrawingView现在在ScrollView的视觉层级上方,触摸事件会直接被它接收,跳过了ScrollView的触摸判断延迟。
- 位置同步:通过绑定ScrollView的
ScrollY属性,DrawingView会跟着ScrollView一起滚动,完全保持原来的相对位置。 - 滚动拦截:绘图时禁用ScrollView,避免用户在绘图时不小心触发滚动,提升交互体验。
备注:内容来源于stack exchange,提问作者Justin Sinnard
相关产品推荐
相关产品推荐

