Skip to main content
 首页 » 编程设计

c#之WebView 中的 WebGL 在 UNO 构建中不起作用,但在 Xamarin 构建中起作用

2024年02月25日33over140

目前我正在开发一个使用 UNO 平台的移动应用程序。为了显示 3D 模型,我使用了 WebView 控件和一些 ThreeJS JavaScript 代码。这适用于 UWP 和 WASM。 (WASM 构建中 WebView 的解决方法也可以在 StackOverflow 上找到 here。) 然而,Android 构建让我很头疼:加载 HTML 页面,调试输出显示正在执行 WebGL 脚本部分,但用户界面没有显示任何内容。

我已经确定(在我看来)使用了正确的 WebView 控件。此外,我使用从“Play Store”(版本 74.x.x.x)下载的“Chrome”的替代 WebView 进行了测试。 WebView的HTTP user agent是正确的,所以根据Android系统的开发者设置来使用WebView。 硬件加速在 Activity 和 AndroidManifest 文件中都设置为“TRUE”。

我还使用开箱即用的“Android-XAML-App”进行了非常简单的测试。立方体几乎立即显示出来。

主视图.xaml

<?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 立方体。

主页.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> 

我比较了 list 文件,但到目前为止我还没有得出可以进一步调查的结论。 我希望 UNO 使用 native Android WebView 控件,但可能缺少某些设置或者它甚至不是相同的控件?

请您参考如下方法:

事实上,这是由于 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>