【问题标题】:How to fix WebView layout in Xamarin Forms after rotation on iOS (WKWebView)如何在 iOS (WKWebView) 上旋转后修复 Xamarin Forms 中的 WebView 布局
【发布时间】:2021-02-26 10:47:18
【问题描述】:

我在使用 Xamarin Forms 4.8.0.1364 和 ContentPage 的 iOS 应用程序中让 WebView 正确占据整个屏幕时遇到问题。本机控件是 WkWebView,正在 iPhone 12、iOS 14.1 模拟器中进行测试。

另外,当设备转回纵向时,WebView 的大小不对,或者 WebView 中的内容渲染不正确。

XAML 如下(注意相对于屏幕截图的 BackgroundColor):

<?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:viewModel="clr-namespace:MyCompany.MyApp.ViewModels;assembly=MyAssembly"
                x:Class="MyCompany.MyApp.Views.MyWebViewPage"
                BackgroundColor="Green" >
   <ContentPage.BindingContext>
       <viewModel:MyPageViewModel URL="https://login.somepage.com" />
   </ContentPage.BindingContext>
   <ContentPage.Content>
       <Grid BackgroundColor="Blue">
           <WebView x:Name="WebView"
                    BackgroundColor="Black"
                    Source="{Binding URL}"
                    Cookies="{Binding Cookies}">
           </WebView>
       </Grid>
   </ContentPage.Content>
</ContentPage>

注意:我尝试了很多东西,并删除了所有没有影响的东西。已经在 Horizo​​ntalOptions 和 VerticalOptions 上尝试过 FillAndExpand,以及在 Grid 列/行上使用星形和自动调整大小。我删除了与 XAML 没有区别的所有内容。 结果是:

原图(足够好!):

旋转90到横向后:

转回纵向后(内容问题?):

我想看到的是 WebView 占据了整个屏幕,而没有各种颜色可见(绿色、蓝色、黑色),并且在旋转之后,内容应该符合预期。

我也尝试过自定义渲染器。

  public class MyWebViewRenderer : WkWebViewRenderer
  {
  protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);
            if (e.NewElement != null)
            {
                AutoresizingMask = UIViewAutoresizing.FlexibleDimensions;
            }
        }

        public override void LayoutSubviews()
        {
            Bounds = CalculateBounds();
         
            base.LayoutSubviews();
        }

        private CGRect CalculateBounds()
        {
            var screenBounds = UIScreen.MainScreen.Bounds;
            var statusBarHeight = UIApplication.SharedApplication.StatusBarFrame.Height;
            nfloat navBarHeight = 0;

            var uiNavController = Window?.RootViewController as UINavigationController;
            if (uiNavController?.TopViewController != null)
            {
                navBarHeight = uiNavController.NavigationBar.Bounds.Height;
            }

            var adjustedHeight = statusBarHeight + navBarHeight;

            var bounds = new CGRect(screenBounds.X, screenBounds.Y + adjustedHeight,
                screenBounds.Width, screenBounds.Height - adjustedHeight);

            return bounds;
        }
      }

MyWebViewRenderer.LayoutSubviews中计算bounds时的结果,结果为:

纵向模式下的初始页面加载: (我的身高计算是关闭的?)

旋转到横向后(实际上看起来还可以):

旋转回纵向后,高度计算正常,但不知何故发生了偏移:

有什么建议吗?

谢谢

【问题讨论】:

  • 您还可以添加检查以查看它是哪个页面,然后保持该页面的方向固定

标签: ios xamarin.forms layout webview wkwebview


【解决方案1】:

将页面的宽度设置为跟随设备的屏幕宽度,并将VerticalOptions 设置为FillAndExpand。另见this answer

using Foundation;
using WebKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using MyNamespace.iOS.Renderers;

[assembly: ExportRenderer(typeof(WebView), typeof(MyWebViewRenderer))]
namespace MyNamespace.iOS.Renderers
{
  public class MyWebViewRenderer : WkWebViewRenderer
  {
    protected override void OnElementChanged(VisualElementChangedEventArgs e)
    {
        base.OnElementChanged(e);

        if (e.NewElement != null)
        {
            WebView webView = Element as WebView;
            webView.VerticalOptions = LayoutOptions.FillAndExpand;

            //width=device-width sets the width of the page to follow the screen-width of the device
            string jScript = @"" +
                "var meta = document.createElement('meta'); " +
                "meta.setAttribute('name', 'viewport');" +
                "meta.setAttribute('content', 'width=device-width');" +
                "document.getElementsByTagName('head')[0].appendChild(meta);";

            var userScript = new WKUserScript((NSString)jScript, WKUserScriptInjectionTime.AtDocumentEnd, true);
            
            this.Configuration.UserContentController.AddUserScript(userScript);
        }
    }
  }
}

【讨论】:

  • 谢谢 Ben,我试过了,但没有任何区别。您提供的链接建议尝试其他一些事情:视口选项,我尝试过,但到目前为止没有运气。
  • 将设置 VerticalOptions 添加到 FillAndExpand
【解决方案2】:

尝试使用WKUserScript 确保网页以与屏幕尺寸相同的尺寸显示:

public class MyWebViewRenderer : WkWebViewRenderer
{
    protected override void OnElementChanged(VisualElementChangedEventArgs e)
    {
        base.OnElementChanged(e);
        if (e.NewElement != null)
        {
            string jScript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";

            WKUserScript wkUScript = new WKUserScript(new NSString(jScript),WKUserScriptInjectionTime.AtDocumentEnd,true);
            WKUserContentController wkUController = new WKUserContentController();
            wkUController.AddUserScript(wkUScript);
            WKWebViewConfiguration webConfig = new WKWebViewConfiguration();

            this.Configuration.UserContentController = wkUController;
        }
    }   
}

【讨论】:

  • 感谢您的建议,但我试过了,但没有任何作用。
  • 你可以试试AutoresizingMask = UIViewAutoresizing.FlexibleWidth|UIViewAutoresizing.FlexibleHeight; 吗?
  • 我以前使用过,但后来我注意到 FlexibleDimensions 实际上是这样定义的: FlexibleDimensions = FlexibleHeight | FlexibleWidth,所以基本上是一样的东西……
  • 我实际上在 xamarin forms 项目上打开了一个错误问题。这一切似乎都应该起作用,所以我很好奇它是否是 Xamarin.Forms 错误。
  • 你能在这里分享问题链接吗?
猜你喜欢
  • 2017-07-19
  • 2020-04-26
  • 1970-01-01
  • 2019-06-30
  • 1970-01-01
  • 1970-01-01
  • 2021-05-28
  • 2020-03-30
  • 1970-01-01
相关资源
最近更新 更多