Xamarin Forms中ScrollView内SkiaSharp画布绘图时仍滚动的问题
问题:Android平台Xamarin Forms中ScrollView内SkiaSharp绘图区域滚动干扰问题
在Android平台的Xamarin Forms项目里,我将一个简易SkiaSharp手指绘图区域放置在ScrollView底部,但绘图仅能正常工作很短时间,一旦开始绘图页面就会发生滚动,导致绘制的线条消失,无法完成绘图操作,希望找到解决方法。
相关XAML代码
<ContentPage.Content> <ScrollView> <StackLayout> <Label x:Name="WeatherConditionLabel" Text="Weather/Condition" FontSize="20" FontAttributes="Bold"/> <Grid> <Label Text="Day/Night:" FontSize="Medium" VerticalOptions="Center" /> </Grid> <Switch HorizontalOptions="Start" IsToggled="false" Scale="1.8" Margin="20"/> <Grid Margin="20,10,10,20"> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.40*" /> <ColumnDefinition Width="0.15*" /> <ColumnDefinition Width="0.25*" /> <ColumnDefinition Width="0.20*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Label Text="Raining:" FontSize="Medium" VerticalOptions="Center" /> <CheckBox GridColumn="1" Color="Turquoise" VerticalOptions="Center" Scale="1.6" x:Name="rainingCheck"/> <Label GridColumn="2" Text="Snowing:" FontSize="Medium" VerticalOptions="Center" /> <CheckBox GridColumn="3" Color="Turquoise" VerticalOptions="Center" Scale="1.6" x:Name="snowingCheck"/> <Label GridRow="1" Text="Fog/Mist:" FontSize="Medium" VerticalOptions="Center" /> <CheckBox GridRow="1" GridColumn="1" Color="Turquoise" Scale="1.6" VerticalOptions="Center" x:Name="FogMistCheck"/> </Grid> <Label x:Name="VehicleConditionImageLabel" Text="Vehicle Condition" FontSize="20" FontAttributes="Bold"/> <xct:DrawingView x:Name="damageDrawing" HeightRequest="200" DefaultLineColor="green" ClearOnFinish="False" ></xct:DrawingView> <Grid Margin="5,5,5,5"> <Grid.ColumnDefinitions> <ColumnDefinition Width="35*" /> <ColumnDefinition Width="30*" /> <ColumnDefinition Width="35*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="40" /> </Grid.RowDefinitions> <Button x:Name="greenBtn" VerticalOptions="Center" BackgroundColor="Green" /> <Button GridColumn="1" x:Name="amberBtn" VerticalOptions="Center" BackgroundColor="Yellow" /> <Button GridColumn="2" x:Name="rebBtn" VerticalOptions="Center" BackgroundColor="red" Clicked="redBtnPressed" /> </Grid> <Grid BackgroundColor="White"> <skia:SKCanvasView x:Name="canvasView" HeightRequest="200" PaintSurface="OnCanvasViewPaintSurface" /> <Grid.Effects> <tt:TouchEffect Capture="True" TouchAction="OnTouchEffectAction" /> </Grid.Effects> </Grid> </StackLayout> </ScrollView> </ContentPage.Content>
解决方法
方法1:拦截触摸事件,阻止ScrollView响应滚动
在触摸绘图区域时,让触摸事件优先被绘图区域处理,不传递给ScrollView。修改OnTouchEffectAction方法,标记事件已处理:
void OnTouchEffectAction(object sender, TouchActionEventArgs e) { // 执行你的绘图逻辑(比如记录触摸点、绘制线条等) // 阻止事件继续传递给ScrollView,避免触发滚动 e.Handled = true; }
方法2:临时禁用ScrollView滚动
在开始绘图时禁用ScrollView,结束后恢复:
- 先给ScrollView命名:
<ScrollView x:Name="MainScrollView"> <!-- 原有内容 --> </ScrollView>
- 修改触摸事件处理代码:
void OnTouchEffectAction(object sender, TouchActionEventArgs e) { switch (e.Type) { case TouchActionType.Pressed: // 开始绘图,禁用ScrollView滚动 MainScrollView.IsEnabled = false; // 绘图逻辑... break; case TouchActionType.Released: case TouchActionType.Cancelled: // 绘图结束,恢复ScrollView滚动 MainScrollView.IsEnabled = true; // 绘图逻辑... break; case TouchActionType.Moved: // 处理移动绘图逻辑... break; } }
方法3:自定义ScrollView渲染器(Android端)
如果前两种方法效果不佳,可通过自定义渲染器在Android层面拦截滚动:
- 创建自定义ScrollView类:
public class CustomScrollView : ScrollView { public bool IsScrollEnabled { get; set; } = true; }
- 在Android项目中添加渲染器:
[assembly: ExportRenderer(typeof(CustomScrollView), typeof(CustomScrollViewRenderer))] namespace YourAppNamespace.Droid.Renderers { public class CustomScrollViewRenderer : ScrollViewRenderer { public CustomScrollViewRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs<ScrollView> e) { base.OnElementChanged(e); if (e.NewElement is CustomScrollView customScrollView) { customScrollView.PropertyChanged += (s, args) => { if (args.PropertyName == nameof(CustomScrollView.IsScrollEnabled)) { Enabled = customScrollView.IsScrollEnabled; } }; } } // 可选:拦截触摸事件,判断是否在绘图区域内再决定是否允许滚动 public override bool OnInterceptTouchEvent(MotionEvent ev) { if (Element is CustomScrollView customScrollView && !customScrollView.IsScrollEnabled) { return false; // 不拦截,让子控件处理 } return base.OnInterceptTouchEvent(ev); } } }
- 在XAML中替换原有ScrollView:
<local:CustomScrollView x:Name="MainScrollView"> <!-- 原有内容 --> </local:CustomScrollView>
- 在触摸事件中控制滚动状态:
void OnTouchEffectAction(object sender, TouchActionEventArgs e) { switch (e.Type) { case TouchActionType.Pressed: MainScrollView.IsScrollEnabled = false; // 绘图逻辑... break; case TouchActionType.Released: case TouchActionType.Cancelled: MainScrollView.IsScrollEnabled = true; // 绘图逻辑... break; } }
内容的提问来源于stack exchange,提问作者TryingAgain
相关产品推荐
相关产品推荐

