求助:Xamarin.Forms启用ScrollView后SignaturePad无法使用
I totally get the frustration here—when you drop the SignaturePadView inside a ScrollView, the scroll container intercepts the touch events the signature pad needs to capture strokes properly. Let’s walk through two reliable fixes to get your signature functionality working again:
Approach 1: Custom ScrollView to Ignore SignaturePad Touches (Most Reliable)
Create a custom ScrollView that detects when touches are targeting the SignaturePadView and lets the pad handle those events instead of triggering a scroll.
Step 1: Shared Project Custom ScrollView
using Xamarin.Forms; namespace App4 { public class SignatureFriendlyScrollView : ScrollView { public static readonly BindableProperty IgnoreViewProperty = BindableProperty.Create( nameof(IgnoreView), typeof(View), typeof(SignatureFriendlyScrollView), null); public View IgnoreView { get => (View)GetValue(IgnoreViewProperty); set => SetValue(IgnoreViewProperty, value); } } }
Step 2: Platform-Specific Renderers
Android Renderer (Add to your Android project)
using Android.Content; using App4; using App4.Droid; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; [assembly: ExportRenderer(typeof(SignatureFriendlyScrollView), typeof(SignatureFriendlyScrollViewRenderer))] namespace App4.Droid { public class SignatureFriendlyScrollViewRenderer : ScrollViewRenderer { public SignatureFriendlyScrollViewRenderer(Context context) : base(context) { } public override bool OnInterceptTouchEvent(Android.Views.MotionEvent ev) { var scrollView = (SignatureFriendlyScrollView)Element; if (scrollView.IgnoreView != null) { var ignoreViewRenderer = Platform.GetRenderer(scrollView.IgnoreView); var ignoreViewNative = ignoreViewRenderer.View; var touchX = ev.GetX(); var touchY = ev.GetY(); var viewLocation = new int[2]; ignoreViewNative.GetLocationOnScreen(viewLocation); var viewRect = new Android.Graphics.Rect( viewLocation[0], viewLocation[1], viewLocation[0] + ignoreViewNative.Width, viewLocation[1] + ignoreViewNative.Height); if (viewRect.Contains((int)touchX, (int)touchY)) { // Let the signature pad handle the touch event instead of scrolling return false; } } return base.OnInterceptTouchEvent(ev); } } }
iOS Renderer (Add to your iOS project)
using App4; using App4.iOS; using CoreGraphics; using UIKit; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; [assembly: ExportRenderer(typeof(SignatureFriendlyScrollView), typeof(SignatureFriendlyScrollViewRenderer))] namespace App4.iOS { public class SignatureFriendlyScrollViewRenderer : ScrollViewRenderer { public override bool ShouldBeginPanGesture(UIGestureRecognizer gestureRecognizer) { var scrollView = (SignatureFriendlyScrollView)Element; if (scrollView.IgnoreView != null) { var ignoreViewRenderer = Platform.GetRenderer(scrollView.IgnoreView); var ignoreViewNative = ignoreViewRenderer.NativeView; var touchLocation = gestureRecognizer.LocationInView(ignoreViewNative.Superview); var viewFrame = ignoreViewNative.Frame; if (viewFrame.Contains(touchLocation)) { // Skip scrolling if touch is on the signature pad return false; } } return base.ShouldBeginPanGesture(gestureRecognizer); } } }
Step 3: Update Your XAML
Swap the default ScrollView with your custom one, and link it to your SignaturePadView:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:acr="clr-namespace:Acr.XamForms.SignaturePad;assembly=Acr.XamForms.SignaturePad" xmlns:local="clr-namespace:App4" x:Class="App4.newpage"> <ContentPage.Content> <local:SignatureFriendlyScrollView Orientation="Vertical" IgnoreView="{x:Reference padView}"> <StackLayout> <Button Text="button1"/> <Button Text="button2"/> <Button Text="button3"/> <Button Text="button4"/> <Button Text="button5"/> <Button Text="button6"/> <Button Text="button7"/> <Button Text="button8"/> <acr:SignaturePadView x:Name="padView" HeightRequest="320" WidthRequest="240" BackgroundColor="White" CaptionText="Caption This" CaptionTextColor="Black" ClearText="Clear Me!" ClearTextColor="Red" PromptText="Prompt Here" PromptTextColor="Red" SignatureLineColor="Aqua" StrokeColor="Black" StrokeWidth="2" /> </StackLayout> </local:SignatureFriendlyScrollView> </ContentPage.Content> </ContentPage>
Approach 2: Quick Fix (Simple, Edge Cases Exist)
If you want to avoid custom renderers, temporarily disable scroll when the user interacts with the signature pad:
Add This to Your Code-Behind
using Xamarin.Forms; namespace App4 { public partial class newpage : ContentPage { public newpage() { InitializeComponent(); // Disable scroll when pad is tapped var padTap = new TapGestureRecognizer(); padTap.Tapped += (s, e) => { if (padView.Parent is ScrollView scrollView) { scrollView.IsEnabled = false; } }; padView.GestureRecognizers.Add(padTap); // Re-enable scroll when tapping outside the pad var pageTap = new TapGestureRecognizer(); pageTap.Tapped += (s, e) => { if (padView.Parent is ScrollView scrollView) { scrollView.IsEnabled = true; } }; Content.GestureRecognizers.Add(pageTap); } } }
Note: This works for basic use but has edge cases (e.g., scrolling immediately after signing), so the custom renderer approach is better for production apps.
内容的提问来源于stack exchange,提问作者Manthiram

