Xamarin.Forms WebView


WebView是用於在您的應用程序中顯示Web和HTML內容的視圖。

內容

WebView支持以下類型的內容:

  • HTML和CSS網站– WebView完全支持使用HTML和CSS編寫的網站,包括JavaScript支持。
  • 文檔–由於WebView是在每個平台上使用本機組件實現的,因此WebView能夠顯示在每個平台上可見的文檔,這意味着PDF文件可在iOS和Android上使用。
  • HTML字符串– WebView可以顯示內存中的HTML字符串。
  • 本地文件– WebView可以顯示應用程序中嵌入的上述任何內容類型。

注:Windows上的WebView不支持Silverlight,Flash或任何ActiveX控件,即使該平台上的Internet Explorer支持它們也是如此

示例:WorkingWithWebview

WebSites
要顯示來自互聯網的網站,請將WebView的Source屬性設置為字符串URL:

var browser = new WebView
{
  Source = "http://xamarin.com"
};

注:網址必須使用指定的協議完整構成(即,其前面必須帶有“ http://”或“ https://”)

要想打開外部的網頁,則可以:

 var openUrl = new Button
            {
                Text = "Open location using built-in Web Browser app"
            };
            openUrl.Clicked += async (sender, e) =>
            {
                await Launcher.OpenAsync("http://xamarin.com/evolve");
            };

或者 創建一個Label,其內容是html文本(包含一個<a href...>)

 

iOS和ATS(App Transport Security

從版本9開始,iOS默認將僅允許您的應用程序與實現最佳實踐安全性的服務器通信。 必須在Info.plist中設置值才能啟用與不安全服務器的通信。

注:如果您的應用程序需要連接到不安全的網站,則應始終使用NSExceptionDomains作為例外輸入域,而不是使用NSAllowsArbitraryLoads完全關閉ATS,NSAllowsArbitraryLoads僅應在極端緊急情況下使用。

更多查看

HTML字符串

如果要呈現在代碼中 動態定義的HTML字符串,則需要創建HtmlWebViewSource的實例:

var browser = new WebView();
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = @"<html><body>
  <h1>Xamarin.Forms</h1>
  <p>Welcome to WebView.</p>
  </body></html>";
browser.Source = htmlSource;

在上面的代碼中,@用於將HTML標記為字符串文字,這意味着所有常用的轉義字符都將被忽略。

注:可能需要設置WebView的WidthRequest和HeightRequest屬性以查看HTML內容,具體取決於WebView是其子級的布局。 例如,這在StackLayout中是必需的。

本地HTML內容

WebView可以顯示應用程序中嵌入的HTML,CSS和Javascript中的內容。 例如:

<html>
  <head>
    <title>Xamarin Forms</title>
  </head>
  <body>
    <h1>Xamrin.Forms</h1>
    <p>This is an iOS web page.</p>
    <img src="XamarinLogo.png" />
  </body>
</html>
html,body {
  margin:0;
  padding:10;
}
body,p,h1 {
  font-family: Chalkduster;
}

請注意,上述CSS中指定的字體將需要針對每個平台進行自定義,因為並非每個平台都具有相同的字體。

要使用WebView顯示本地內容,您需要像打開其他文件一樣打開HTML文件,然后將內容作為字符串加載到HtmlWebViewSource的Html屬性中。 有關打開文件的更多信息,請參見使用文件

 

盡管已經加載了第一頁,但是WebView不了解HTML的來源,在處理引用本地資源的頁面時,這是一個問題。 當本地頁面彼此鏈接,頁面使用單獨的JavaScript文件或頁面鏈接到CSS樣式表時,可能發生這種情況的示例。

為了解決這個問題,您需要告訴WebView在文件系統上哪里可以找到文件,通過在WebView使用的HtmlWebViewSource上設置BaseUrl屬性來執行此操作

由於每個操作系統上的文件系統都不相同,因此您需要確定每個平台上的URL,Xamarin.Forms公開了DependencyService以在運行時在每個平台上解決依賴關系。

要使用DependencyService,首先定義一個可以在每個平台上實現的接口:

public interface IBaseUrl { string Get(); }

請注意,除非在每個平台上都實現了該界面,否則該應用程序將無法運行。 在公共項目中,請確保您記得使用DependencyService設置BaseUrl:

var source = new HtmlWebViewSource();
source.BaseUrl = DependencyService.Get<IBaseUrl>().Get();

然后必須提供每個平台的接口實現。

iOS
在iOS上,Web內容應通過構建操作BundleResource位於項目的根目錄或Resources目錄中,如下所示:

 

 應將BaseUrl設置為Main bundle的路徑:

[assembly: Dependency (typeof (BaseUrl_iOS))]
namespace WorkingWithWebview.iOS
{
  public class BaseUrl_iOS : IBaseUrl
  {
    public string Get()
    {
      return NSBundle.MainBundle.BundlePath;
    }
  }
}

Android
在Android上,通過構建操作AndroidAsset將HTML,CSS和圖像放在Assets文件夾中,如下所示:

文件屬性中,生成操作=AndroidAsset

 

 在Android上,應將BaseUrl設置為“ file:/// android_asset /”:

[assembly: Dependency (typeof(BaseUrl_Android))]
namespace WorkingWithWebview.Android
{
  public class BaseUrl_Android : IBaseUrl
  {
    public string Get()
    {
      return "file:///android_asset/";
    }
  }
}

在Android上,還可以通過MainActivity.Instance屬性公開的當前Android上下文訪問Assets文件夾中的文件:

var assetManager = MainActivity.Instance.Assets;
using (var streamReader = new StreamReader (assetManager.Open ("local.html")))
{
  var html = streamReader.ReadToEnd ();
}

WebView支持通過幾種可用的方法和屬性進行導航:

  • GoForward()–如果CanGoForward為true,則調用GoForward會向前導航到下一個訪問的頁面。
  • GoBack()–如果CanGoBack為true,則調用GoBack將導航到最后訪問的頁面。
  • CanGoBack –如果存在要導航回的頁面,則為true;如果瀏覽器位於起始URL,則為false。
  • CanGoForward –如果用戶向后導航並且可以前進到已經訪問過的頁面,則為true。

在頁面內,WebView不支持多點觸摸手勢,重要的是要確保內容經過移動優化,並且無需縮放即可顯示。

應用程序通常在WebView而非設備的瀏覽器中顯示鏈接,在這些情況下,允許常規導航很有用,但是當用戶在開始鏈接上時回擊時,應用程序應返回到常規應用程序視圖。

使用內置的導航方法和屬性來啟用此方案。

示例:WebViewSample

首先創建瀏覽器視圖的頁面:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="WebViewSample.InAppBrowserXaml"
             Title="Browser">
    <StackLayout Margin="20">
        <StackLayout Orientation="Horizontal">
            <Button Text="Back" HorizontalOptions="StartAndExpand" Clicked="OnBackButtonClicked" />
            <Button Text="Forward" HorizontalOptions="EndAndExpand" Clicked="OnForwardButtonClicked" />
        </StackLayout>
        <!-- WebView needs to be given height and width request within layouts to render. -->
        <WebView x:Name="webView" WidthRequest="1000" HeightRequest="1000" />
    </StackLayout>
</ContentPage>
View Code
public partial class InAppBrowserXaml : ContentPage
{
    public InAppBrowserXaml(string URL)
    {
        InitializeComponent();
        webView.Source = URL;
    }

    async void OnBackButtonClicked(object sender, EventArgs e)
    {
        if (webView.CanGoBack)
        {
            webView.GoBack();
        }
        else
        {
            await Navigation.PopAsync();
        }
    }

    void OnForwardButtonClicked(object sender, EventArgs e)
    {
        if (webView.CanGoForward)
        {
            webView.GoForward();
        }
    }
}

Events

WebView引發以下事件以幫助您響應狀態變化:

  • Navigating – WebView開始加載新頁面時引發的事件。
  • Navigated–加載頁面且導航停止時引發的事件。
  • ReloadRequested –請求重新加載當前內容時引發的事件。

Navigating事件附帶的WebNavigatingEventArgs對象具有四個屬性:

  • Cancel–指示是否取消導航。
  • NavigationEvent –引發的導航事件。
  • Source–執行導航的元素。
  • url-導航目標。

Navigated事件隨附的WebNavigatedEventArgs對象具有四個屬性:

  • NavigationEvent –引發的導航事件。
  • Result–使用WebNavigationResult枚舉成員描述導航的結果。有效值為取消,失敗,成功和超時。
  • Source–執行導航的元素。
  • url-導航目標。

如果您期望使用加載時間較長的網頁,請考慮使用 Navigating and Navigated 事件來實現狀態指示器。例如:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="WebViewSample.LoadingLabelXaml"
             Title="Loading Demo">
    <StackLayout>
        <!--Loading label should not render by default.-->
        <Label x:Name="labelLoading" Text="Loading..." IsVisible="false" />
        <WebView HeightRequest="1000" WidthRequest="1000" Source="http://www.xamarin.com" Navigated="webviewNavigated" Navigating="webviewNavigating" />
    </StackLayout>
</ContentPage>
void webviewNavigating(object sender, WebNavigatingEventArgs e)
{
    labelLoading.IsVisible = true;
}

void webviewNavigated(object sender, WebNavigatedEventArgs e)
{
    labelLoading.IsVisible = false;
}

重新加載內容

WebView有一個Reload方法,可用於重新加載當前內容:

var webView = new WebView();
...
webView.Reload();

調用Reload方法時,將觸發ReloadRequested事件,指示已請求重新加載當前內容。

性能

現在流行的Web瀏覽器采用了硬件加速渲染和JavaScript編譯等技術。 在iOS上,默認情況下,Xamarin.Forms WebView由UIWebView類實現,而這些技術中的許多技術在此實現中不可用。 但是,應用程序可以選擇使用iOS WkWebView類來實現Xamarin.Forms WebView,后者支持更快的瀏覽。 這可以通過將以下代碼添加到該應用程序的iOS平台項目中的AssemblyInfo.cs文件中來實現:

// Opt-in to using WkWebView instead of UIWebView.
[assembly: ExportRenderer(typeof(WebView), typeof(Xamarin.Forms.Platform.iOS.WkWebViewRenderer))]

注:在iOS上,WkWebViewRenderer具有接受WkWebViewConfiguration參數的構造函數重載,這使渲染器可以在創建時進行配置。

默認情況下,Android上的WebView與內置瀏覽器的速度差不多。

UWP WebView使用Microsoft Edge渲染引擎,台式機和平板電腦設備應具有與使用Edge瀏覽器本身相同的性能。

權限

為了使WebView正常工作,必須確保為每個平台都設置了權限。 請注意,在某些平台上,WebView將在調試模式下運行,但在為發布而構建時則無法運行。 這是因為在調試模式下,Visual Studio for Mac默認設置了某些權限(如Android上的Internet訪問權限)。

  • UWP –顯示網絡內容時需要Internet(客戶端和服務器)功能。
  • Android –僅在顯示網絡內容時才需要INTERNET,本地內容不需要特殊權限。
  • iOS –不需要特殊權限。

布局

與大多數其他Xamarin.Forms視圖不同,WebView要求在包含在StackLayout或RelativeLayout中時指定HeightRequest和WidthRequest,如果您未能指定這些屬性,則WebView將不會呈現。

具有WidthRequest和HeightRequest的StackLayout:

<StackLayout>
    <Label Text="test" />
    <WebView Source="http://www.xamarin.com/"
        HeightRequest="1000"
        WidthRequest="1000" />
</StackLayout>

調用JavaScript

WebView包括從C#調用JavaScript函數並將任何結果返回到調用C#代碼的功能,這是通過WebView.EvaluateJavaScriptAsync方法完成的,該示例在WebView示例的以下示例中顯示:

var numberEntry = new Entry { Text = "5" };
var resultLabel = new Label();
var webView = new WebView();
...

int number = int.Parse(numberEntry.Text);
string result = await webView.EvaluateJavaScriptAsync($"factorial({number})");
resultLabel.Text = $"Factorial of {number} is {result}.";

WebView.EvaluateJavaScriptAsync方法評估指定為參數的JavaScript,並以字符串形式返回任何結果。 在此示例中,調用了階乘JavaScript函數,該函數返回數字的階乘。 此JavaScript函數在WebView加載的本地HTML文件中定義,並在以下示例中顯示:

<html>
<body>
<script type="text/javascript">
function factorial(num) {
        if (num === 0 || num === 1)
            return 1;
        for (var i = num - 1; i >= 1; i--) {
            num *= i;
        }
        return num;
}
</script>
</body>
</html>

UIWebView棄用和App Store拒絕(ITMS-90809)

  從2020年4月開始,Apple將拒絕仍使用不推薦使用的UIWebView API的應用程序。雖然Xamarin.Forms已默認切換為WKWebView,但Xamarin.Forms二進制文件中仍舊有對舊版SDK的引用。當前的iOS鏈接器行為不會消除此問題,因此,當您提交到App Store時,不贊成使用的UIWebView API仍將在您的應用程序中被引用。

鏈接器的預覽版本可用於解決此問題。要啟用預覽,您將需要為鏈接器提供一個附加參數--optimize = experimental-xforms-product-type。

要實現此目的的先決條件是:

  • Xamarin.Forms 4.5或更高版本。如果您的應用程序使用Material Visual,則需要Xamarin.Forms 4.6或更高版本。
  • Xamarin.iOS 13.10.0.17或更高版本。在Visual Studio中檢查您的Xamarin.iOS版本。 Xamarin.iOS的此版本包含在Visual Studio for Mac 8.4.1和Visual Studio 16.4.3中。
  • 刪除對UIWebView的引用。您的代碼不應包含對UIWebView的任何引用或使用UIWebView的任何類。

有關檢測和刪除UIWebView引用的更多信息,請參見UIWebView棄用

配置鏈接器

請對鏈接器執行以下步驟,以刪除UIWebView引用:

1、打開iOS項目屬性–右鍵單擊您的iOS項目,然后選擇“屬性”。
2、導航到“ iOS build”部分-選擇“ iOS build”部分。
3、更新其他mtouch參數–在其他mtouch參數中,添加此標志--optimize = experimental-xforms-product-type(除了其中可能已有的任何值之外)。注意:此標志與“鏈接器行為”設置為“僅SDK”或“全部鏈接”一起使用。如果出於任何原因在將“鏈接器行為”設置為“全部”時看到錯誤,則很可能是應用程序代碼或第三方庫中存在鏈接器不安全的問題。有關鏈接器的更多信息,請參見鏈接Xamarin.iOS Apps。
4、更新所有構建配置–使用窗口頂部的“配置和平台”列表來更新所有構建配置。要更新的最重要配置是Release / iPhone配置,因為該配置通常用於創建App Store提交的構建。

現在,當您創建一個新的(release)版本並將其提交到App Store時,應該不存在有關已棄用API的警告。

問題

1、URL地址 問題

在ios上,若url地址有誤(兩個斜杠),例如:https://www.cnblogs.com//liqingwen/p/6218994.html

則會報錯:NSURLConnection finished with error - code -1003

導致打不開網頁

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM