C# WebView中的WebGL在UNO版本中不起作用,但在Xamarin版本中起作用
目前,我正在开发一个移动应用程序,它使用UNO平台auf。为了显示3D模型,我使用WebView控件和一些ThreeJSJavaScript代码。这对UWP和WASM都非常有效。WASM构建中WebView的解决方法也可以在StackOverflow上找到。 然而,Android构建让我头疼:HTML页面加载,调试输出显示WebGL脚本部分正在执行,但用户界面没有显示任何内容 我已经确定在我看来使用了正确的WebView控件。此外,我还测试了Chrome上的另一个WebView,它是我从Play Store 74.x.x.x版下载的。WebView的HTTP用户代理是正确的,因此WebView是根据Android系统的开发者设置使用的。 在活动和AndroidManifest文件中,Hardware Acceleration都设置为TRUE 我还用一个Android XAML应用程序做了一个非常简单的测试,它是开箱即用的。立方体几乎立即显示 MainView.xamlC# WebView中的WebGL在UNO版本中不起作用,但在Xamarin版本中起作用,c#,android,xamarin,android-webview,uno-platform,C#,Android,Xamarin,Android Webview,Uno Platform,目前,我正在开发一个移动应用程序,它使用UNO平台auf。为了显示3D模型,我使用WebView控件和一些ThreeJSJavaScript代码。这对UWP和WASM都非常有效。WASM构建中WebView的解决方法也可以在StackOverflow上找到。 然而,Android构建让我头疼:HTML页面加载,调试输出显示WebGL脚本部分正在执行,但用户界面没有显示任何内容 我已经确定在我看来使用了正确的WebView控件。此外,我还测试了Chrome上的另一个WebView,它是我从Play
<?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:local="clr-namespace:WebViewTestAndroid"
x:Class="WebViewTestAndroid.MainPage">
<Grid>
<WebView Source="https://threejs.org/examples/?q=cube#webgl_geometry_cube" />
</Grid>
</ContentPage>
这是UNO主页不起作用的一个例子。页面正在加载,但未显示3D多维数据集
MainPage.xaml
<Page
x:Class="UnoWebViewTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UnoWebViewTest"
xmlns:ios="http://uno.ui/ios"
xmlns:android="http://uno.ui/android"
xmlns:xamarin="http://uno.ui/xamarin"
xmlns:wasm="http://uno.ui/wasm"
mc:Ignorable="d ios android xamarin wasm"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<android:WebView Source="https://threejs.org/examples/?q=cube#webgl_geometry_cube" />
</Grid>
</Page>
我比较了清单文件,但到目前为止,我没有得出结论,我可以进一步调查。
我希望UNO使用的是本机Android WebView控件,但可能缺少一些设置,或者它甚至不是同一个控件?这个问题让我发疯,所以我花了一整天的时间下载完整的Xamarin和UNO源代码,并从头调试所有东西 首先,UNO将WebView控件的HardwareAcceleration设置为false。 第二,缺少的线索是这一行:
view.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent);
问题是,实际上不可能从外部进行设置,因此我们创建了一个继承自Android.Webkit.WebView的新类:
public partial class MyCustomWebView : Android.Webkit.WebView
{
protected MyCustomWebView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
MakeSettings();
}
public MyCustomWebView(Context context) : base(context)
{
MakeSettings();
}
public MyCustomWebView(Context context, IAttributeSet attrs) : base(context, attrs)
{
MakeSettings();
}
public MyCustomWebView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
{
MakeSettings();
}
public MyCustomWebView(Context context, IAttributeSet attrs, int defStyleAttr, bool privateBrowsing) : base(context, attrs, defStyleAttr, privateBrowsing)
{
MakeSettings();
}
public MyCustomWebView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
{
MakeSettings();
}
private void MakeSettings()
{
SetLayerType(LayerType.Hardware, null);
ForceHasOverlappingRendering(true);
SetWebViewClient(new MyCustomWebViewClient(this));
SetWebChromeClient(new WebChromeClient());
Settings.AllowFileAccessFromFileURLs = true;
Settings.AllowUniversalAccessFromFileURLs = true;
Settings.JavaScriptEnabled = true;
Settings.DomStorageEnabled = true;
Settings.AllowFileAccess = true;
Settings.CacheMode = CacheModes.NoCache;
Settings.MediaPlaybackRequiresUserGesture = false;
Settings.SetPluginState(WebSettings.PluginState.On);
}
public string HtmlContent
{
get { return string.Empty; }
set { LoadUrl(value); }
}
}
public class MyCustomWebViewClient : Android.Webkit.WebViewClient
{
public MyCustomWebViewClient(WebView view)
{
var test = view.IsHardwareAccelerated;
view.SetLayerType(LayerType.Hardware, null);
}
public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
{
view.LoadUrl(request.Url.ToString());
return true;
}
public override void OnPageStarted(WebView view, string url, Bitmap favicon)
{
// The native webview control requires to have LayoutParameters to function properly.
view.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent);
base.OnPageStarted(view, url, favicon);
}
}
在XAML中使用此自定义控件可以在WebView中使用硬件加速的WebGL:
<android:MyCustomWebView HtmlContent="https://threejs.org/examples/?q=cube#webgl_geometry_cube" />
这个问题开始让我发疯,所以我花了一整天的时间下载完整的Xamarin和UNO源代码,并从头调试所有的东西 首先,UNO将WebView控件的HardwareAcceleration设置为false。 第二,缺少的线索是这一行:
view.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent);
问题是,实际上不可能从外部进行设置,因此我们创建了一个继承自Android.Webkit.WebView的新类:
public partial class MyCustomWebView : Android.Webkit.WebView
{
protected MyCustomWebView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
MakeSettings();
}
public MyCustomWebView(Context context) : base(context)
{
MakeSettings();
}
public MyCustomWebView(Context context, IAttributeSet attrs) : base(context, attrs)
{
MakeSettings();
}
public MyCustomWebView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
{
MakeSettings();
}
public MyCustomWebView(Context context, IAttributeSet attrs, int defStyleAttr, bool privateBrowsing) : base(context, attrs, defStyleAttr, privateBrowsing)
{
MakeSettings();
}
public MyCustomWebView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
{
MakeSettings();
}
private void MakeSettings()
{
SetLayerType(LayerType.Hardware, null);
ForceHasOverlappingRendering(true);
SetWebViewClient(new MyCustomWebViewClient(this));
SetWebChromeClient(new WebChromeClient());
Settings.AllowFileAccessFromFileURLs = true;
Settings.AllowUniversalAccessFromFileURLs = true;
Settings.JavaScriptEnabled = true;
Settings.DomStorageEnabled = true;
Settings.AllowFileAccess = true;
Settings.CacheMode = CacheModes.NoCache;
Settings.MediaPlaybackRequiresUserGesture = false;
Settings.SetPluginState(WebSettings.PluginState.On);
}
public string HtmlContent
{
get { return string.Empty; }
set { LoadUrl(value); }
}
}
public class MyCustomWebViewClient : Android.Webkit.WebViewClient
{
public MyCustomWebViewClient(WebView view)
{
var test = view.IsHardwareAccelerated;
view.SetLayerType(LayerType.Hardware, null);
}
public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
{
view.LoadUrl(request.Url.ToString());
return true;
}
public override void OnPageStarted(WebView view, string url, Bitmap favicon)
{
// The native webview control requires to have LayoutParameters to function properly.
view.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent);
base.OnPageStarted(view, url, favicon);
}
}
在XAML中使用此自定义控件可以在WebView中使用硬件加速的WebGL:
<android:MyCustomWebView HtmlContent="https://threejs.org/examples/?q=cube#webgl_geometry_cube" />
事实上,这是由于Uno的WebView禁用了硬件加速。除此之外,Uno和Xamarin.Forms也同样在引擎盖下使用Android.WebKit.WebView 可以使用附加属性轻松地在Uno中重新启用硬件加速:
public static class WebViewHardware
{
public static bool GetIsEnabled(WebView obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
}
public static void SetIsEnabled(WebView obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}
// Using a DependencyProperty as the backing store for IsEnabled. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(WebViewHardware), new PropertyMetadata(false, OnIsEnabledChanged));
private static void OnIsEnabledChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
var webView = (WebView)dependencyObject;
var isEnabled = (bool)args.NewValue;
#if __ANDROID__
webView.Loaded += OnLoaded;
void OnLoaded(object sender, RoutedEventArgs e)
{
webView.Loaded -= OnLoaded;
var layerType = isEnabled ? Android.Views.LayerType.Hardware : Android.Views.LayerType.Software;
webView.SetLayerType(layerType, null);
}
#endif
}
这可以在XAML中使用,如下所示:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<WebView Source="https://threejs.org/examples/?q=cube#webgl_geometry_cube" local:WebViewHardware.IsEnabled="True"/>
</Grid>
事实上,这是由于Uno的WebView禁用了硬件加速。除此之外,Uno和Xamarin.Forms也同样在引擎盖下使用Android.WebKit.WebView 可以使用附加属性轻松地在Uno中重新启用硬件加速:
public static class WebViewHardware
{
public static bool GetIsEnabled(WebView obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
}
public static void SetIsEnabled(WebView obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}
// Using a DependencyProperty as the backing store for IsEnabled. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(WebViewHardware), new PropertyMetadata(false, OnIsEnabledChanged));
private static void OnIsEnabledChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
var webView = (WebView)dependencyObject;
var isEnabled = (bool)args.NewValue;
#if __ANDROID__
webView.Loaded += OnLoaded;
void OnLoaded(object sender, RoutedEventArgs e)
{
webView.Loaded -= OnLoaded;
var layerType = isEnabled ? Android.Views.LayerType.Hardware : Android.Views.LayerType.Software;
webView.SetLayerType(layerType, null);
}
#endif
}
这可以在XAML中使用,如下所示:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<WebView Source="https://threejs.org/examples/?q=cube#webgl_geometry_cube" local:WebViewHardware.IsEnabled="True"/>
</Grid>
未显示WebGL内容的Uno回购中的问题:未显示WebGL内容的Uno回购中的问题: