【问题标题】:Xamarin WebView GestureRecognizer not workingXamarin WebView GestureRecognizer 不工作
【发布时间】:2020-06-05 18:08:04
【问题描述】:

我对 Xamarin WebView 上的 GestureRecognizers 有一个尴尬的问题: 尽管此处和 Xamarin 论坛中的任何一些问题/答案的文档都说 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>

到目前为止的替代方案:

  • 同一页面标题上的Same GestureRecognizer:作品
  • 另一个页面的 ListView 上的相同 GestureRecognizer:有效
  • 尝试过 Nuget 包 Vapolia.XamarinGestures,但在 web 视图上也不起作用
  • 尝试将 GestureRecoginzer 放置在 WebView 周围的 StackLayout 上:同样无效。

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

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

另一种方法是将该目标网页添加到“前进”路径上的 webview 历史堆栈中。但不知道该怎么做。

谁有一些提示?

【问题讨论】:

    标签: xamarin webview uigesturerecognizer


    【解决方案1】:

    您可以使用自定义渲染器在特定平台上添加滑动事件。并在 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);
    }
    

    在安卓中

    
    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">
    
    

    【讨论】:

    • 卢卡斯,非常感谢您提供的详细示例 - 到目前为止太忙了,无法查看它。我想避免使用自定义渲染器,但我还有另一个问题
    • 表单中的WebView会阻塞一些GestureRecognizer。所以最好使用Custom Renderer。
    • 我想避免使用自定义渲染器,但现在表单 webview 有另一个问题:我正在将远程 HTML 解析到 Xamarin 表单 webview (webviewsource.Html = "..")其中包括本地保存的图像。在模拟器上它工作正常,但在实际设备上我只看到空框(没有错误?比如丢失图像)。我假设我需要设置“allowingReadAccessToURL”才能加载那些本地图像,因此再次需要自定义视图控制器......或者这也可能只是在渲染器中?
    • 它们是不同的问题,您可以创建一个包含更多详细信息的新主题,以便我们更好地帮助您。如果对你有帮助,别忘了接受我的回答,这将帮助更多有类似问题的人。
    • 是的,我现在使用相应的自定义渲染器(不是控制器)解决了本地图像问题,如下所述:stackoverflow.com/questions/39901982/… 并且现在还将实现您的 GestureRecognizer。
    【解决方案2】:

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

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

    MasterDetailPage.IsGestureEnabled = false;
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多