如何解决UWP项目中WebView2切换可见性时的闪烁问题?
UWP中WebView2切换可见性时的闪烁问题解决建议
在UWP项目中,某页面包含多个子页面,其中一个子页面使用Microsoft.UI.Xaml.Controls.WebView2控件打开一次链接(如www.bing.com)。完成网页导航后切换到其他子页面再返回时,WebView2内容会出现从黑屏到网页内容的闪烁,该问题由WebView2可见性变化导致。
现有代码
XAML
<Page x:Class="WebView2FlickerDemo.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WebView2FlickerDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:controls="using:Microsoft.UI.Xaml.Controls" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid> <Button Click="Button_Click" Width="200" Height="100"></Button> <controls:WebView2 x:Name="WebView2" Height="567.55" Width="792" Margin="200 150 0 0" Visibility="Visible"/> <Grid x:Name="myGrid" Background="Blue" Height="567.55" Width="792" Margin="200 150 0 0" Visibility="Collapsed"></Grid> </Grid> </Page>
C#
public MainPage() { this.InitializeComponent(); StartWebView2(); } private async void StartWebView2() { try { await WebView2.EnsureCoreWebView2Async(); WebView2.CoreWebView2.Navigate("https://www.bing.com"); } catch (Exception ex) { } } private void Button_Click(object sender, RoutedEventArgs e) { if (WebView2.Visibility == Visibility.Visible) { WebView2.Visibility = Visibility.Collapsed; myGrid.Visibility = Visibility.Visible; } else if (WebView2.Visibility == Visibility.Collapsed) { WebView2.Visibility = Visibility.Visible; myGrid.Visibility = Visibility.Collapsed; } }
解决建议
方案1:用Opacity+IsHitTestVisible替代Visibility控制显示
直接设置Visibility=Collapsed会销毁WebView2的内部渲染状态,切换回来时需重新初始化导致闪烁。改用透明度和交互性控制,保持控件始终处于加载状态:
修改XAML初始状态:
<controls:WebView2 x:Name="WebView2" Height="567.55" Width="792" Margin="200 150 0 0" Opacity="1" IsHitTestVisible="True"/> <Grid x:Name="myGrid" Background="Blue" Height="567.55" Width="792" Margin="200 150 0 0" Opacity="0" IsHitTestVisible="False"/>
修改C#点击事件:
private void Button_Click(object sender, RoutedEventArgs e) { if (WebView2.Opacity == 1) { WebView2.Opacity = 0; WebView2.IsHitTestVisible = false; myGrid.Opacity = 1; myGrid.IsHitTestVisible = true; } else { WebView2.Opacity = 1; WebView2.IsHitTestVisible = true; myGrid.Opacity = 0; myGrid.IsHitTestVisible = false; } }
方案2:通过Canvas.ZIndex控制层级覆盖
保持WebView2始终可见,调整层级让其他子页面覆盖在它上方,避免控件进入隐藏状态:
修改XAML:
<controls:WebView2 x:Name="WebView2" Height="567.55" Width="792" Margin="200 150 0 0" Canvas.ZIndex="0"/> <Grid x:Name="myGrid" Background="Blue" Height="567.55" Width="792" Margin="200 150 0 0" Canvas.ZIndex="1"/>
修改C#点击事件:
private void Button_Click(object sender, RoutedEventArgs e) { if (WebView2.Canvas.ZIndex == 0) { WebView2.Canvas.ZIndex = 2; myGrid.Canvas.ZIndex = 1; } else { WebView2.Canvas.ZIndex = 0; myGrid.Canvas.ZIndex = 1; } }
方案3:缓存WebView2快照过渡
首次加载完成后截取WebView2内容快照,切换回来时先显示快照,待控件完全渲染后再切换回原控件:
在C#中添加快照逻辑:
private WriteableBitmap _webViewSnapshot; private async void StartWebView2() { try { await WebView2.EnsureCoreWebView2Async(); WebView2.CoreWebView2.Navigate("https://www.bing.com"); WebView2.CoreWebView2.NavigationCompleted += CoreWebView2_NavigationCompleted; } catch (Exception ex) { } } private async void CoreWebView2_NavigationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs e) { if (e.IsSuccess) { var renderTargetBitmap = new RenderTargetBitmap(); await renderTargetBitmap.RenderAsync(WebView2); _webViewSnapshot = new WriteableBitmap(renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight); using (var stream = _webViewSnapshot.PixelBuffer.AsStream()) { await renderTargetBitmap.PixelBuffer.CopyToAsync(stream); } } }
XAML新增快照显示控件:
<Image x:Name="WebViewSnapshotImg" Height="567.55" Width="792" Margin="200 150 0 0" Visibility="Collapsed"/>
修改点击事件:
private void Button_Click(object sender, RoutedEventArgs e) { if (WebView2.Visibility == Visibility.Visible) { WebView2.Visibility = Visibility.Collapsed; myGrid.Visibility = Visibility.Visible; } else { WebViewSnapshotImg.Source = _webViewSnapshot; WebViewSnapshotImg.Visibility = Visibility.Visible; myGrid.Visibility = Visibility.Collapsed; Task.Delay(100).ContinueWith(t => { Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { WebViewSnapshotImg.Visibility = Visibility.Collapsed; WebView2.Visibility = Visibility.Visible; }); }); } }
内容的提问来源于stack exchange,提问作者Tom Xue
相关产品推荐
相关产品推荐

