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>
目前的备选方案:
- 同一页面标题上的相同 GestureRecognizer:有效
- 另一个页面的 ListView 上的相同 GestureRecognizer:有效
- 尝试过 Nuget 包 Vapolia.XamarinGestures,它在 webview 上也不起作用
- 尝试将 GestureRecoginzer 放在 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 中启用了滑动手势。
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>
目前的备选方案:
- 同一页面标题上的相同 GestureRecognizer:有效
- 另一个页面的 ListView 上的相同 GestureRecognizer:有效
- 尝试过 Nuget 包 Vapolia.XamarinGestures,它在 webview 上也不起作用
- 尝试将 GestureRecoginzer 放在 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 中启用了滑动手势。