Xamarin WebView GestureRecognizer 不工作

Xamarin WebView GestureRecognizer not working

Xamarin WebView 上的 GestureRecognizers 有一个尴尬的问题: 尽管此处和 Xamarin 论坛中的一些 questions/answers 文档说 WebView GestureRecognizers 应该都可以工作,但我无法让它触发任何事件。

我的 XAML 代码如下所示:

<StackLayout BackgroundColor="LightGray" >
    <WebView x:Name="webView" VerticalOptions="FillAndExpand" >
        <WebView.GestureRecognizers>
            <SwipeGestureRecognizer Direction="Left" Swiped="onSwiped"/>
        </WebView.GestureRecognizers>
        <WebView.Source>
            <HtmlWebViewSource Html="{Binding HTML}" />
        </WebView.Source>
    </WebView>
</StackLayout>

目前的备选方案:

在 iOS 设备和模拟器上试过了。通常 iOS 应该是这里最简单的部分...

我真正想要实现的是:向左轻扫移动到另一个(编程定义的)网页。 我假设这些手势以某种方式被 webview 吸收以进行常规导航,但我想知道为什么有些示例会说所有手势都适用于 webview。

另一种方法是将该目标网页添加到 "forward" 路径上的 webview 历史堆栈中。但不确定该怎么做。

有人有一些提示吗?

您可以使用 Custom Renderer 在特定平台上添加滑动事件。并在 Forms 中处理它们。

在表格中

创建 CustomWebView

public class CustomWebView : WebView
{
    public event EventHandler SwipeLeft;
    public event EventHandler SwipeRight;

    public void OnSwipeLeft() =>
        SwipeLeft?.Invoke(this, null);

    public void OnSwipeRight() =>
        SwipeRight?.Invoke(this, null);
}

在Android


using Android.Content;
using Android.Views;
using App11;
using App11.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CustomWebView), typeof(MyWebViewRenderer))]
namespace App11.Droid
{
    public class MyWebViewRenderer : WebViewRenderer
    {
        public MyWebViewRenderer(Context context) : base(context)
        {

        }

        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);

            Control.SetOnTouchListener(new MyOnTouchListener((CustomWebView)Element));
        }

    }

    public class MyOnTouchListener : Java.Lang.Object, Android.Views.View.IOnTouchListener
    {
        float oldX;

        float newX;

        CustomWebView myWebView;
        public MyOnTouchListener(CustomWebView webView)
        {
            myWebView = webView;
        }
        public bool OnTouch(Android.Views.View v, MotionEvent e)
        {
            if (e.Action == MotionEventActions.Down)
            {
                oldX = e.GetX(0);
            }
            if (e.Action == MotionEventActions.Up)
            {
                newX = e.GetX();

                if (newX - oldX > 0)
                {
                    myWebView.OnSwipeRight();
                }
                else
                {
                    myWebView.OnSwipeLeft();
                }
            }

            return false;
        }
    }
}

在iOS


using App11;
using App11.iOS;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

using ObjCRuntime;

[assembly: ExportRenderer(typeof(CustomWebView), typeof(MyWebViewRenderer))]
namespace App11.iOS
{
    public class MyWebViewRenderer:WkWebViewRenderer
    {
        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            if(e.NewElement!=null)
            {

                this.BackgroundColor = UIColor.Red;

                UISwipeGestureRecognizer leftgestureRecognizer = new UISwipeGestureRecognizer(this,new Selector("SwipeEvent:"));

                leftgestureRecognizer.Direction = UISwipeGestureRecognizerDirection.Left;

                UISwipeGestureRecognizer rightgestureRecognizer = new UISwipeGestureRecognizer(this, new Selector("SwipeEvent:"));
                rightgestureRecognizer.Direction = UISwipeGestureRecognizerDirection.Right;

                leftgestureRecognizer.Delegate = new MyWebViewDelegate();
                rightgestureRecognizer.Delegate = new MyWebViewDelegate();

                this.AddGestureRecognizer(leftgestureRecognizer);
                this.AddGestureRecognizer(rightgestureRecognizer);
            }


        }

        [Export("SwipeEvent:")]
        void SwipeEvent(UISwipeGestureRecognizer recognizer)
        {
            var webview = Element as CustomWebView;

            if(recognizer.Direction == UISwipeGestureRecognizerDirection.Left)
            {
                webview.OnSwipeLeft();
            }
            else if(recognizer.Direction == UISwipeGestureRecognizerDirection.Right)
            {
                webview.OnSwipeRight();
            }
        }


    }

    public class MyWebViewDelegate: UIGestureRecognizerDelegate
    {
        public override bool ShouldRecognizeSimultaneously(UIGestureRecognizer gestureRecognizer, UIGestureRecognizer otherGestureRecognizer)
        {
            return false;
        }
    }


}

现在你只需要像

一样使用它
<local:CustomWebView x:Name="browser"
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" 
           SwipeLeft="browser_SwipeLeft"
           SwipeRight="browser_SwipeRight">

还有一个额外的技巧让它最终起作用。由于我的 Xamarin MasterDetailPage 设置,上述所有(正确的)解决方案都被忽略了。

这是在捕获所有水平滑动,而不是将它们传递给 HybridWebView。

MasterDetailPage.IsGestureEnabled = false;

终于修复了它并在我的 WebView 中启用了滑动手势。