You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:Xamarin.Forms启用ScrollView后SignaturePad无法使用

Fixing SignaturePad Issues Inside ScrollView in Xamarin.Forms

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:30:50